home *** CD-ROM | disk | FTP | other *** search
/ Chip 2000 May / chip-cd_2000_05.zip / 05 / aktualnosci / shareware / euphoria / 0.DAT next >
Text File  |  2000-01-13  |  1MB  |  43,627 lines

  1.      * This file contains a big bundle of files. Run install.bat
  2.      * to unbundle and organize the files into subdirectories.
  3.  
  4. ASCII.BAT
  5. 30
  6. @echo off
  7. ex.exe ascii.ex
  8.  
  9. ASCII.EX
  10. 811
  11.     -- Display ASCII / code page chart
  12.     -- in 50 lines-per-screen mode  
  13.  
  14. include graphics.e
  15.  
  16. constant SCREEN = 1
  17.  
  18. if text_rows(50) then
  19. end if
  20.  
  21. text_color(WHITE)
  22. for i = 0 to 255 do
  23.     if remainder(i, 8) = 0 then 
  24.     puts(SCREEN, '\n')
  25.     text_color(RED)
  26.     if i = 128 and platform() = LINUX then
  27.         if getc(0) then
  28.         end if
  29.     end if
  30.     end if
  31.     if remainder(i, 16) = 0 then
  32.     puts(SCREEN, '\n')
  33.     text_color(WHITE)
  34.     end if
  35.     printf(SCREEN, "%3d: ", i)
  36.     if i = 0 then
  37.     puts(SCREEN, "NUL ")
  38.     elsif i = 9 then
  39.     puts(SCREEN, "TAB ")
  40.     elsif i = 10 then
  41.     puts(SCREEN, "LF  ")
  42.     elsif i = 13 then
  43.     puts(SCREEN, "CR  ")
  44.     else
  45.     puts(SCREEN, i)
  46.     puts(SCREEN, "   ")
  47.     end if
  48. end for
  49.  
  50. text_color(WHITE)
  51. puts(SCREEN, "\n\nPress Enter...")
  52. if atom(gets(0)) then
  53. end if
  54.  
  55. if graphics_mode(-1) then
  56. end if
  57.  
  58. BIN.DOC
  59. 1906
  60.    EUPHORIA\BIN
  61.  
  62.    This directory contains the Euphoria executables ex.exe and exw.exe, plus 
  63.    a number of utility programs written in Euphoria:
  64.  
  65.     ascii.ex     - prints a character chart from 0 to 255
  66.     cdguru.bat   - The Guru search engine applied to the current directory 
  67.                that you are in. Searches any kind of text files.
  68.     ed.ex        - the Euphoria editor
  69.     eprint.ex    - prints Euphoria or other files in two-column condensed
  70.                mode. Highlights syntax of Euphoria files.
  71.     guru.ex         - The Euphoria "Guru" search engine
  72.     install.ex   - The Euphoria install program. You've already installed
  73.                    Euphoria, so this is here just for educational purposes.
  74.                    Feel free to use it as a base for your own install
  75.                    programs.
  76.     key.ex         - shows the numeric key code for any key on the keyboard
  77.     lines.ex     - count lines and characters in a bunch of files
  78.     search.ex    - search files for a string-pattern
  79.     where.ex     - search for a file on your PATH
  80.  
  81.    Complete Edition only:
  82.     bind.bat     - shroud & bind a DOS32 Euphoria program to ex.exe to make 
  83.                a stand-alone .exe file
  84.     bindw.bat    - shroud & bind a WIN32 Euphoria program to exw.exe to
  85.                    make a stand-alone .exe file
  86.     shroud.bat   - source code shrouder, makes a shrouded .e or .ex file
  87.     bind.ex         - a shrouded and scrambled Euphoria program used by 
  88.                    shroud.bat and bind.bat
  89.        pdexw.exe    - Public Domain interpreter for binding
  90.        pdex.exe     - Public Domain interpreter for binding
  91.        
  92.    There are small .bat files for most of the .ex utilities, so you
  93.    don't have to type "ex ...",     e.g. just type "ascii" to turn run the
  94.    ascii.ex program.
  95.  
  96.    Many of these programs expect to be run from a command line interface.
  97.  
  98.    For more documentation, see the comments at the top of each file.
  99.    
  100. CDGURU.BAT
  101. 86
  102. @echo off
  103. rem Current directory "Guru"
  104. ex.exe guru.ex %1 %2 %3 %4 %5 %6 %7 %8 %9
  105.  
  106. ED.BAT
  107. 34
  108. @echo off
  109. ex.exe ed.ex %1 %2 %3
  110. ED.EX
  111. 60258
  112.     ----------------------------------------------------------
  113.     --       This Euphoria Editor was developed by          --
  114.     --            Rapid Deployment Software.                --
  115.     --                                                      --
  116.     -- Permission is freely granted to anyone to modify     --
  117.     -- and/or redistribute this editor (ed.ex, syncolor.e). --
  118.     ----------------------------------------------------------
  119.  
  120. -- This program can be run with:
  121. --     ex ed
  122. --     exu ed.ex
  123. -- or
  124. --     exw ed.ex (a bit slower, some control-key combinations aren't recognized,
  125. --                and Esc l doesn't work in all cases)
  126.  
  127. -- How it Works:
  128. -- * Using gets(), ed reads and appends each line of text into a 2-d "buffer",
  129. --   i.e. a sequence of sequences where each (sub)sequence contains one line.
  130. -- * ed waits for you to press a key, and then fans out to one of many small
  131. --   routines that each perform one editing operation.
  132. -- * Each editing operation is responsible for updating the 2-d buffer variable
  133. --   containing the lines of text, and for updating the screen to reflect any
  134. --   changes. This code is typically fairly simple, but there can be a lot
  135. --   of special cases to worry about.
  136. -- * Finally, ed writes back each line, using puts()
  137. -- * How multiple-windows works: When you switch to a new window, all the 
  138. --   variables associated with the current window are bundled together and 
  139. --   saved in a sequence, along with the 2-d text buffer for that window.
  140. --   When you switch back, all of these state variables, plus the 2-d text
  141. --   buffer variable for that window are restored. Most of the code in ed is 
  142. --   not even "aware" that there can be multiple-windows.
  143.  
  144. without type_check -- makes it a bit faster
  145.  
  146. include graphics.e
  147. include get.e
  148. include file.e
  149. include wildcard.e
  150.  
  151. constant TRUE = 1,
  152.      FALSE = 0
  153.  
  154. -- special input characters
  155. constant CONTROL_B = 2,
  156.      CONTROL_C = 3,
  157.      CONTROL_D = 4,   -- alternate key for line-delete  
  158.      CONTROL_L = 12,
  159.      CONTROL_P = 16,  -- alternate key for PAGE-DOWN in Linux.
  160.               -- DOS uses this key for printing or something.
  161.      CONTROL_R = 18,
  162.      CONTROL_T = 20,
  163.      CONTROL_U = 21   -- alternate key for PAGE-UP in Linux
  164.  
  165. integer ESCAPE, CR, BS, HOME, END, CONTROL_HOME, CONTROL_END,
  166.     PAGE_UP, PAGE_DOWN, INSERT, 
  167.     DELETE, XDELETE, ARROW_LEFT, ARROW_RIGHT,
  168.     CONTROL_ARROW_LEFT, CONTROL_ARROW_RIGHT, ARROW_UP, ARROW_DOWN,
  169.     F1, F10, F11, F12, 
  170.     CONTROL_DELETE  -- key for line-delete 
  171.             -- (not available on some systems)
  172. sequence delete_cmd, compare_cmd
  173. integer SLASH
  174. integer SAFE_CHAR -- minimum ASCII char that's safe to display
  175.      
  176. if platform() = LINUX then
  177.     SLASH = '/'
  178.     SAFE_CHAR = 32
  179.     delete_cmd = "rm "
  180.     compare_cmd = "diff "
  181.     ESCAPE = 27
  182.     CR = 10
  183.     BS = 263
  184.     HOME = 262 
  185.     END = 360 
  186.     CONTROL_HOME = CONTROL_T -- (top)
  187.     CONTROL_END = CONTROL_B  -- (bottom)
  188.     PAGE_UP = 339 
  189.     PAGE_DOWN = 338 
  190.     INSERT = 331
  191.     DELETE = 330
  192.     XDELETE = 127 -- use in xterm
  193.     ARROW_LEFT = 260
  194.     ARROW_RIGHT = 261
  195.     CONTROL_ARROW_LEFT = CONTROL_L  -- (left)
  196.     CONTROL_ARROW_RIGHT = CONTROL_R -- (right)
  197.     ARROW_UP = 259
  198.     ARROW_DOWN = 258
  199.     F1 = 265
  200.     F10 = 274
  201.     F11 = 275
  202.     F12 = 276
  203.     CONTROL_DELETE = DELETE -- key for line-delete 
  204.                 -- (not available on some systems)
  205. else
  206.     -- DOS/Windows
  207.     SLASH = '\\'
  208.     SAFE_CHAR = 14
  209.     delete_cmd = "del "
  210.     compare_cmd = "fc /T "
  211.     ESCAPE = 27
  212.     CR = 13
  213.     BS = 8
  214.     HOME = 327
  215.     END = 335
  216.     CONTROL_HOME = 375
  217.     CONTROL_END = 373
  218.     PAGE_UP = 329
  219.     PAGE_DOWN = 337
  220.     INSERT = 338
  221.     DELETE = 339
  222.     XDELETE = -999 -- never
  223.     ARROW_LEFT = 331
  224.     ARROW_RIGHT = 333
  225.     CONTROL_ARROW_LEFT = 371
  226.     CONTROL_ARROW_RIGHT = 372
  227.     ARROW_UP = 328
  228.     ARROW_DOWN = 336
  229.     F1 = 315
  230.     F10 = 324
  231.     F11 = 389
  232.     F12 = 390
  233.     CONTROL_DELETE = 403 -- key for line-delete 
  234.              -- (not available on some systems)
  235. end if
  236.  
  237.  
  238.  
  239. -------- START OF USER-MODIFIABLE PARAMETERS ---------------------------------- 
  240.  
  241. -- make your own specialized macro command(s):
  242. constant CUSTOM_KEY = F12
  243. constant CUSTOM_KEYSTROKES = HOME & "-- " & ARROW_DOWN
  244.  
  245. constant PROG_INDENT = 4  -- tab width for editing program source files
  246.               -- (tab width is 8 for other files)
  247. -- Euphoria files:
  248. constant E_FILES = {".e", ".ex", ".ew", ".exw", ".eu", ".exu", ".pro"}  
  249. -- program indent files:
  250. constant PROG_FILES = E_FILES & {".c", ".h", ".bas"} 
  251.  
  252. constant WANT_COLOR_SYNTAX  = TRUE -- FALSE if you don't want
  253.                    -- color syntax highlighting
  254.  
  255. constant WANT_AUTO_COMPLETE = TRUE -- FALSE if you don't want 
  256.                    -- auto-completion of Euphoria statements
  257.  
  258. constant HOT_KEYS = TRUE  -- FALSE if you want to hit Enter after each command
  259.  
  260. -- cursor style: 
  261. constant ED_CURSOR = THICK_UNDERLINE_CURSOR
  262.              -- UNDERLINE_CURSOR
  263.              -- HALF_BLOCK_CURSOR
  264.              -- BLOCK_CURSOR
  265.            
  266. -- number of lines on screen: (25,28,43,50)
  267. constant INITIAL_LINES = 25,  -- when editor starts up
  268.      FINAL_LINES = 25     -- when editor is finished
  269.  
  270. -- colors
  271. constant TOP_LINE_TEXT_COLOR = BLACK,
  272.      TOP_LINE_BACK_COLOR = BROWN, 
  273.      TOP_LINE_DIM_COLOR = BLUE,
  274.      BACKGROUND_COLOR = WHITE
  275.  
  276. -- colors needed by syncolor.e:
  277. -- Adjust to suit your monitor and your taste.
  278. global constant NORMAL_COLOR = BLACK,   -- GRAY might look better
  279.         COMMENT_COLOR = RED,
  280.         KEYWORD_COLOR = BLUE,
  281.         BUILTIN_COLOR = MAGENTA,
  282.         STRING_COLOR = GREEN,   -- BROWN might look better
  283.         BRACKET_COLOR = {NORMAL_COLOR, YELLOW, BRIGHT_WHITE, 
  284.                  BRIGHT_BLUE, BRIGHT_RED, BRIGHT_CYAN, 
  285.                  BRIGHT_GREEN}
  286.  
  287. -- number of characters to shift left<->right when you move beyond column 80
  288. constant SHIFT = 4   -- 1..78 should be ok
  289.  
  290. -- name of edit buffer temp file for Esc m command
  291. constant TEMPFILE = "editbuff.tmp" 
  292.  
  293. -------- END OF USER-MODIFIABLE PARAMETERS ------------------------------------
  294.  
  295.  
  296. -- Special keys that we can handle. Some are duplicates.
  297. -- If you add more, you should list them here:
  298. constant SPECIAL_KEYS = {ESCAPE, BS, DELETE, XDELETE, PAGE_UP, PAGE_DOWN,
  299.              CONTROL_P, CONTROL_U, CONTROL_T, CONTROL_B,
  300.              CONTROL_R, CONTROL_L,
  301.              INSERT, CONTROL_DELETE, 
  302.              CONTROL_D, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, 
  303.              ARROW_DOWN, CONTROL_ARROW_LEFT, CONTROL_ARROW_RIGHT,
  304.              HOME, END, CONTROL_HOME, CONTROL_END,
  305.              F1, F1+1, F1+2, F1+3, F1+4, F1+5,
  306.              F1+6, F1+7, F1+8, F10, CUSTOM_KEY}
  307.  
  308. -- output device:
  309. constant SCREEN = 1
  310.  
  311. constant CONTROL_CHAR = 254 -- change funny control chars to this
  312.  
  313. constant STANDARD_TAB_WIDTH = 8
  314.  
  315. constant MAX_WINDOWS = 10 -- F1..F10
  316.  
  317. type boolean(integer x)
  318.     return x = TRUE or x = FALSE
  319. end type
  320.  
  321. type natural(integer x)
  322.     return x >= 0
  323. end type
  324.  
  325. type positive_int(integer x)
  326.     return x >= 1
  327. end type
  328.  
  329. sequence buffer -- In-memory buffer where the file is manipulated.
  330. -- This is a sequence where each element is a sequence
  331. -- containing one line of text. Each line of text ends with '\n'
  332.  
  333. positive_int screen_length  -- number of lines on physical screen
  334. positive_int screen_width
  335.  
  336. global sequence BLANK_LINE 
  337.  
  338. positive_int window_base    -- location of first line of current window 
  339.                 -- (status line)
  340. window_base = 1
  341. positive_int window_length  -- number of lines of text in current window
  342.  
  343. sequence window_list -- state info for all windows
  344. window_list = {0}
  345.  
  346. sequence buffer_list -- all buffers
  347. buffer_list = {}
  348.  
  349. type window_id(integer x)
  350.     return x >= 1 and x <= length(window_list)
  351. end type
  352.  
  353. type buffer_id(integer x)
  354.     return x >= 0 and x <= length(buffer_list)
  355. end type
  356.  
  357. type window_line(integer x)
  358. -- a valid line in the current window
  359.     return x >= 1 and x <= window_length
  360. end type
  361.  
  362. type screen_col(integer x)
  363. -- a valid column on the screen
  364.     return x >= 1 
  365. end type
  366.  
  367. type buffer_line(integer x)
  368. -- a valid buffer line
  369.     return (x >= 1 and x <= length(buffer)) or x = 1
  370. end type
  371.  
  372. type char(integer x)
  373. -- a character (including special key codes)
  374.     return x >= 0 and x <= 511
  375. end type
  376.  
  377. type extended_char(integer x)
  378.     return char(x) or x = -1
  379. end type
  380.  
  381. type file_number(integer x)
  382.     return x >= -1
  383. end type
  384.  
  385. sequence file_name   -- name of the file that we are editing
  386.  
  387. -- These are the critical state variables that all editing operations
  388. -- must update:
  389. buffer_line  b_line  -- current line in buffer
  390. positive_int b_col   -- current character within line in buffer
  391. window_line  s_line  -- line on screen corresponding to b_line
  392. screen_col   s_col   -- column on screen corresponding to b_col
  393. natural s_shift      -- how much the screen has been shifted (for >80)
  394. s_shift = 0
  395.  
  396. boolean stop         -- indicates when to stop processing current buffer
  397.  
  398. sequence kill_buffer -- kill buffer of deleted lines or characters
  399. kill_buffer = {}
  400.  
  401. boolean adding_to_kill  -- TRUE if still accumulating deleted lines/chars
  402.  
  403. boolean multi_color     -- use colors for keywords etc.
  404. boolean auto_complete   -- perform auto completion of statements
  405. boolean dot_e           -- TRUE if this is a .e/.ex file
  406. boolean modified        -- TRUE if file has been modified
  407.  
  408. boolean editbuff        -- TRUE if temp file exists (Esc m)
  409. editbuff = FALSE
  410.  
  411. atom buffer_version,    -- version of buffer contents
  412.      my_buffer_version  -- last version used by current window
  413.  
  414. boolean control_chars,  -- binary file - view but don't save
  415.     cr_removed      -- Linux: CR's were removed from DOS file (CR-LF)
  416.  
  417. natural start_line, start_col
  418.  
  419. sequence error_message
  420.  
  421. sequence file_history, command_history, search_history, replace_history
  422. file_history = {}
  423. command_history = {}
  424. search_history = {}
  425. replace_history = {}
  426.  
  427. sequence config -- video configuration
  428.  
  429. window_id window_number -- current active window
  430. window_number = 1
  431.  
  432. buffer_id buffer_number -- current active buffer
  433. buffer_number = 0
  434.  
  435. sequence key_queue -- queue of input characters forced by ed
  436. key_queue = {}
  437.  
  438. procedure delay(atom n)
  439. -- an n second pause while a message is on the screen
  440.     atom t
  441.  
  442.     t = time()
  443.     while time() < t + n do
  444.     end while
  445. end procedure
  446.  
  447. procedure set_modified()
  448. -- buffer differs from file
  449.     modified = TRUE
  450.     cursor(NO_CURSOR) -- hide cursor while we update the screen
  451.     buffer_version += 1
  452. end procedure
  453.  
  454. procedure clear_modified()
  455. -- buffer is now same as file
  456.     modified = FALSE
  457. end procedure
  458.  
  459.  
  460. natural edit_tab_width 
  461.  
  462. function tab(natural tab_width, positive_int pos)
  463. -- compute new column position after a tab
  464.     return (floor((pos - 1) / tab_width) + 1) * tab_width + 1
  465. end function
  466.  
  467. function expand_tabs(natural tab_width, sequence line)
  468. -- replace tabs by blanks in a line of text
  469.     natural tab_pos, column, ntabs
  470.  
  471.     column = 1
  472.     while TRUE do
  473.     tab_pos = find('\t', line[column..length(line)])
  474.     if tab_pos = 0 then
  475.         -- no more tabs
  476.         return line
  477.     else
  478.         tab_pos += column - 1
  479.     end if
  480.     column = tab(tab_width, tab_pos)
  481.     ntabs = 1
  482.     while line[tab_pos+ntabs] = '\t' do
  483.         ntabs += 1
  484.         column += tab_width
  485.     end while
  486.     -- replace consecutive tabs by blanks
  487.     line = line[1..tab_pos-1] & 
  488.            repeat(' ', column - tab_pos) &
  489.            line[tab_pos+ntabs..length(line)]            
  490.     end while
  491. end function
  492.  
  493. function indent_tabs(natural tab_width, sequence line)
  494. -- replace leading blanks of a line with tabs
  495.     natural i, blanks
  496.  
  497.     if length(line) < tab_width then
  498.     return line
  499.     end if
  500.     i = 1
  501.     while line[i] = ' ' do
  502.     i += 1
  503.     end while    
  504.     blanks = i - 1    
  505.     return repeat('\t', floor(blanks / tab_width)) & 
  506.        BLANK_LINE[1..remainder(blanks, tab_width)] &
  507.        line[i..length(line)]
  508. end function
  509.  
  510. function convert_tabs(natural old_width, natural new_width, sequence line)
  511. -- retabulate a line for a new tab size
  512.     if old_width = new_width then
  513.     return line
  514.     end if
  515.     return indent_tabs(new_width, expand_tabs(old_width, line))
  516. end function
  517.  
  518. -- color display of lines
  519. include syncolor.e
  520.  
  521. procedure reverse_video()
  522. -- start inverse video
  523.     text_color(TOP_LINE_TEXT_COLOR)
  524.     bk_color(TOP_LINE_BACK_COLOR)
  525. end procedure
  526.  
  527. procedure normal_video()
  528. -- end inverse video
  529.     text_color(NORMAL_COLOR)
  530.     bk_color(BACKGROUND_COLOR)
  531. end procedure
  532.  
  533. procedure ClearLine(window_line sline)
  534. -- clear the current line on screen
  535.     scroll(1, window_base + sline, window_base + sline)
  536. end procedure
  537.  
  538. procedure ClearWindow()
  539. -- clear the current window
  540.     scroll(window_length, window_base+1, window_base+window_length)
  541. end procedure
  542.  
  543. procedure ScrollUp(positive_int top, positive_int bottom)
  544. -- move text up one line on screen
  545.     scroll(+1, window_base + top, window_base + bottom)
  546. end procedure
  547.  
  548. procedure ScrollDown(positive_int top, positive_int bottom)
  549. -- move text down one line on screen
  550.     scroll(-1, window_base + top, window_base + bottom)
  551. end procedure
  552.  
  553. procedure set_absolute_position(natural window_line, positive_int column)
  554. -- move cursor to a line and an absolute (non-shifted) column within
  555. -- the current window
  556.     position(window_base + window_line, column)
  557. end procedure
  558.  
  559. procedure DisplayLine(buffer_line bline, window_line sline, boolean all_clear)
  560. -- display a buffer line on a given line on the screen
  561.     sequence this_line, color_line, text
  562.     natural last, last_pos, color, len
  563.     
  564.     this_line = expand_tabs(edit_tab_width, buffer[bline])
  565.     last = length(this_line) - 1
  566.     set_absolute_position(sline, 1)
  567.     if multi_color then
  568.     -- color display
  569.     color_line = SyntaxColor(this_line)
  570.     last_pos = 0
  571.     
  572.     for i = 1 to length(color_line) do
  573.         -- display the next colored text segment
  574.         color = color_line[i][1]
  575.         text = color_line[i][2]
  576.         len = length(text)
  577.         if last_pos >= s_shift then
  578.         text_color(color)
  579.         puts(SCREEN, text)
  580.         elsif last_pos+len > s_shift then
  581.         -- partly left-of-screen
  582.         text_color(color)
  583.         puts(SCREEN, text[1+(s_shift-last_pos)..len])
  584.         last_pos += len
  585.         else
  586.         -- left-of-screen
  587.         last_pos += len
  588.         end if
  589.     end for
  590.     else
  591.     -- monochrome display
  592.     if last > s_shift then
  593.         puts(SCREEN, this_line[1+s_shift..last])
  594.     end if
  595.     end if
  596.     if last-s_shift > screen_width then
  597.     -- line extends beyond right margin 
  598.     set_absolute_position(sline, screen_width)
  599.     text_color(BACKGROUND_COLOR)
  600.     bk_color(NORMAL_COLOR)
  601.     puts(SCREEN, this_line[screen_width+s_shift])
  602.     normal_video()
  603.     elsif not all_clear then
  604.     puts(SCREEN, BLANK_LINE)
  605.     end if
  606. end procedure
  607.  
  608. without warning
  609. procedure DisplayWindow(positive_int bline, window_line sline)
  610. -- print a series of buffer lines, starting at sline on screen
  611. -- and continue until the end of screen, or end of buffer
  612.     boolean all_clear
  613.     
  614.     if sline = 1 then 
  615.     ClearWindow()
  616.     all_clear = TRUE
  617.     else
  618.     all_clear = FALSE
  619.     end if
  620.  
  621.     for b = bline to length(buffer) do
  622.     DisplayLine(b, sline, all_clear)
  623.     if sline = window_length then
  624.         return
  625.     else
  626.         sline += 1
  627.     end if
  628.     end for
  629.     -- blank any remaining screen lines after end of file
  630.     for s = sline to window_length do
  631.     ClearLine(s)
  632.     end for
  633. end procedure
  634. with warning
  635.  
  636. procedure set_position(natural window_line, positive_int column)
  637. -- Move cursor to a logical screen position within the window.
  638. -- The window will be shifted left<->right if necessary.
  639. -- window_line 0 is status line, window_line 1 is first line of text
  640.     natural s
  641.     
  642.     if window_line = 0 then
  643.     -- status line
  644.     position(window_base + window_line, column)
  645.     else
  646.     s = s_shift
  647.     while column-s_shift > screen_width do
  648.         s_shift += SHIFT
  649.     end while
  650.     while column-s_shift < 1 do
  651.         s_shift -= SHIFT
  652.     end while
  653.     if s_shift != s then
  654.         -- display shifted window
  655.         DisplayWindow(b_line - s_line + 1, 1)
  656.     end if
  657.     position(window_base + window_line, column-s_shift)
  658.     end if
  659. end procedure
  660.  
  661. without warning
  662. function clean(sequence line)
  663. -- replace control characters with a graphics character
  664. -- Linux: replace CR-LF with LF (for now)
  665.     integer c
  666.     
  667.     for i = 1 to length(line) do
  668.     c = line[i]
  669.     if c < SAFE_CHAR and c != '\n' and c != '\t' then
  670.         if c != '\r' or platform() != LINUX then
  671.         line[i] = CONTROL_CHAR  -- replace with displayable character
  672.         control_chars = TRUE
  673.         end if
  674.     end if
  675.     end for
  676.     if line[length(line)] != '\n' then
  677.     line &= '\n'
  678.     end if
  679.     if platform() = LINUX and 
  680.        length(line) > 1 and 
  681.        line[length(line)-1] = '\r' then
  682.        -- DOS file: remove CR
  683.        cr_removed = TRUE
  684.        line = line[1..length(line)-2] & '\n'
  685.     end if
  686.     return line
  687. end function
  688. with warning
  689.  
  690. function add_line(file_number file_no)
  691. -- add a new line to the buffer
  692.     object line
  693.  
  694.     line = gets(file_no)
  695.     
  696.     if atom(line) then
  697.     -- end of file
  698.     return FALSE 
  699.     end if
  700.     
  701.     line = convert_tabs(STANDARD_TAB_WIDTH, edit_tab_width, clean(line))
  702.     buffer = append(buffer, line)
  703.     return TRUE
  704. end function
  705.  
  706. procedure new_buffer()
  707. -- make room for a new (empty) buffer
  708.     buffer_list &= 0 -- place holder for new buffer
  709.     buffer_number = length(buffer_list) 
  710.     buffer = {}
  711. end procedure
  712.  
  713. procedure read_file(file_number file_no)
  714. -- read the entire file into buffer variable
  715.     
  716.     -- read and immediately display the first screen-full
  717.     for i = 1 to window_length do
  718.     if not add_line(file_no) then
  719.         exit
  720.     end if
  721.     end for
  722.     DisplayWindow(1, 1)
  723.  
  724.     -- read the rest
  725.     while add_line(file_no) do
  726.     end while
  727.  
  728. end procedure
  729.  
  730. procedure set_top_line(sequence message)
  731. -- print message on top line
  732.     set_position(0, 1)
  733.     reverse_video()
  734.     puts(SCREEN, message & BLANK_LINE)
  735.     set_position(0, length(message)+1)
  736. end procedure
  737.  
  738. procedure arrow_right()
  739. -- action for right arrow key
  740.  
  741.     if b_col < length(buffer[b_line]) then
  742.     if buffer[b_line][b_col] = '\t' then
  743.         s_col = tab(edit_tab_width, s_col)
  744.     else
  745.         s_col += 1
  746.     end if
  747.     b_col += 1
  748.     end if
  749. end procedure
  750.  
  751. procedure arrow_left()
  752. -- action for left arrow key
  753.  
  754.     positive_int old_b_col
  755.  
  756.     old_b_col = b_col
  757.     b_col = 1
  758.     s_col = 1
  759.     for i = 1 to old_b_col - 2 do
  760.     arrow_right()
  761.     end for
  762. end procedure
  763.     
  764. procedure skip_white()
  765. -- set cursor to first non-whitespace in line    
  766.     positive_int temp_col
  767.     
  768.     while find(buffer[b_line][b_col], " \t") do
  769.     temp_col = s_col
  770.     arrow_right()
  771.     if s_col = temp_col then
  772.         return -- can't move any further right
  773.     end if
  774.     end while
  775. end procedure
  776.  
  777. procedure goto_line(integer new_line, integer new_col)
  778. -- move to a specified line and column
  779. -- refresh screen if line is 0
  780.     integer new_s_line
  781.     boolean refresh
  782.  
  783.     if length(buffer) = 0 then
  784.     ClearWindow()
  785.     s_line = 1
  786.     s_col = 1
  787.     return
  788.     end if
  789.     if new_line = 0 then
  790.     new_line = b_line
  791.     refresh = TRUE
  792.     else
  793.     refresh = FALSE
  794.     end if
  795.     if new_line < 1 then
  796.     new_line = 1
  797.     elsif new_line > length(buffer) then
  798.     new_line = length(buffer)
  799.     end if
  800.     new_s_line = new_line - b_line + s_line
  801.     b_line = new_line
  802.     if not refresh and window_line(new_s_line) then
  803.     -- new line is on the screen
  804.     s_line = new_s_line
  805.     else
  806.     -- new line is off the screen, or refreshing
  807.     s_line = floor((window_length+1)/2)
  808.     if s_line > b_line or length(buffer) < window_length then
  809.         s_line = b_line
  810.     elsif b_line > length(buffer) - window_length + s_line then
  811.         s_line = window_length - (length(buffer) - b_line)
  812.     end if
  813.     DisplayWindow(b_line - s_line + 1, 1)
  814.     end if
  815.     b_col = 1
  816.     s_col = 1
  817.     for i = 1 to new_col-1 do
  818.     arrow_right()
  819.     end for
  820.     set_position(s_line, s_col)
  821. end procedure
  822.  
  823. function plain_text(char c)
  824. -- defines text for next_word, previous_word 
  825.     return (c >= '0' and c <= '9') or
  826.        (c >= 'A' and c <= 'Z') or
  827.        (c >= 'a' and c <= 'z') or
  828.        c = '_'
  829. end function
  830.  
  831. procedure next_word()
  832. -- move to start of next word in line
  833.     char c
  834.     positive_int col
  835.     
  836.     -- skip plain text
  837.     col = b_col
  838.     while TRUE do
  839.     c = buffer[b_line][col]
  840.     if not plain_text(c) then
  841.         exit
  842.     end if
  843.     col += 1
  844.     end while
  845.     
  846.     -- skip white-space and punctuation
  847.     while c != '\n' do
  848.     c = buffer[b_line][col]
  849.     if plain_text(c) then
  850.         exit
  851.     end if
  852.     col += 1
  853.     end while
  854.     goto_line(b_line, col)
  855. end procedure
  856.  
  857. procedure previous_word()
  858. -- move to start of previous word in line    
  859.     char c
  860.     natural col
  861.     
  862.     -- skip white-space & punctuation
  863.     col = b_col - 1
  864.     while col > 1 do
  865.     c = buffer[b_line][col]
  866.     if plain_text(c) then
  867.         exit
  868.     end if
  869.     col -= 1
  870.     end while
  871.  
  872.     -- skip plain text
  873.     while col > 1 do
  874.     c = buffer[b_line][col-1]
  875.     if not plain_text(c) then
  876.         exit
  877.     end if
  878.     col -= 1
  879.     end while
  880.  
  881.     goto_line(b_line, col)
  882. end procedure
  883.  
  884.  
  885. procedure arrow_up()
  886. -- action for up arrow key
  887.  
  888.     b_col = 1
  889.     s_col = 1
  890.     if b_line > 1 then
  891.     b_line -= 1
  892.     if s_line > 1 then
  893.         s_line -= 1
  894.     else
  895.         -- move all lines down, display new line at top
  896.         ScrollDown(1, window_length)
  897.         DisplayLine(b_line, 1, TRUE)
  898.         set_position(1, 1)
  899.     end if
  900.     skip_white()
  901.     end if
  902. end procedure
  903.  
  904. procedure arrow_down()
  905. -- action for down arrow key
  906.     b_col = 1
  907.     s_col = 1
  908.     if b_line < length(buffer) then
  909.     b_line += 1
  910.     if s_line < window_length then
  911.         s_line += 1
  912.     else
  913.         -- move all lines up, display new line at bottom
  914.         ScrollUp(1, window_length)
  915.         DisplayLine(b_line, window_length, TRUE)
  916.     end if
  917.     skip_white()
  918.     end if
  919. end procedure
  920.  
  921. function numeric(sequence string)
  922. -- convert digit string to an integer
  923.     atom n
  924.  
  925.     n = 0
  926.     for i = 1 to length(string) do
  927.     if string[i] >= '0' and string[i] <= '9' then
  928.         n = n * 10 + string[i] - '0'
  929.         if not integer(n) then
  930.         return 0
  931.         end if
  932.     else
  933.         exit
  934.     end if
  935.     end for
  936.     return n
  937. end function
  938.  
  939. procedure page_down()
  940. -- action for page-down key
  941.     buffer_line prev_b_line
  942.  
  943.     if length(buffer) <= window_length then
  944.     return
  945.     end if
  946.     prev_b_line = b_line
  947.     b_col = 1
  948.     s_col = 1
  949.     if b_line + window_length + window_length - s_line <= length(buffer) then
  950.     b_line = b_line + window_length
  951.     else
  952.     b_line = length(buffer) - (window_length - s_line)
  953.     end if
  954.     if b_line != prev_b_line then
  955.     DisplayWindow(b_line - s_line + 1, 1)
  956.     end if
  957. end procedure
  958.  
  959. procedure page_up()
  960. -- action for page-up key
  961.     buffer_line prev_b_line
  962.  
  963.     if length(buffer) <= window_length then
  964.     return
  965.     end if
  966.     prev_b_line = b_line
  967.     b_col = 1
  968.     s_col = 1
  969.     if b_line - window_length >= s_line then
  970.     b_line = b_line - window_length
  971.     else
  972.     b_line = s_line
  973.     end if
  974.     if b_line != prev_b_line then
  975.     DisplayWindow(b_line - s_line + 1, 1)
  976.     end if
  977. end procedure
  978.  
  979. procedure set_f_line(natural w, sequence comment)
  980. -- show F-key & file_name
  981.     sequence f_key, text
  982.     
  983.     if length(window_list) = 1 then
  984.     f_key = ""
  985.     elsif w = 10 then
  986.     f_key = "F10: "
  987.     else
  988.     f_key = 'F' & ('0' + w) & ": "
  989.     end if
  990.     set_top_line("")
  991.     puts(SCREEN, ' ' & f_key & file_name & comment)
  992.     text = "Esc for commands"
  993.     set_position(0, screen_width - length(text))
  994.     puts(SCREEN, text)
  995. end procedure
  996.  
  997. constant W_BUFFER_NUMBER = 1,
  998.      W_MY_BUFFER_VERSION = 2,
  999.      W_WINDOW_BASE = 3,
  1000.      W_WINDOW_LENGTH = 4,
  1001.      W_B_LINE = 11
  1002.  
  1003. procedure save_state()
  1004. -- save current state variables for a window
  1005.     window_list[window_number] = {buffer_number, buffer_version, window_base, 
  1006.                   window_length, auto_complete, multi_color, 
  1007.                   dot_e, control_chars, cr_removed, file_name, 
  1008.                   b_line, b_col, s_line, s_col, s_shift, 
  1009.                   edit_tab_width}
  1010.     buffer_list[buffer_number] = {buffer, modified, buffer_version}
  1011. end procedure
  1012.  
  1013. procedure restore_state(window_id w)
  1014. -- restore state variables for a window
  1015.     sequence state
  1016.     sequence buffer_info
  1017.  
  1018.     -- set up new buffer
  1019.     state = window_list[w]
  1020.     window_number = w
  1021.     buffer_number =  state[W_BUFFER_NUMBER]
  1022.     buffer_info = buffer_list[buffer_number]
  1023.     buffer = buffer_info[1]
  1024.     modified = buffer_info[2]
  1025.     buffer_version = buffer_info[3]
  1026.     buffer_list[buffer_number] = 0 -- save space
  1027.     
  1028.     -- restore other variables
  1029.     my_buffer_version = state[2]
  1030.     window_base = state[3]
  1031.     window_length = state[4]
  1032.     auto_complete = state[5]
  1033.     multi_color = state[6]
  1034.     dot_e = state[7]
  1035.     control_chars = state[8]
  1036.     cr_removed = state[9]
  1037.     file_name = state[10]
  1038.     edit_tab_width = state[16]
  1039.     set_f_line(w, "")
  1040.     normal_video()
  1041.     if buffer_version != my_buffer_version then
  1042.     -- buffer has changed since we were last in this window
  1043.     -- or window size has changed
  1044.     if state[W_B_LINE] > length(buffer) then
  1045.         if length(buffer) = 0 then
  1046.         b_line = 1
  1047.         else
  1048.         b_line = length(buffer)
  1049.         end if
  1050.     else
  1051.         b_line = state[W_B_LINE]
  1052.     end if
  1053.     s_shift = 0
  1054.     goto_line(0, 1)
  1055.     else
  1056.     b_line = state[W_B_LINE]
  1057.     b_col = state[12]
  1058.     s_line = state[13]
  1059.     s_col = state[14]
  1060.     s_shift = state[15]
  1061.     set_position(s_line, s_col)
  1062.     end if
  1063. end procedure
  1064.  
  1065. procedure refresh_other_windows(positive_int w)
  1066. -- redisplay all windows except w
  1067.     
  1068.     normal_video()
  1069.     for i = 1 to length(window_list) do
  1070.     if i != w then
  1071.         restore_state(i)
  1072.         set_f_line(i, "")
  1073.         normal_video()
  1074.         goto_line(0, b_col)
  1075.         save_state()
  1076.     end if
  1077.     end for
  1078. end procedure
  1079.  
  1080. procedure set_window_size()
  1081. -- set sizes for windows
  1082.     natural nwindows, lines, base, size
  1083.     
  1084.     nwindows = length(window_list)
  1085.     lines = screen_length - nwindows
  1086.     base = 1
  1087.     for i = 1 to length(window_list) do
  1088.     size = floor(lines / nwindows)
  1089.     window_list[i][W_WINDOW_BASE] = base
  1090.     window_list[i][W_WINDOW_LENGTH] = size
  1091.     window_list[i][W_MY_BUFFER_VERSION] = -1 -- force redisplay
  1092.     base += size + 1
  1093.     nwindows -= 1
  1094.     lines -= size
  1095.     end for
  1096. end procedure
  1097.  
  1098. procedure clone_window()
  1099. -- set up a new window that is a clone of the current window
  1100. -- save state of current window
  1101.     window_id w
  1102.     
  1103.     if length(window_list) >= MAX_WINDOWS then
  1104.     return
  1105.     end if
  1106.     save_state()
  1107.     -- create a place for new window
  1108.     window_list = window_list[1..window_number] & 
  1109.           {window_list[window_number]} &  -- the new clone window
  1110.           window_list[window_number+1..length(window_list)]
  1111.     w = window_number + 1
  1112.     set_window_size()
  1113.     refresh_other_windows(w)
  1114.     restore_state(w) 
  1115. end procedure
  1116.  
  1117. procedure switch_window(integer new_window_number)
  1118. -- switch context to a new window on the screen
  1119.     
  1120.     if new_window_number != window_number then
  1121.     save_state()
  1122.     restore_state(new_window_number)
  1123.     end if
  1124. end procedure
  1125.  
  1126. function delete_window()
  1127. -- delete the current window    
  1128.     boolean buff_in_use
  1129.     
  1130.     buffer_list[buffer_number] = {buffer, modified, buffer_version}
  1131.     window_list = window_list[1..window_number-1] & 
  1132.           window_list[window_number+1..length(window_list)]
  1133.     buff_in_use = FALSE
  1134.     for i = 1 to length(window_list) do
  1135.     if window_list[i][W_BUFFER_NUMBER] = buffer_number then
  1136.         buff_in_use = TRUE
  1137.         exit
  1138.     end if
  1139.     end for 
  1140.     if not buff_in_use then
  1141.     buffer_list[buffer_number] = 0 -- discard the buffer
  1142.     end if
  1143.     if length(window_list) = 0 then
  1144.     return TRUE
  1145.     end if
  1146.     set_window_size()
  1147.     refresh_other_windows(1)
  1148.     window_number = 1
  1149.     restore_state(window_number)
  1150.     set_position(s_line, s_col)
  1151.     return FALSE
  1152. end function
  1153.  
  1154. procedure add_queue(sequence keystrokes)
  1155. -- add to artificial queue of keystrokes
  1156.     key_queue &= keystrokes
  1157. end procedure
  1158.  
  1159. function next_key()
  1160. -- return the next key from the user, or from our 
  1161. -- artificial queue of keystrokes. Check for control-c.
  1162.     char c
  1163.     
  1164.     if length(key_queue) then
  1165.     -- read next artificial keystroke
  1166.     c = key_queue[1]
  1167.     key_queue = key_queue[2..length(key_queue)]
  1168.     else
  1169.     -- read a new keystroke from user
  1170.     c = wait_key()
  1171.     if check_break() then
  1172.         c = CONTROL_C
  1173.     end if
  1174.     if c = ESCAPE then
  1175.         c = get_key()
  1176.         if c = -1 then
  1177.         return ESCAPE
  1178.         elsif c = 79 then
  1179.         c = wait_key()
  1180.         if c = 0 then
  1181.             return HOME
  1182.         elsif c = 101 then
  1183.             return END
  1184.         else
  1185.             add_queue({79, c})
  1186.         end if
  1187.         elsif c = 91 then
  1188.         c = get_key() -- 49
  1189.         c = get_key()
  1190.         if get_key() then -- 126
  1191.         end if
  1192.         if c >= 49 and c <= 60 then
  1193.             return F1+c-49 -- only F1..F4 are like this
  1194.         else
  1195.             add_queue({91, 49, c, 126})
  1196.         end if
  1197.         else
  1198.         add_queue({c})
  1199.         end if
  1200.         return ESCAPE
  1201.     end if
  1202.     end if
  1203.     return c
  1204. end function
  1205.  
  1206. procedure refresh_all_windows()
  1207. -- redisplay all the windows
  1208.     window_id w
  1209.  
  1210.     w = window_number
  1211.     save_state()
  1212.     refresh_other_windows(w)
  1213.     restore_state(w)
  1214. end procedure
  1215.  
  1216. function key_gets(sequence hot_keys, sequence history)
  1217. -- Return an input string from the keyboard.
  1218. -- Handles special editing keys. 
  1219. -- Some keys are "hot" - no Enter required.
  1220. -- A list of "history" strings can be supplied,
  1221. -- and accessed by the user using up/down arrow.
  1222.     sequence input_string
  1223.     integer line, init_column, column, char, col, h
  1224.     sequence cursor
  1225.     boolean first_key
  1226.     
  1227.     if not HOT_KEYS then
  1228.     hot_keys = ""
  1229.     end if
  1230.     cursor = get_position()
  1231.     line = cursor[1]
  1232.     init_column = cursor[2]
  1233.     history = append(history, "")
  1234.     h = length(history)
  1235.     if h > 1 then
  1236.        h -= 1  -- start by offering the last choice
  1237.     end if
  1238.     input_string = history[h]
  1239.     column = init_column
  1240.     first_key = TRUE
  1241.     
  1242.     while TRUE do
  1243.     position(line, init_column)
  1244.     puts(SCREEN, input_string)
  1245.     puts(SCREEN, BLANK_LINE)
  1246.     position(line, column)
  1247.     
  1248.     char = next_key()
  1249.     
  1250.     if char = CR or char = 10 then
  1251.         exit
  1252.         
  1253.     elsif char = BS then
  1254.         if column > init_column then
  1255.         column -= 1
  1256.         col = column-init_column
  1257.         input_string = input_string[1..col] & 
  1258.                    input_string[col+2..length(input_string)]
  1259.         end if
  1260.     
  1261.     elsif char = ARROW_LEFT then
  1262.         if column > init_column then
  1263.         column -= 1
  1264.         end if
  1265.     
  1266.     elsif char = ARROW_RIGHT then
  1267.         if column < init_column+length(input_string) and
  1268.            column < screen_width then
  1269.         column += 1
  1270.         end if      
  1271.     
  1272.     elsif char = ARROW_UP then
  1273.         if h > 1 then
  1274.         h -= 1
  1275.         else
  1276.         h = length(history)
  1277.         end if
  1278.         input_string = history[h]
  1279.         column = init_column + length(input_string)
  1280.     
  1281.     elsif char = ARROW_DOWN then
  1282.         if h < length(history) then
  1283.         h += 1
  1284.         else
  1285.         h = 1
  1286.         end if
  1287.         input_string = history[h]
  1288.         column = init_column + length(input_string)
  1289.         
  1290.     elsif char = DELETE or char = XDELETE then
  1291.         if column - init_column < length(input_string) then
  1292.         col = column-init_column
  1293.         input_string = input_string[1..col] & 
  1294.                    input_string[col+2..length(input_string)]
  1295.         end if
  1296.     
  1297.     elsif char = HOME then
  1298.         column = init_column
  1299.         
  1300.     elsif char = END then
  1301.         column = init_column+length(input_string)
  1302.         
  1303.     elsif (char >= 32 and char <= 255) or char = '\t' then
  1304.         -- normal key
  1305.         if first_key then
  1306.         input_string = ""
  1307.         end if
  1308.         if column < screen_width then
  1309.         if char = '\t' then
  1310.             char = ' '
  1311.         end if
  1312.         column += 1
  1313.         if column - init_column > length(input_string) then
  1314.             input_string = append(input_string, char)
  1315.             if column = init_column + 1 and find(char, hot_keys) then
  1316.             exit
  1317.             end if
  1318.         else
  1319.             col = column-init_column
  1320.             input_string = input_string[1..col-1] &
  1321.                    char &
  1322.                    input_string[col..length(input_string)]
  1323.         end if
  1324.         end if
  1325.     
  1326.     elsif char = CONTROL_C then
  1327.         -- refresh screen, treat as Enter key
  1328.         refresh_all_windows()
  1329.         goto_line(0, b_col)
  1330.         input_string &= CR
  1331.         exit
  1332.     end if
  1333.     
  1334.     first_key = FALSE
  1335.     end while
  1336.     
  1337.     return input_string
  1338. end function
  1339.  
  1340. procedure new_screen_length()
  1341. -- set new number of lines on screen
  1342.     natural nlines
  1343.     window_id w
  1344.     
  1345.     set_top_line("How many lines on screen? (25, 28, 43, 50) ")
  1346.     nlines = numeric(key_gets("", {}))
  1347.     if nlines then
  1348.     screen_length = text_rows(nlines)
  1349.     if screen_length != nlines then
  1350.         sound(500)
  1351.     end if
  1352.     w = window_number
  1353.     save_state()
  1354.     set_window_size()
  1355.     refresh_other_windows(w)
  1356.     restore_state(w)
  1357.     if screen_length != nlines then
  1358.         sound(0)
  1359.     end if
  1360.     end if
  1361. end procedure
  1362.  
  1363.  
  1364. -- searching/replacing variables
  1365. boolean searching, replacing, match_case
  1366. searching = FALSE
  1367. replacing = FALSE
  1368. match_case = TRUE
  1369.  
  1370. sequence find_string -- current (default) string to look for
  1371. find_string = ""
  1372.  
  1373. sequence replace_string -- current (default) string to replace with
  1374. replace_string = ""
  1375.  
  1376. procedure replace()
  1377. -- replace find_string by replace_string
  1378. -- we are currently positioned at the start of an occurrence of find_string
  1379.     sequence line
  1380.  
  1381.     set_modified()
  1382.     line = buffer[b_line]
  1383.     line = line[1..b_col-1] & replace_string & line[b_col+length(find_string)..
  1384.                         length(line)]
  1385.     buffer[b_line] = line
  1386.     -- position at end of replacement string
  1387.     for i = 1 to length(replace_string)-1 do
  1388.     arrow_right()
  1389.     end for
  1390.     DisplayLine(b_line, s_line, FALSE)
  1391. end procedure
  1392.  
  1393. function alphabetic(object s)
  1394. -- does s contain alphabetic characters?
  1395.     return find(TRUE, (s >= 'A' and s <= 'Z') or
  1396.               (s >= 'a' and s <= 'z')) 
  1397. end function
  1398.  
  1399. function case_match(sequence string, sequence text)
  1400. -- Find string in text with
  1401. -- either case-sensitive or non-case-sensitive comparison
  1402.     if match_case then
  1403.     return match(string, text)
  1404.     else
  1405.     return match(lower(string), lower(text))
  1406.     end if
  1407. end function
  1408.  
  1409. function update_history(sequence history, sequence string)
  1410. -- update a history variable - string will be placed at the end
  1411.     integer f
  1412.     
  1413.     f = find(string, history) 
  1414.     if f then
  1415.     -- delete it
  1416.     history = history[1..f-1] & history[f+1..length(history)]
  1417.     end if
  1418.     -- put it at the end
  1419.     return append(history, string)
  1420. end function
  1421.  
  1422. function search(boolean continue)
  1423. -- find a string from here to the end of the file
  1424. -- return TRUE if string is found
  1425.     natural col
  1426.     sequence pos, temp_string
  1427.     
  1428.     set_top_line("")
  1429.     if length(buffer) = 0 then
  1430.     puts(SCREEN, "buffer empty")
  1431.     return FALSE
  1432.     end if
  1433.     puts(SCREEN, "searching for: ")
  1434.     if continue then
  1435.     puts(SCREEN, find_string)
  1436.     else
  1437.     pos = get_position()
  1438.     temp_string = find_string
  1439.     find_string = key_gets("", search_history)
  1440.     if length(find_string) > 0 then
  1441.         if not equal(temp_string, find_string) then
  1442.         -- new string typed in
  1443.         search_history = update_history(search_history, find_string)
  1444.         if alphabetic(find_string) and length(find_string) < 40 then
  1445.             set_position(0, pos[2]+length(find_string)+3)
  1446.             puts(SCREEN, "match case? n")
  1447.             pos = get_position()
  1448.             set_position(0, pos[2] - 1)
  1449.             match_case = find('y', key_gets("", {}))
  1450.         end if
  1451.         end if
  1452.         if replacing then
  1453.         set_top_line("")
  1454.         puts(SCREEN, "replace with: ")
  1455.         replace_string = key_gets("", replace_history)
  1456.         replace_history = update_history(replace_history, 
  1457.                          replace_string)
  1458.         end if
  1459.     end if
  1460.     end if
  1461.  
  1462.     normal_video()
  1463.     if length(find_string) = 0 then
  1464.     return FALSE
  1465.     end if
  1466.     col = case_match(find_string, buffer[b_line][b_col+1..length(buffer[b_line])])
  1467.     if col then
  1468.     -- found it on this line after current position
  1469.     for i = 1 to col do
  1470.         arrow_right()
  1471.     end for
  1472.     if replacing then
  1473.         replace()
  1474.     end if
  1475.     return TRUE
  1476.     else
  1477.     -- check lines following this one
  1478.     for b = b_line+1 to length(buffer) do
  1479.         col = case_match(find_string, buffer[b])
  1480.         if col then
  1481.         goto_line(b, 1)
  1482.         for i = 1 to col - 1 do
  1483.            arrow_right()
  1484.         end for
  1485.         if replacing then
  1486.             replace()
  1487.         end if
  1488.         set_top_line("")
  1489.         printf(SCREEN, "searching for: %s", {find_string})
  1490.         return TRUE
  1491.         end if
  1492.     end for
  1493.     set_top_line("")
  1494.     printf(SCREEN, "\"%s\" not found", {find_string})
  1495.     if alphabetic(find_string) then
  1496.         if match_case then
  1497.         puts(SCREEN, "  (case must match)")
  1498.         else
  1499.         puts(SCREEN, "  (any case)")
  1500.         end if
  1501.     end if
  1502.     end if
  1503.     return FALSE
  1504. end function
  1505.  
  1506. procedure show_message()
  1507. -- display error message from ex.err
  1508.     if length(error_message) > 0 then
  1509.     set_top_line("")
  1510.     puts(SCREEN, error_message)
  1511.     normal_video()
  1512.     end if
  1513.     set_position(s_line, s_col)
  1514. end procedure
  1515.  
  1516. procedure set_err_pointer()
  1517. -- set cursor at point of error 
  1518.     
  1519.     for i = 1 to screen_width*5 do -- prevents infinite loop
  1520.     if s_col >= start_col then
  1521.         exit
  1522.     end if
  1523.     arrow_right()
  1524.     end for
  1525. end procedure
  1526.  
  1527. function delete_trailing_white(sequence name)
  1528. -- get rid of blanks, tabs, newlines at end of string
  1529.     while length(name) > 0 do
  1530.     if find(name[length(name)], "\n\r\t ") then
  1531.         name = name[1..length(name)-1]
  1532.     else
  1533.         exit
  1534.     end if
  1535.     end while
  1536.     return name
  1537. end function
  1538.  
  1539. function get_err_line()
  1540. -- try to get file name & line number from ex.err
  1541. -- returns file_name, sets start_line, start_col, error_message
  1542.  
  1543.     file_number err_file
  1544.     sequence file_name
  1545.     sequence err_lines
  1546.     object temp_line
  1547.     natural colon_pos
  1548.  
  1549.     err_file = open("ex.err", "r")
  1550.     if err_file = -1 then
  1551.     error_message = ""
  1552.     else
  1553.     -- read the top of the ex.err error message file
  1554.     err_lines = {}
  1555.     while length(err_lines) < 5 do
  1556.         temp_line = gets(err_file)
  1557.         if atom(temp_line) then
  1558.         exit
  1559.         end if
  1560.         err_lines = append(err_lines, temp_line)
  1561.     end while
  1562.     close(err_file)
  1563.     -- look for file name, line, column and error message
  1564.     if length(err_lines) > 0 then
  1565.         if sequence(err_lines[1]) then
  1566.         colon_pos = match(".e", lower(err_lines[1]))
  1567.         if colon_pos then
  1568.             if find(err_lines[1][colon_pos+2], "xXwWuU") then
  1569.             colon_pos += 1
  1570.             if find(err_lines[1][colon_pos+2], "wWuU") then
  1571.                 colon_pos += 1
  1572.             end if
  1573.             end if
  1574.             file_name = err_lines[1][1..colon_pos+1]
  1575.             start_line = numeric(err_lines[1][colon_pos+3..
  1576.                               length(err_lines[1])])
  1577.             error_message = delete_trailing_white(err_lines[2])
  1578.             if length(err_lines) > 3 then
  1579.             start_col = find('^', expand_tabs(STANDARD_TAB_WIDTH, 
  1580.                           err_lines[length(err_lines)-1]))
  1581.             end if
  1582.             return file_name
  1583.         end if
  1584.         end if
  1585.     end if
  1586.     end if
  1587.     return ""
  1588. end function
  1589.  
  1590. function last_use()
  1591. -- return TRUE if current buffer 
  1592. -- is only referenced by the current window
  1593.     natural count
  1594.  
  1595.     count = 0
  1596.     for i = 1 to length(window_list) do
  1597.     if window_list[i][W_BUFFER_NUMBER] = buffer_number then
  1598.         count += 1
  1599.         if count = 2 then
  1600.         return FALSE
  1601.         end if
  1602.     end if
  1603.     end for
  1604.     return TRUE
  1605. end function
  1606.  
  1607.  
  1608. procedure save_file(sequence save_name)
  1609. -- write buffer to the disk file
  1610.     file_number file_no
  1611.     boolean strip_cr
  1612.     sequence line
  1613.     
  1614.     if control_chars then
  1615.     set_top_line("")
  1616.     printf(SCREEN, "%s: control chars were changed to " & CONTROL_CHAR &
  1617.                " - save anyway? ", {save_name})
  1618.     if not find('y', key_gets("yn", {})) then
  1619.         stop = FALSE
  1620.         return
  1621.     end if
  1622.     end if
  1623.     strip_cr = FALSE
  1624.     if cr_removed then
  1625.     set_top_line("")
  1626.     printf(SCREEN, "%s: Convert CR-LF (DOS-style) to LF (Linux-style)? ", 
  1627.              {save_name})
  1628.     strip_cr = find('y', key_gets("yn", {}))
  1629.     end if
  1630.     set_top_line("")
  1631.     file_no = open(save_name, "w")
  1632.     if file_no = -1 then
  1633.     printf(SCREEN, "Can't save %s - write permission denied", 
  1634.           {save_name})
  1635.     stop = FALSE
  1636.     return
  1637.     end if
  1638.     printf(SCREEN, "saving %s ... ", {save_name})
  1639.     for i = 1 to length(buffer) do
  1640.     line = buffer[i]
  1641.     if cr_removed and not strip_cr then
  1642.         -- He wants CR's - put them back.
  1643.         -- All lines have \n at the end.
  1644.         if length(line) < 2 or line[length(line)-1] != '\r' then
  1645.         line = line[1..length(line)-1] & "\r\n"
  1646.         end if
  1647.     end if
  1648.     puts(file_no, convert_tabs(edit_tab_width, STANDARD_TAB_WIDTH, line))
  1649.     end for
  1650.     close(file_no)
  1651.     if strip_cr then
  1652.     -- the file doesn't have CR's
  1653.     cr_removed = FALSE 
  1654.     end if
  1655.     puts(SCREEN, "ok")
  1656.     if equal(save_name, file_name) then
  1657.     clear_modified()
  1658.     end if
  1659.     stop = TRUE
  1660. end procedure
  1661.  
  1662. procedure shell(sequence command)
  1663. -- run an external command
  1664.     
  1665.     bk_color(BLACK)
  1666.     text_color(WHITE)
  1667.     clear_screen()
  1668.     system(command, 1)
  1669.     normal_video()
  1670.     while get_key() != -1 do
  1671.     -- clear the keyboard buffer
  1672.     end while
  1673.     refresh_all_windows()
  1674. end procedure
  1675.  
  1676. procedure first_bold(sequence string)
  1677. -- highlight first char
  1678.     text_color(TOP_LINE_TEXT_COLOR)
  1679.     puts(SCREEN, string[1])
  1680.     text_color(TOP_LINE_DIM_COLOR)
  1681.     puts(SCREEN, string[2..length(string)])
  1682. end procedure
  1683.  
  1684. procedure delete_editbuff()
  1685. -- Shutting down. Let user delete EDITBUFF.TMP
  1686.     if editbuff then
  1687.     set_top_line("Delete " & TEMPFILE & "? ")
  1688.     if find('y', key_gets("yn", {})) then
  1689.         system(delete_cmd & TEMPFILE, 2)
  1690.     end if
  1691.     end if
  1692. end procedure
  1693.  
  1694. procedure get_escape(boolean help)
  1695. -- process escape command
  1696.     sequence command, answer
  1697.     natural line
  1698.     object self_command
  1699.  
  1700.     cursor(ED_CURSOR)
  1701.  
  1702.     set_top_line("")
  1703.     if help then
  1704.     command = "h"
  1705.     else
  1706.     first_bold("help ")
  1707.     first_bold("clone ")
  1708.     first_bold("quit ")
  1709.     first_bold("save ")
  1710.     first_bold("write ")
  1711.     first_bold("new ")
  1712.     if dot_e then
  1713.         if platform() = LINUX then
  1714.         first_bold("exu ")
  1715.         else
  1716.         first_bold("ex ")
  1717.         end if
  1718.     end if
  1719.     first_bold("dos ")
  1720.     first_bold("find ")
  1721.     first_bold("replace ")
  1722.     first_bold("lines ")
  1723.     first_bold("mods ")
  1724.     text_color(TOP_LINE_TEXT_COLOR)
  1725.     puts(SCREEN, "ddd CR: ")
  1726.     command = key_gets("hcqswnedfrlm", {}) & ' '
  1727.     end if
  1728.  
  1729.     if command[1] = 'f' then
  1730.     replacing = FALSE
  1731.     searching = search(FALSE)
  1732.  
  1733.     elsif command[1] = 'r' then
  1734.     replacing = TRUE
  1735.     searching = search(FALSE)
  1736.  
  1737.     elsif command[1] = 'q' then
  1738.     if modified and last_use() then
  1739.         set_top_line("quit without saving changes? ")
  1740.         if find('y', key_gets("yn", {})) then
  1741.         stop = delete_window()
  1742.         end if
  1743.     else
  1744.         stop = delete_window()
  1745.     end if
  1746.     
  1747.     elsif command[1] = 'c' then
  1748.     clone_window()
  1749.     
  1750.     elsif command[1] = 'n' then
  1751.     if modified and last_use() then
  1752.         while TRUE do
  1753.         set_top_line("")
  1754.         printf(SCREEN, "save changes to %s? ", {file_name})
  1755.         answer = key_gets("yn", {})
  1756.         if find('y', answer) then
  1757.             save_file(file_name)
  1758.             exit
  1759.         elsif find('n', answer) then
  1760.             exit
  1761.         end if
  1762.         end while
  1763.     end if
  1764.     save_state()
  1765.     set_top_line("new file name: ")
  1766.     answer = delete_trailing_white(key_gets("", file_history))
  1767.     if length(answer) != 0 then
  1768.         file_name = answer
  1769.         stop = TRUE
  1770.     end if
  1771.  
  1772.     elsif command[1] = 'w' then
  1773.     save_file(file_name)
  1774.     stop = FALSE
  1775.  
  1776.     elsif command[1] = 's' then
  1777.     save_file(file_name)
  1778.     if stop then
  1779.         stop = delete_window()
  1780.     end if
  1781.  
  1782.     elsif command[1] = 'e' and dot_e then
  1783.     if modified then
  1784.         save_file(file_name)
  1785.         stop = FALSE
  1786.     end if
  1787.     -- execute the current file & return
  1788.     if sequence(dir("ex.err")) then
  1789.         if platform() = LINUX then
  1790.         system(delete_cmd & "ex.err", 0)
  1791.         else
  1792.         system(delete_cmd & "ex.err > NUL", 0)
  1793.         end if
  1794.     end if
  1795.     if platform() = LINUX then
  1796.         shell("exu " & file_name)
  1797.     elsif match(".exw", lower(file_name)) or 
  1798.           match(".ew",  lower(file_name)) then
  1799.         shell("exw " & file_name)
  1800.     else
  1801.         shell("ex " & file_name)
  1802.     end if
  1803.     goto_line(0, b_col)
  1804.     if equal(file_name, get_err_line()) then
  1805.         goto_line(start_line, 1)
  1806.         set_err_pointer()
  1807.         show_message()
  1808.     end if
  1809.  
  1810.     elsif command[1] = 'd' then
  1811.     if platform() = LINUX then
  1812.         set_top_line("Linux command? ")
  1813.     else
  1814.         set_top_line("DOS command? ")
  1815.     end if
  1816.     command = key_gets("", command_history)
  1817.     if length(delete_trailing_white(command)) > 0 then
  1818.         shell(command)
  1819.         command_history = update_history(command_history, command)
  1820.     end if
  1821.     normal_video()
  1822.     goto_line(0, b_col) -- refresh screen
  1823.     
  1824.     elsif command[1] = 'm' then
  1825.     -- show differences between buffer and file on disk
  1826.     save_file(TEMPFILE)
  1827.     if stop then
  1828.         stop = FALSE
  1829.         shell(compare_cmd & file_name & " " & TEMPFILE & " | more")
  1830.         normal_video()
  1831.         goto_line(0, b_col)
  1832.         editbuff = TRUE
  1833.     end if
  1834.     
  1835.     elsif command[1] = 'h' then
  1836.     self_command = getenv("EUDIR")
  1837.     if atom(self_command) then
  1838.         -- Euphoria hasn't been installed yet 
  1839.         set_top_line("EUDIR not set. See install.doc")
  1840.     else    
  1841.         self_command = {ESCAPE, 'c', ESCAPE, 'n'} & self_command & 
  1842.                SLASH & "doc"
  1843.         if help then
  1844.         set_top_line(
  1845.         "That key does nothing - do you want to view the help text? ")
  1846.         answer = key_gets("yn", {}) & ' '
  1847.         if answer[1] != 'n' and answer[1] != 'N' then
  1848.             answer = "e"
  1849.         end if
  1850.         else
  1851.         set_top_line("ed.doc, refman.doc, or library.doc? (e, r or l): ")
  1852.         answer = key_gets("erl", {}) & ' '
  1853.         end if
  1854.         if answer[1] = 'r' then
  1855.         add_queue(self_command & SLASH & "refman.doc" & CR)
  1856.         elsif answer[1] = 'e' then
  1857.         add_queue(self_command & SLASH & "ed.doc" & CR)
  1858.         elsif answer[1] = 'l' then
  1859.         add_queue(self_command & SLASH & "library.doc" & CR)
  1860.         else
  1861.         normal_video()
  1862.         end if
  1863.     end if
  1864.  
  1865.     elsif command[1] = 'l' then
  1866.     new_screen_length()
  1867.  
  1868.     elsif command[1] >= '0' and command[1] <= '9' then
  1869.     line = numeric(command)
  1870.     normal_video()
  1871.     goto_line(line, 1)
  1872.     if not buffer_line(line) then
  1873.         set_top_line("")
  1874.         printf(SCREEN, "lines are 1..%d", length(buffer))
  1875.     end if
  1876.  
  1877.     else
  1878.     set_top_line("")
  1879.     if length(buffer) = 0 then
  1880.         puts(SCREEN, "empty buffer")
  1881.     else
  1882.         printf(SCREEN, "%s line %d of %d, column %d of %d, ",
  1883.                {file_name, b_line, length(buffer), s_col,
  1884.             length(expand_tabs(edit_tab_width, buffer[b_line]))-1})
  1885.         if modified then
  1886.         puts(SCREEN, "modified")
  1887.         else
  1888.         puts(SCREEN, "not modified")
  1889.         end if
  1890.     end if
  1891.     end if
  1892.  
  1893.     normal_video()
  1894. end procedure
  1895.  
  1896. procedure insert(char key)
  1897. -- insert a character into the current line at the current position
  1898.  
  1899.     sequence tail
  1900.  
  1901.     set_modified()
  1902.     tail = buffer[b_line][b_col..length(buffer[b_line])]
  1903.     if key = CR or key = '\n' then
  1904.     -- truncate this line and create a new line using tail
  1905.     buffer[b_line] = buffer[b_line][1..b_col-1] & '\n'
  1906.     
  1907.     -- make room for new line:
  1908.     buffer = append(buffer, 0)
  1909.     for i = length(buffer)-1 to b_line+1 by -1 do
  1910.         buffer[i+1] = buffer[i]
  1911.     end for
  1912.     
  1913.     -- store new line
  1914.     buffer[b_line+1] = tail
  1915.     
  1916.     if s_line = window_length then
  1917.         arrow_down()
  1918.         arrow_up()
  1919.     else
  1920.         ScrollDown(s_line+1, window_length)
  1921.     end if
  1922.     if window_length = 1 then
  1923.         arrow_down()
  1924.     else
  1925.         DisplayLine(b_line, s_line, FALSE)
  1926.         b_line += 1
  1927.         s_line += 1
  1928.         DisplayLine(b_line, s_line, FALSE)
  1929.     end if
  1930.     s_col = 1
  1931.     b_col = 1
  1932.     else
  1933.     if key = '\t' then
  1934.         s_col = tab(edit_tab_width, s_col)
  1935.     else
  1936.         s_col += 1
  1937.     end if
  1938.     buffer[b_line] = buffer[b_line][1..b_col-1] & key & tail
  1939.     DisplayLine(b_line, s_line, TRUE)
  1940.     b_col += 1
  1941.     end if
  1942.     set_position(s_line, s_col)
  1943. end procedure
  1944.  
  1945. procedure insert_string(sequence text)
  1946. -- insert a bunch of characters at the current position
  1947.     natural save_line, save_col
  1948.  
  1949.     save_line = b_line
  1950.     save_col = b_col
  1951.     for i = 1 to length(text) do
  1952.     if text[i] = CR or text[i] = '\n' then
  1953.         insert(text[i])
  1954.     else
  1955.         buffer[b_line] = buffer[b_line][1..b_col-1] & text[i] &
  1956.                  buffer[b_line][b_col..length(buffer[b_line])]
  1957.         b_col += 1
  1958.         if i = length(text) then
  1959.         DisplayLine(b_line, s_line, FALSE)
  1960.         end if
  1961.     end if
  1962.     end for
  1963.     goto_line(save_line, save_col)
  1964. end procedure
  1965.  
  1966. -- expandable words & corresponding text
  1967. constant expand_word = {"if", "for", "while", "elsif",
  1968.             "procedure", "type", "function"},
  1969.  
  1970.      expand_text = {" then",  "=  to  by  do",  " do",  " then",
  1971.             "()",  "()",  "()" 
  1972.                }
  1973.  
  1974. procedure try_auto_complete(char key)
  1975. -- check for a keyword that can be automatically completed
  1976.     sequence word, this_line, white_space, leading_white, begin
  1977.     natural first_non_blank, wordnum
  1978.  
  1979.     if key = ' ' then
  1980.     insert(key)
  1981.     end if
  1982.     this_line = buffer[b_line]
  1983.     white_space = this_line = ' ' or this_line = '\t'
  1984.     first_non_blank = find(0, white_space) -- there's always '\n' at end
  1985.     leading_white = this_line[1..first_non_blank - 1]         
  1986.     if auto_complete and first_non_blank < b_col - 2 then
  1987.     if not find(0, white_space[b_col..length(white_space)-1]) then
  1988.         word = this_line[first_non_blank..b_col - 1 - (key = ' ')]
  1989.         wordnum = find(word, expand_word)           
  1990.         
  1991.         if key = CR and equal(word, "else") then    
  1992.          leading_white &= '\t'
  1993.         
  1994.         elsif wordnum > 0 then
  1995.         sound(1000)
  1996.         -- expandable word (only word on line)
  1997.  
  1998.         begin = expand_text[wordnum] & CR & leading_white
  1999.         
  2000.         if equal(word, "elsif") then
  2001.             insert_string(begin & '\t')
  2002.            
  2003.         elsif find(word, {"function", "type"}) then
  2004.             insert_string(begin & CR & 
  2005.                   leading_white & "\treturn" & CR &
  2006.                   "end " & expand_word[wordnum])
  2007.         else
  2008.             insert_string(begin & '\t' & CR &
  2009.                   leading_white &
  2010.                   "end " & expand_word[wordnum])
  2011.         end if
  2012.         delay(0.07) -- or beep is too short
  2013.         sound(0)
  2014.         end if
  2015.     end if
  2016.     end if
  2017.     if key = CR then
  2018.     if b_col >= first_non_blank then
  2019.         buffer[b_line] = buffer[b_line][1..b_col-1] & leading_white &
  2020.                  buffer[b_line][b_col..length(buffer[b_line])]
  2021.         insert(CR)
  2022.         skip_white()
  2023.     else
  2024.         insert(CR)
  2025.     end if
  2026.     end if
  2027. end procedure
  2028.  
  2029. procedure insert_kill_buffer()
  2030. -- insert the kill buffer at the current position
  2031. -- kill buffer could be a sequence of lines or a sequence of characters
  2032.  
  2033.     if length(kill_buffer) = 0 then
  2034.     return
  2035.     end if
  2036.     set_modified()
  2037.     if atom(kill_buffer[1]) then
  2038.     -- inserting a sequence of chars
  2039.     insert_string(kill_buffer)
  2040.     else
  2041.     -- inserting a sequence of lines
  2042.     buffer = buffer[1..b_line - 1] &
  2043.          kill_buffer &
  2044.          buffer[b_line..length(buffer)]
  2045.     DisplayWindow(b_line, s_line)
  2046.     b_col = 1
  2047.     s_col = 1
  2048.     end if
  2049. end procedure
  2050.  
  2051. procedure delete_line(buffer_line dead_line)
  2052. -- delete a line from the buffer and update the display if necessary
  2053.  
  2054.     integer x
  2055.  
  2056.     set_modified()
  2057.     -- move up all lines coming after the dead line
  2058.     for i = dead_line to length(buffer)-1 do
  2059.     buffer[i] = buffer[i+1]
  2060.     end for
  2061.     buffer = buffer[1..length(buffer)-1]
  2062.     
  2063.     x = dead_line - b_line + s_line
  2064.     if window_line(x) then
  2065.     -- dead line is on the screen at line x
  2066.     ScrollUp(x, window_length)
  2067.     if length(buffer) - b_line >= window_length - s_line then
  2068.         -- show new line at bottom
  2069.         DisplayLine(b_line + window_length - s_line, window_length, TRUE)
  2070.     end if
  2071.     end if
  2072.     if b_line > length(buffer) then
  2073.     arrow_up()
  2074.     else
  2075.     b_col = 1
  2076.     s_col = 1
  2077.     end if
  2078.     adding_to_kill = TRUE
  2079. end procedure
  2080.  
  2081. procedure delete_char()
  2082. -- delete the character at the current position
  2083.     char dchar
  2084.     sequence head
  2085.     natural save_b_col
  2086.  
  2087.     set_modified()
  2088.     dchar = buffer[b_line][b_col]
  2089.     head = buffer[b_line][1..b_col - 1]
  2090.     if dchar = '\n' then
  2091.     if b_line < length(buffer) then
  2092.         -- join this line with the next one and delete the next one
  2093.         buffer[b_line] = head & buffer[b_line+1]
  2094.         DisplayLine(b_line, s_line, FALSE)
  2095.         save_b_col = b_col
  2096.         delete_line(b_line + 1)
  2097.         for i = 1 to save_b_col - 1 do
  2098.         arrow_right()
  2099.         end for
  2100.     else
  2101.         if length(buffer[b_line]) = 1 then
  2102.         delete_line(b_line)
  2103.         else
  2104.         arrow_left() -- a line must always end with \n
  2105.         end if
  2106.     end if
  2107.     else
  2108.     buffer[b_line] = head & buffer[b_line][b_col+1..length(buffer[b_line])]
  2109.     if length(buffer[b_line]) = 0 then
  2110.         delete_line(b_line)
  2111.     else
  2112.         DisplayLine(b_line, s_line, FALSE)
  2113.         if b_col > length(buffer[b_line]) then
  2114.         arrow_left()
  2115.         end if
  2116.     end if
  2117.     end if
  2118.     adding_to_kill = TRUE
  2119. end procedure
  2120.  
  2121. function good(extended_char key)
  2122. -- return TRUE if key should be processed
  2123.     if find(key, SPECIAL_KEYS) then
  2124.     return TRUE
  2125.     elsif key >= ' ' and key <= 255 then
  2126.     return TRUE
  2127.     elsif key = '\t' or key = CR then
  2128.     return TRUE
  2129.     else
  2130.     return FALSE
  2131.     end if
  2132. end function
  2133.  
  2134. procedure edit_file()
  2135. -- edit the file in buffer
  2136.     extended_char key
  2137.  
  2138.     if length(buffer) > 0 then
  2139.     if start_line > 0 then
  2140.         if start_line > length(buffer) then
  2141.         start_line = length(buffer)
  2142.         end if
  2143.         goto_line(start_line, 1)
  2144.         set_err_pointer()
  2145.         show_message()
  2146.     end if
  2147.     end if
  2148.     
  2149.     -- to speed up keyboard repeat rate:
  2150.     -- system("mode con rate=30 delay=2", 2)
  2151.     
  2152.     cursor(ED_CURSOR)
  2153.     stop = FALSE
  2154.  
  2155.     while not stop do
  2156.  
  2157.     key = next_key()
  2158.     if key = CONTROL_C then
  2159.         refresh_all_windows()
  2160.         goto_line(0, b_col)
  2161.     end if
  2162.     
  2163.     if good(key) then
  2164.         -- normal key
  2165.         
  2166.         if key = CUSTOM_KEY then
  2167.         add_queue(CUSTOM_KEYSTROKES)
  2168.  
  2169.         elsif key >= F1 and key <= F10 then
  2170.         if key < F1 + length(window_list) then
  2171.             switch_window(key - F1 + 1)
  2172.         else
  2173.             set_top_line("")
  2174.             printf(SCREEN, "F%d is not an active window", key - F1 + 1)
  2175.             normal_video()
  2176.         end if
  2177.         adding_to_kill = FALSE
  2178.         
  2179.         elsif length(buffer) = 0 and key != ESCAPE then
  2180.         -- empty buffer
  2181.         -- only allowed action is to insert something
  2182.         if key = INSERT or not find(key, SPECIAL_KEYS) then
  2183.             -- initialize buffer
  2184.             buffer = {{'\n'}} -- one line with \n
  2185.             b_line = 1
  2186.             b_col = 1
  2187.             s_line = 1
  2188.             s_col = 1
  2189.             if key = INSERT then
  2190.             insert_kill_buffer()
  2191.             else
  2192.             insert(key)
  2193.             end if
  2194.             DisplayLine(1, 1, FALSE)
  2195.         end if
  2196.  
  2197.         elsif key = DELETE or key = XDELETE then
  2198.         if not adding_to_kill then
  2199.             kill_buffer = {buffer[b_line][b_col]}
  2200.         elsif sequence(kill_buffer[1]) then
  2201.             -- we were building up deleted lines,
  2202.             -- but now we'll switch to chars
  2203.             kill_buffer = {buffer[b_line][b_col]}
  2204.         else
  2205.             kill_buffer = append(kill_buffer, buffer[b_line][b_col])
  2206.         end if
  2207.         delete_char()
  2208.  
  2209.         elsif key = CONTROL_DELETE or key = CONTROL_D then
  2210.         if not adding_to_kill then
  2211.             kill_buffer = {buffer[b_line]}
  2212.         elsif atom(kill_buffer[1]) then
  2213.             -- we were building up deleted chars,
  2214.             -- but now we'll switch to lines
  2215.             kill_buffer = {buffer[b_line]}
  2216.         else
  2217.             kill_buffer = append(kill_buffer, buffer[b_line])
  2218.         end if
  2219.         delete_line(b_line)
  2220.  
  2221.         else
  2222.         if key = PAGE_DOWN or key = CONTROL_P then
  2223.             page_down()
  2224.  
  2225.         elsif key = PAGE_UP or key = CONTROL_U then
  2226.             page_up()
  2227.  
  2228.         elsif key = ARROW_LEFT then
  2229.             arrow_left()
  2230.  
  2231.         elsif key = ARROW_RIGHT then
  2232.             arrow_right()
  2233.  
  2234.         elsif key = CONTROL_ARROW_LEFT or key = CONTROL_L then
  2235.             previous_word()
  2236.             
  2237.         elsif key = CONTROL_ARROW_RIGHT or key = CONTROL_R then
  2238.             next_word()
  2239.             
  2240.         elsif key = ARROW_DOWN then
  2241.             arrow_down()
  2242.  
  2243.         elsif key = ARROW_UP then
  2244.             arrow_up()
  2245.  
  2246.         elsif key = ' ' then
  2247.             try_auto_complete(key)
  2248.  
  2249.         elsif key = INSERT then
  2250.             insert_kill_buffer()
  2251.  
  2252.         elsif key = BS then
  2253.             arrow_left()
  2254.             delete_char()
  2255.  
  2256.         elsif key = HOME then
  2257.             b_col = 1
  2258.             s_col = 1
  2259.         
  2260.         elsif key = END then
  2261.             goto_line(b_line, length(buffer[b_line]))
  2262.         
  2263.         elsif key = CONTROL_HOME or key = CONTROL_T then
  2264.             goto_line(1, 1)
  2265.  
  2266.         elsif key = CONTROL_END or key = CONTROL_B then
  2267.             goto_line(length(buffer), length(buffer[length(buffer)]))
  2268.  
  2269.         elsif key = ESCAPE then
  2270.             -- special command
  2271.             get_escape(FALSE)
  2272.  
  2273.         elsif key = CR then
  2274.             if searching then
  2275.             searching = search(TRUE)
  2276.             normal_video()
  2277.             searching = TRUE -- avoids accidental <CR> insertion
  2278.             else
  2279.             try_auto_complete(key)
  2280.             end if
  2281.         
  2282.         else
  2283.             insert(key)
  2284.  
  2285.         end if
  2286.  
  2287.         adding_to_kill = FALSE
  2288.  
  2289.         end if
  2290.  
  2291.         if key != CR and key != ESCAPE then
  2292.         searching = FALSE
  2293.         end if
  2294.         cursor(ED_CURSOR)
  2295.     
  2296.     else
  2297.         -- illegal key pressed
  2298.         get_escape(TRUE)  -- give him some help
  2299.     end if
  2300.     set_position(s_line, s_col)
  2301.     end while
  2302. end procedure
  2303.  
  2304. procedure ed(sequence command)
  2305. -- editor main procedure 
  2306. -- start editing a new file
  2307. -- ed.ex is executed by ed.bat
  2308. -- command line will be:
  2309. --    ex ed.ex              - get filename from ex.err, or user
  2310. --    ex ed.ex filename     - filename specified
  2311.  
  2312.     file_number file_no
  2313.  
  2314.     start_line = 0
  2315.     start_col = 0
  2316.  
  2317.     if length(command) >= 3 then
  2318.     file_name = command[3]
  2319.     if platform() != LINUX then
  2320.         file_name = lower(file_name)
  2321.     end if
  2322.     else
  2323.     file_name = get_err_line()
  2324.     end if
  2325.     wrap(0)
  2326.     if length(file_name) = 0 then
  2327.     -- we still don't know the file name - so ask user
  2328.     puts(SCREEN, "file name: ")
  2329.     cursor(ED_CURSOR)
  2330.     file_name = key_gets("", file_history)
  2331.     puts(SCREEN, '\n')
  2332.     end if
  2333.     file_name = delete_trailing_white(file_name)
  2334.     if length(file_name) = 0 then
  2335.     abort(1) -- file_name was just whitespace - quit
  2336.     end if
  2337.     file_history = update_history(file_history, file_name)
  2338.     file_no = open(file_name, "r")
  2339.  
  2340.     -- turn off multi_color & auto_complete for non .e files
  2341.     multi_color = WANT_COLOR_SYNTAX
  2342.     auto_complete = WANT_AUTO_COMPLETE
  2343.     if not config[VC_COLOR] or config[VC_MODE] = 7 then
  2344.     multi_color = FALSE -- mono monitor
  2345.     end if
  2346.     file_name &= ' '
  2347.     dot_e = FALSE
  2348.     for i = 1 to length(E_FILES) do
  2349.     if match(E_FILES[i] & ' ', file_name) then
  2350.         dot_e = TRUE
  2351.     end if
  2352.     end for
  2353.     if not dot_e then
  2354.     multi_color = FALSE
  2355.     auto_complete = FALSE
  2356.     end if
  2357.     
  2358.     -- use PROG_INDENT tab width for Euphoria & other languages:
  2359.     edit_tab_width = STANDARD_TAB_WIDTH
  2360.     for i = 1 to length(PROG_FILES) do
  2361.        if match(PROG_FILES[i] & ' ', file_name) then
  2362.        edit_tab_width = PROG_INDENT
  2363.        exit
  2364.        end if
  2365.     end for
  2366.     
  2367.     if multi_color then
  2368.     init_class()
  2369.     end if
  2370.  
  2371.     file_name = file_name[1..length(file_name)-1] -- remove ' '
  2372.     adding_to_kill = FALSE
  2373.     clear_modified()
  2374.     buffer_version = 0
  2375.     control_chars = FALSE
  2376.     cr_removed = FALSE
  2377.     new_buffer()
  2378.     s_line = 1
  2379.     s_col = 1
  2380.     b_line = 1
  2381.     b_col = 1
  2382.     save_state()
  2383.     while get_key() != -1 do
  2384.     -- clear the keyboard buffer 
  2385.     -- to reduce "key bounce" problems
  2386.     end while
  2387.     if file_no = -1 then
  2388.     set_f_line(window_number, " <new file>")
  2389.     normal_video()
  2390.     ClearWindow()
  2391.     else
  2392.     set_f_line(window_number, "")
  2393.     normal_video()
  2394.     set_position(1, 1)
  2395.     cursor(NO_CURSOR)
  2396.     read_file(file_no)
  2397.     close(file_no)
  2398.     end if
  2399.     set_position(1, 1)
  2400.     edit_file()
  2401. end procedure
  2402.  
  2403. procedure ed_main()
  2404. -- startup and shutdown of ed()
  2405.     sequence cl
  2406.     
  2407.     allow_break(FALSE)
  2408.     
  2409.     config = video_config()
  2410.  
  2411.     if config[VC_XPIXELS] > 0 then
  2412.     if graphics_mode(3) then
  2413.     end if
  2414.     config = video_config()
  2415.     end if
  2416.  
  2417.     if config[VC_LINES] != INITIAL_LINES then
  2418.     screen_length = text_rows(INITIAL_LINES)
  2419.     config = video_config()
  2420.     end if
  2421.     screen_length = config[VC_LINES]
  2422.     screen_width = config[VC_COLUMNS]
  2423.     BLANK_LINE = repeat(' ', screen_width)
  2424.     window_length = screen_length - 1
  2425.  
  2426.     cl = command_line()
  2427.  
  2428.     while length(window_list) > 0 do
  2429.     ed(cl)
  2430.     cl = {"ex", "ed.ex" , file_name}
  2431.     end while
  2432.  
  2433.     -- exit editor
  2434.     delete_editbuff()
  2435.     if screen_length != FINAL_LINES then
  2436.     screen_length = text_rows(FINAL_LINES)
  2437.     end if
  2438.     cursor(UNDERLINE_CURSOR)
  2439.     bk_color(BLACK)
  2440.     text_color(WHITE)
  2441.     position(screen_length, 1)
  2442.     puts(SCREEN, BLANK_LINE)
  2443.     position(screen_length, 1)
  2444.     puts(SCREEN, "\n")
  2445. end procedure
  2446.  
  2447. ed_main()
  2448. -- This abort statement reduces the chance of 
  2449. -- a syntax error when you edit ed.ex using itself: 
  2450. abort(0) 
  2451.  
  2452. EPRINT.BAT
  2453. 34
  2454. @echo off
  2455. ex.exe eprint.ex %1
  2456.  
  2457. EPRINT.EX
  2458. 5230
  2459.         ------------------------------------
  2460.         -- Print a Euphoria program       --
  2461.         -- (doesn't work yet under Linux) --
  2462.         ------------------------------------
  2463.  
  2464. -- This works with HP PCL printers.
  2465. -- You can change control codes (bold, italics etc) for other printers.
  2466. -- If you have a color printer you can choose colors,
  2467. -- otherwise you will simply get keywords in bold, comments in italics.
  2468. -- You can print non-Euphoria files too.
  2469.  
  2470. -- usage: eprint filename
  2471. --   You will be asked if you want to print in color, 
  2472. --   and if you want to print in condensed mode.
  2473.  
  2474. include wildcard.e
  2475.  
  2476. constant TRUE = 1, FALSE = 0
  2477. constant KEYB = 0, DISPLAY = 1, ERROR = 2
  2478. constant M_GET_POSITION   = 25
  2479.  
  2480. integer syntax, color_printer
  2481. syntax = TRUE                -- to highlight syntax in .e/.ex/.pro files
  2482.  
  2483. constant ESC = 27
  2484.  
  2485. constant hp550c = {"2", "8", "1", "12", "4", "10", "1", "1"}
  2486.  
  2487. integer printer
  2488.  
  2489. procedure bold_on()
  2490.     puts(printer, ESC & "(s3B")
  2491. end procedure
  2492.  
  2493. procedure bold_off()
  2494.     puts(printer, ESC & "(s0B")
  2495. end procedure
  2496.  
  2497. procedure italics_on()
  2498.     puts(printer, ESC & "(s1S")
  2499. end procedure
  2500.  
  2501. procedure italics_off()
  2502.     puts(printer, ESC & "(s0S")
  2503. end procedure
  2504.  
  2505. procedure second_column()
  2506.     puts(printer, ESC & "&a80C")
  2507. end procedure
  2508.  
  2509. procedure form_feed()
  2510.     puts(printer, 12)
  2511. end procedure
  2512.  
  2513. procedure reset()
  2514.     puts(printer, ESC & 'E')   -- reset
  2515. end procedure
  2516.  
  2517. procedure colorMode()
  2518.     puts(printer, ESC & "*r-4U")  -- CYMK
  2519. end procedure
  2520.  
  2521. procedure small()
  2522.     puts(printer, ESC & "(s20H")    -- Print Pitch (width)
  2523.     puts(printer, ESC & "(s8V")     -- Point Size (height)
  2524.     puts(printer, ESC & "&l4C")     -- vertical motion
  2525. end procedure
  2526.  
  2527. -- symbols needed by syncolor.e:
  2528. global constant  NORMAL_COLOR = 8,
  2529.         COMMENT_COLOR = 4,
  2530.         KEYWORD_COLOR = 1,
  2531.         BUILTIN_COLOR = 5,
  2532.          STRING_COLOR = 6,
  2533.         BRACKET_COLOR = {NORMAL_COLOR}
  2534.  
  2535. include syncolor.e
  2536.  
  2537. procedure set_printer_color(integer color)
  2538. -- set the printer color (or mono effect)
  2539.     sequence color_code
  2540.  
  2541.     if not syntax then
  2542.     return
  2543.     end if
  2544.  
  2545.     if color_printer then
  2546.     color_code = hp550c[color]
  2547.     puts(printer, ESC & "*v" & color_code & "S")
  2548.     else
  2549.     -- normal mono printer
  2550.     if color = KEYWORD_COLOR then
  2551.         italics_off()
  2552.         bold_on()
  2553.     elsif color = COMMENT_COLOR then
  2554.         bold_off()
  2555.         italics_on()
  2556.     else
  2557.         italics_off()
  2558.         bold_off()
  2559.     end if
  2560.     end if
  2561. end procedure
  2562.  
  2563. procedure DisplayColorLine(sequence line)
  2564. -- display one line of text on the printer
  2565.     sequence color_line
  2566.     
  2567.     color_line = SyntaxColor(line)
  2568.     for i = 1 to length(color_line) do
  2569.     set_printer_color(color_line[i][1])
  2570.     puts(printer, color_line[i][2])     
  2571.     end for
  2572. end procedure
  2573.  
  2574. procedure try_colors()
  2575. -- utility routine to display colors on hp550c
  2576.     for i = '0' to '6' do
  2577.     for j = '0' to '9' do
  2578.         puts(printer, ESC & "*v" & i & j & "S")
  2579.         printf(printer, "%s:", {i&j})
  2580.         puts(printer, "Testing Colors ...\n")
  2581.     end for
  2582.     end for
  2583. end procedure
  2584.  
  2585. function get_position()
  2586. -- return {line, column} of current cursor position
  2587.     return machine_func(M_GET_POSITION, 0)
  2588. end function
  2589.  
  2590. function get_response(sequence query, integer letterToSearch)
  2591.     integer matchOrNot
  2592.     sequence pos
  2593.     
  2594.     puts(DISPLAY, query)
  2595.     pos = get_position()
  2596.     position(pos[1], pos[2] - 2)
  2597.     matchOrNot = find(letterToSearch, lower(gets(KEYB)))
  2598.     puts(DISPLAY, '\n')
  2599.     return matchOrNot
  2600. end function
  2601.  
  2602. procedure eprint()
  2603.     integer  efile
  2604.     sequence command, matchname
  2605.     object   line
  2606.     sequence buffer
  2607.     integer  base_line, condensed, nColumns, page_length
  2608.  
  2609.     command = command_line()
  2610.     if length(command) != 3 then
  2611.     puts(ERROR, "usage: eprint filename\n")
  2612.     return
  2613.     end if
  2614.     efile = open(command[3], "r")
  2615.     if efile = -1 then
  2616.     puts(ERROR, "couldn't open " & command[3] & '\n')
  2617.     return
  2618.     end if
  2619.     matchname = command[3] & '&'
  2620.     if not match(".e&", matchname) and
  2621.        not match(".ex&", matchname) and
  2622.        not match(".pro&", matchname) then
  2623.     syntax = FALSE
  2624.     end if
  2625.     printer = open("PRN", "w")
  2626.     if printer = -1 then
  2627.     puts(ERROR, "Can't open printer\n")
  2628.     return
  2629.     end if
  2630.     init_class()
  2631.     reset()
  2632.     
  2633.     if syntax then
  2634.     color_printer = get_response("print in color? (n)", 'y')
  2635.     if color_printer then
  2636.         colorMode()
  2637.     end if
  2638.     else
  2639.     color_printer = FALSE
  2640.     end if
  2641.     
  2642.     condensed = not get_response("condensed print? (y)", 'n')
  2643.     if condensed then
  2644.     nColumns = 2
  2645.     small()
  2646.     else
  2647.     nColumns = 1
  2648.     end if
  2649.     page_length = 59 * nColumns    -- (upper bound) 118 for condensed
  2650.  
  2651.     -- read in whole file
  2652.     buffer = {}
  2653.     while TRUE do
  2654.     line = gets(efile)
  2655.     if atom(line) then
  2656.         exit
  2657.     end if
  2658.     if line[length(line)] != '\n' then
  2659.         line &= '\n' -- need end marker
  2660.     end if
  2661.     buffer = append(buffer, line)
  2662.     end while
  2663.     base_line = 1
  2664.     while base_line <= length(buffer) do
  2665.     for i = base_line to base_line + page_length - 1 do
  2666.         if i <= length(buffer) then
  2667.         DisplayColorLine(buffer[i])
  2668.         if nColumns = 2 and i + page_length <= length(buffer) then
  2669.             second_column()
  2670.             DisplayColorLine(buffer[i + page_length])
  2671.         end if
  2672.         puts(printer, '\n')
  2673.         end if
  2674.     end for
  2675.     base_line += page_length * nColumns
  2676.     form_feed()
  2677.     end while
  2678.     close(efile)
  2679.     reset()
  2680.     close(printer)
  2681. end procedure
  2682.  
  2683. eprint()
  2684.  
  2685. GURU.BAT
  2686. 80
  2687. @echo off
  2688. rem Euphoria "Guru"
  2689. ex.exe guru.ex E! %1 %2 %3 %4 %5 %6 %7 %8 %9
  2690.  
  2691. GURU.EX
  2692. 15996
  2693. -- Guru
  2694. -- usage:
  2695. -- to search EUPHORIA directories:
  2696. --        guru word1 word2 word3 ...
  2697.  
  2698. -- Euphoria .doc and other files are searched. .htm files are skipped.
  2699.  
  2700. -- to search the current directory and all subdirectories:
  2701. --      cdguru word1 word2 word3 ...
  2702.  
  2703. -- Searches for the best articles that contain the words that you type.
  2704. -- Each word can contain * and ? wildcard characters.
  2705. -- The articles are given a score and presented to you sorted by score.
  2706. -- The scoring system strongly favors articles that contain several of 
  2707. -- your words, rather than just several occurrences of one of your words.
  2708. -- Some very common words are ignored (see noise_words).
  2709. -- e.g.
  2710. --        guru sequence* atom *pend g?r?
  2711.  
  2712. -- Results are displayed on screen and also saved in "c:\guru.out"
  2713. -- or $HOME/guru.out (Linux).
  2714. -- Hints - remember to add * to words that can be pluralized or have 
  2715. --         many different endings.
  2716. --       - enter an important word twice to double the value of that word  
  2717. --       - If you get a "Critical Error", type 'i' for ignore. It just
  2718. --         means that a file is currently locked by another application.
  2719.  
  2720. without type_check
  2721.  
  2722. include misc.e
  2723. include file.e
  2724. include wildcard.e
  2725. include graphics.e
  2726. include sort.e
  2727.  
  2728.  
  2729. -------- some user-modifiable parameters: 
  2730.  
  2731. integer SLASH
  2732. sequence log_name, log_path, home
  2733.  
  2734. log_name = "guru.out"
  2735. -- place to store results
  2736. if platform() = LINUX then
  2737.     SLASH = '/'
  2738.     home = getenv("HOME")
  2739.     if sequence(home) then
  2740.     log_path = home & '/' & log_name -- put in home dir if possible
  2741.     else
  2742.     log_path = log_name  
  2743.     end if
  2744. else
  2745.     SLASH = '\\'
  2746.     log_path = "c:\\" & log_name  
  2747. end if
  2748.  
  2749. -- files to skip:
  2750. sequence skip_list 
  2751. skip_list = {
  2752.     "*.EXE", "*.DLL", "*.LIB", "*.OBJ", 
  2753.     "*.SWP", "*.PAR", "*.ZIP", "*.BMP", 
  2754.     "*.GIF", "*.JPG", "*.WAV"
  2755. }
  2756.  
  2757. -- ignore these extremely common words when searching
  2758. sequence noise_words
  2759. noise_words = {
  2760.     "a", "an", "the", "to", "and", "of", "is", "or", "by", "as", "in",
  2761.     "you", "are", "be", "if", "?", "*"
  2762. }
  2763. constant separator_line = repeat(196, 5)
  2764.  
  2765. constant MAX_CHUNKS = 20        -- maximum number of chunks to display
  2766.  
  2767. -- desired size for a chunk of text:
  2768. constant MIN_CHUNK_SIZE = 10,   -- minimum number of lines
  2769.      MAX_CHUNK_SIZE = 20    -- maximum number of lines
  2770.  
  2771. constant  LEFT_HIGHLIGHT = 17,  -- highlight markers for matched words
  2772.      RIGHT_HIGHLIGHT = 16   -- (assume LEFT_HIGHLIGHT > RIGHT_HIGHLIGHT)
  2773.  
  2774. constant HIGHLIGHT_COLOR = BRIGHT_WHITE
  2775.      
  2776. -------- end of user-modifiable parameters 
  2777.  
  2778. constant SCREEN = 1, ERR = 2
  2779.  
  2780. constant TRUE = 1, FALSE = 0
  2781. constant EOF = -1
  2782.  
  2783. type boolean(integer x)
  2784.     return x = 0 or x = 1
  2785. end type
  2786.  
  2787. sequence word_list, word_count, file_spec
  2788.  
  2789. boolean euphoria
  2790.  
  2791. integer count_line
  2792.  
  2793. integer log_file
  2794.  
  2795. constant LINE_WIDTH = 83
  2796. constant TO_LOWER = 'a' - 'A' 
  2797.  
  2798. function fast_lower(sequence s)
  2799. -- Faster than the standard lower().
  2800. -- Speed of lower() is important here.
  2801.     integer c
  2802.     
  2803.     for i = 1 to length(s) do
  2804.     c = s[i]
  2805.     if c <= 'Z' then
  2806.         if c >= 'A' then
  2807.         s[i] = c + TO_LOWER
  2808.         end if
  2809.     end if
  2810.     end for
  2811.     return s
  2812. end function
  2813.  
  2814. function clean(sequence line)
  2815. -- replace any funny control characters 
  2816. -- and put in \n's to help break up long lines
  2817.     sequence new_line
  2818.     integer c, col
  2819.     
  2820.     new_line = ""
  2821.     col = 1
  2822.     for i = 1 to length(line) do
  2823.     if col > LINE_WIDTH then
  2824.         new_line = append(new_line, '\n')
  2825.         col = 1
  2826.     end if
  2827.     c = line[i]
  2828.     col += 1
  2829.     if c < 14 then
  2830.         if c = '\n' then
  2831.         col = 1
  2832.         elsif c = '\r' then
  2833.         c = ' '    
  2834.         elsif c !=  '\t' then
  2835.         c = '.'
  2836.         end if
  2837.     end if
  2838.     new_line = append(new_line, c)
  2839.     end for
  2840.     return new_line
  2841. end function
  2842.  
  2843. boolean display
  2844. display = TRUE
  2845.  
  2846. procedure both_puts(object text)
  2847.     puts(log_file, text)
  2848.     if display then
  2849.     puts(SCREEN, text)
  2850.     end if
  2851. end procedure
  2852.  
  2853. procedure both_printf(sequence format, object values)
  2854.     printf(log_file, format, values)
  2855.     if display then
  2856.     printf(SCREEN, format, values)
  2857.     end if
  2858. end procedure
  2859.  
  2860. constant MAX_LINE = 100 
  2861.  
  2862. -- space for largest line
  2863. sequence buff
  2864. buff = repeat(0, MAX_LINE)
  2865.  
  2866. function safe_gets(integer fn)
  2867. -- Return the next line of text - always with \n on the end.
  2868. -- Lines are split at MAX_LINE to prevent
  2869. -- "out of memory" problems on humongous lines
  2870. -- and to reduce the amount of extraneous output.
  2871.     integer c
  2872.     
  2873.     for b = 1 to MAX_LINE-1 do
  2874.     c = getc(fn)
  2875.     if c <= LEFT_HIGHLIGHT then
  2876.         if c = '\n' then
  2877.         buff[b] = c
  2878.         return buff[1..b]
  2879.         elsif c = EOF then
  2880.         if b = 1 then
  2881.             return EOF
  2882.         else
  2883.             buff[b] = '\n'
  2884.             return buff[1..b]
  2885.         end if
  2886.         elsif c >= RIGHT_HIGHLIGHT or c = 0 then
  2887.         c = '.'
  2888.         end if
  2889.     end if
  2890.     buff[b] = c
  2891.     end for
  2892.     buff[MAX_LINE] = '\n'
  2893.     return buff[1..MAX_LINE]
  2894. end function
  2895.  
  2896. function sum(sequence s)
  2897. -- sum of a sequence
  2898.     atom sum
  2899.     
  2900.     sum = 0
  2901.     for i = 1 to length(s) do
  2902.     sum += s[i]
  2903.     end for
  2904.     return sum
  2905. end function
  2906.  
  2907. object line
  2908. integer line_next
  2909. boolean words_on_line
  2910.  
  2911. sequence char_class
  2912. --    0 means not legitimate
  2913. --    1 means legitimate char
  2914. --  > 1 means possible first char of matching word
  2915. char_class = repeat(0, 255)
  2916. char_class['A'..'Z'] = 1
  2917. char_class['a'..'z'] = 1
  2918. char_class['0'..'9'] = 1
  2919. char_class['_'] = 1
  2920.  
  2921. function has_punctuation(sequence word)
  2922. -- TRUE if word contains any punctuation characters 
  2923.     integer c
  2924.     for i = 1 to length(word) do
  2925.     c = word[i]
  2926.     if char_class[c] = 0 and c != '?' and c != '*' then
  2927.         return TRUE
  2928.     end if
  2929.     end for
  2930.     return FALSE
  2931. end function
  2932.  
  2933. function next_word()
  2934. -- Return next possible matching word from line
  2935. -- based on first letter of the word.
  2936.     sequence word
  2937.     integer c
  2938.  
  2939.     while TRUE do
  2940.     -- skip white space:
  2941.     while TRUE do
  2942.         c = line[line_next]
  2943.         line_next += 1
  2944.         if char_class[c] > 0 then
  2945.         exit
  2946.         elsif c = '\n' then -- there's always a '\n' at end of line 
  2947.         return -1
  2948.         end if
  2949.     end while
  2950.     
  2951.     words_on_line = TRUE
  2952.     
  2953.     -- check first letter in word:
  2954.     if char_class[c] > 1 then
  2955.         -- possible matching word
  2956.         word = {c}
  2957.         -- read rest of word
  2958.         while TRUE do
  2959.         c = line[line_next]
  2960.         if char_class[c] = 0 then
  2961.             return word
  2962.         end if
  2963.         line_next += 1
  2964.         word &= c
  2965.         end while
  2966.     else
  2967.         -- not a possible matching word -skip it
  2968.         while TRUE do
  2969.         c = line[line_next]
  2970.         if char_class[c] = 0 then
  2971.             exit
  2972.         end if
  2973.         line_next += 1
  2974.         end while
  2975.     end if
  2976.     end while
  2977. end function
  2978.  
  2979. sequence chunk_list
  2980. chunk_list = {{-1, {}, {}}}
  2981.  
  2982. procedure highlight(sequence text)
  2983. -- print a line with highlighted words in color
  2984.     integer c
  2985.     
  2986.     if not display then
  2987.     return
  2988.     end if
  2989.     for i = 1 to length(text) do
  2990.     c = text[i]
  2991.     if c = LEFT_HIGHLIGHT then
  2992.         text_color(HIGHLIGHT_COLOR)
  2993.     elsif c = RIGHT_HIGHLIGHT then
  2994.         text_color(WHITE)
  2995.     else
  2996.         puts(SCREEN, c)
  2997.     end if
  2998.     end for
  2999. end procedure
  3000.  
  3001. procedure print_chunk_list()
  3002. -- print the best chunks found
  3003.     sequence chunk, line
  3004.  
  3005.     position(count_line, 1)
  3006.     for i = 1 to length(word_list) do
  3007.     both_printf("%s:%d ", {word_list[i], word_count[i]})
  3008.     end for
  3009.     position(count_line+1, 1)
  3010.     puts(SCREEN, repeat(' ', 80))
  3011.     puts(log_file, '\n')
  3012.     
  3013.     for i = 1 to length(chunk_list) - 1 do
  3014.     if i > 1 and display then
  3015.         text_color(GREEN)
  3016.         puts(SCREEN, "\nPress q to quit, Enter for more:")
  3017.         text_color(WHITE)
  3018.         puts(SCREEN, " ")
  3019.         if getc(0) = 'q' then
  3020.         display = FALSE
  3021.         end if
  3022.     end if
  3023.     text_color(RED)
  3024.     both_printf("\n#%d of %d ------ %s --- score: %d ------\n", 
  3025.             {i, length(chunk_list)-1, 
  3026.             chunk_list[i][2], 100 * chunk_list[i][1] + 0.5})
  3027.     text_color(WHITE)
  3028.     chunk = chunk_list[i][3]
  3029.     wrap(FALSE)
  3030.     for j = 1 to length(chunk) do
  3031.         line = clean(chunk[j])
  3032.         highlight(line)
  3033.         puts(log_file, line)        
  3034.     end for
  3035.     wrap(TRUE)
  3036.     end for
  3037.     if length(chunk_list) > 1 then
  3038.     text_color(GREEN)
  3039.     puts(SCREEN, "\nSee " & log_path & '\n')
  3040.     end if
  3041.     text_color(WHITE)
  3042.     puts(SCREEN, " \n")
  3043. end procedure
  3044.  
  3045. procedure save_chunk(sequence file_name, sequence chunk, atom score)
  3046. -- record an interesting chunk on the chunk list 
  3047.  
  3048.     score /= 10 + sqrt(length(chunk)) -- reduce slightly for larger chunks
  3049.     for i = 1 to length(chunk_list) do
  3050.     if score > chunk_list[i][1] then
  3051.         -- insert chunk into list at proper position
  3052.         chunk_list = append(chunk_list[1..i-1], {score, file_name, chunk}) 
  3053.              & chunk_list[i..length(chunk_list)]
  3054.         if length(chunk_list) >  MAX_CHUNKS+1 then
  3055.         -- drop the worst chunk on the list
  3056.         chunk_list = chunk_list[1..length(chunk_list)-1]
  3057.         end if
  3058.         exit
  3059.     end if
  3060.     end for
  3061. end procedure
  3062.  
  3063. sequence wild_word
  3064.  
  3065. procedure scan(sequence file_name)
  3066. -- read next file 
  3067.     integer fileNum, first_hit, last_hit, new_chunk
  3068.     sequence lword, chunk, word_value
  3069.     object word
  3070.     atom chunk_total, line_total
  3071.     boolean doc_file, matched, first_match
  3072.     
  3073.     fileNum = open(file_name, "rb")   
  3074.     if fileNum = -1 then
  3075.     return 
  3076.     end if
  3077.     
  3078.     -- is it a Euphoria .doc file?
  3079.     doc_file = euphoria and match(".DOC", file_name) 
  3080.     
  3081.     -- update display
  3082.     wrap(FALSE)
  3083.     position(count_line, 1)
  3084.     for i = 1 to length(word_list) do
  3085.     printf(SCREEN, "%s:%d ", {word_list[i], word_count[i]})
  3086.     end for
  3087.     position(count_line+1, 1)
  3088.     puts(SCREEN, "searching: " & file_name & repeat(' ', 80) & '\r')
  3089.     wrap(TRUE)
  3090.     
  3091.     new_chunk = TRUE
  3092.     while TRUE do
  3093.     -- initialize
  3094.     if new_chunk then
  3095.         chunk = {}
  3096.         chunk_total = 0
  3097.         first_hit = 0
  3098.         last_hit = 0
  3099.         new_chunk = FALSE
  3100.         word_value = repeat(1, length(word_list))
  3101.     end if
  3102.     line_next = 1
  3103.     line_total = 0
  3104.  
  3105.     -- read next line
  3106.     line = safe_gets(fileNum)
  3107.     if atom(line) then
  3108.         exit -- end of file
  3109.     end if
  3110.     
  3111.     if get_key() = 'q' then
  3112.         close(fileNum)
  3113.         print_chunk_list()
  3114.         abort(1)
  3115.     end if
  3116.     
  3117.     words_on_line = FALSE
  3118.     
  3119.     while TRUE do
  3120.         -- read next word in line
  3121.         word = next_word()
  3122.         if atom(word) then
  3123.         exit
  3124.         end if
  3125.         lword = fast_lower(word)
  3126.         first_match = TRUE
  3127.         for i = 1 to length(word_list) do
  3128.         if wild_word[i] then
  3129.             -- slow
  3130.             matched = wildcard_match(word_list[i], lword) 
  3131.         else
  3132.             -- fast
  3133.             matched = equal(word_list[i], lword)
  3134.         end if
  3135.         if matched then
  3136.             -- score a bit higher for matching a non-wildcard word
  3137.             line_total += word_value[i] * (1.0 
  3138.                     + 0.5 * (match(separator_line, line) != 0) 
  3139.                     + 0.3 * (not wild_word[i])
  3140.                     + 0.3 * doc_file)
  3141.             word_count[i] += 1
  3142.             word_value[i] /= 2
  3143.             if first_match then
  3144.             first_match = FALSE
  3145.             line = line[1..line_next - length(word) - 1] & 
  3146.                     LEFT_HIGHLIGHT &
  3147.                     word & 
  3148.                     RIGHT_HIGHLIGHT & 
  3149.                     line[line_next..length(line)]
  3150.             line_next += 2
  3151.             end if
  3152.         end if
  3153.         end for
  3154.     end while
  3155.     chunk = append(chunk, line)
  3156.     
  3157.     -- decide chunk boundaries
  3158.     if words_on_line then
  3159.         if line_total > 0 then
  3160.         chunk_total += line_total
  3161.         last_hit = length(chunk)
  3162.         if first_hit = 0 then
  3163.             first_hit = last_hit
  3164.         end if
  3165.         end if
  3166.         if chunk_total > 0 then
  3167.         if (line_total = 0 and 
  3168.             last_hit < length(chunk) - MIN_CHUNK_SIZE/2 and
  3169.             length(chunk) >= MIN_CHUNK_SIZE) or
  3170.             length(chunk) >= MAX_CHUNK_SIZE then
  3171.             
  3172.             if length(chunk) <= MIN_CHUNK_SIZE then
  3173.             first_hit = 1
  3174.             last_hit = length(chunk)
  3175.             else
  3176.             -- trim off some context, but not all
  3177.             first_hit = floor((first_hit + 1) / 2)
  3178.             last_hit = floor((last_hit + length(chunk)) / 2)
  3179.             end if
  3180.             
  3181.             save_chunk(file_name, 
  3182.                    chunk[first_hit..last_hit], 
  3183.                    chunk_total)
  3184.             new_chunk = TRUE
  3185.         end if
  3186.         elsif length(chunk) >= MIN_CHUNK_SIZE then
  3187.         new_chunk = TRUE
  3188.         end if
  3189.     elsif chunk_total = 0 and length(chunk) > MIN_CHUNK_SIZE/2 then
  3190.         new_chunk = TRUE
  3191.     end if
  3192.     end while
  3193.     if chunk_total > 0 then
  3194.     save_chunk(file_name, chunk, chunk_total)
  3195.     end if
  3196.     close(fileNum)
  3197.     return 
  3198. end procedure
  3199.  
  3200. function look_at(sequence path_name, sequence entry)
  3201. -- see if a file name qualifies for searching
  3202.     sequence file_name
  3203.     
  3204.     if find('d', entry[D_ATTRIBUTES]) then
  3205.     return 0 -- a directory
  3206.     end if
  3207.     file_name = entry[D_NAME]
  3208.     if equal(file_name, log_name) then
  3209.     return 0 -- avoid circularity
  3210.     end if
  3211.     -- check skip list
  3212.     for i = 1 to length(skip_list) do
  3213.     if wildcard_file(skip_list[i], file_name) then
  3214.         return 0
  3215.     end if
  3216.     end for
  3217.     path_name &= SLASH
  3218.     if equal(path_name[1..2], '.' & SLASH) then
  3219.     path_name = path_name[3..length(path_name)]
  3220.     end if
  3221.     path_name &= file_name
  3222.     scan(path_name)
  3223.     return 0
  3224. end function
  3225.  
  3226. procedure usage(sequence g)
  3227.     text_color(MAGENTA)
  3228.     puts(SCREEN, "\n\t\t" & g & " Guru\n\n")
  3229.     text_color(WHITE)
  3230.     puts(SCREEN, 
  3231.     "Enter keywords that will define the subject you are interested in. \n") 
  3232.     puts(SCREEN, 
  3233.     " - Upper/lower case is not important.\n")
  3234.     puts(SCREEN, 
  3235.     " - Words may contain * and ? wildcard characters,\n")
  3236.     puts(SCREEN, 
  3237.     " - example ---> get? input *routine*\n\n")
  3238.     puts(SCREEN, "---> ")
  3239. end procedure
  3240.  
  3241. function blank_delim(sequence s)
  3242. -- break up a blank-delimited string
  3243.     sequence list, segment
  3244.     integer i
  3245.     list = {}
  3246.     i = 1
  3247.     while i < length(s) do
  3248.     while find(s[i], " \t") do
  3249.         i += 1
  3250.     end while
  3251.     if s[i] = '\n' then
  3252.         exit
  3253.     end if
  3254.     segment = ""
  3255.     while not find(s[i], " \t\n") do
  3256.         segment = segment & s[i]
  3257.         i += 1
  3258.     end while
  3259.     list = append(list, segment)
  3260.     end while
  3261.     return list
  3262. end function
  3263.  
  3264. if platform() != LINUX then
  3265.     log_name = upper(log_name)
  3266. end if
  3267.  
  3268. sequence cmd
  3269. cmd = command_line()  -- ex guru.ex words...
  3270.  
  3271. euphoria = FALSE
  3272. if length(cmd) < 3 then
  3273.     usage("Current Directory")
  3274.     cmd = blank_delim(gets(0))
  3275.     puts(SCREEN, '\n')
  3276. elsif equal(cmd[3], "E!") then
  3277.     -- search Euphoria directories
  3278.     euphoria = TRUE
  3279.     if length(cmd) <= 3 then
  3280.     usage("Euphoria")
  3281.     cmd = blank_delim(gets(0))
  3282.     puts(SCREEN, '\n')
  3283.     else
  3284.     cmd = cmd[4..length(cmd)]
  3285.     end if
  3286. else
  3287.     cmd = cmd[3..length(cmd)]
  3288. end if
  3289.  
  3290. log_file = open(log_path, "w")
  3291. if log_file = -1 then
  3292.     puts(ERR, "Couldn't open " & log_path & '\n')
  3293.     abort(1)
  3294. end if
  3295.  
  3296. word_list = {}
  3297. wild_word = {}
  3298. for i = 1 to length(cmd) do
  3299.     cmd[i] = lower(cmd[i])
  3300.     if find(cmd[i], noise_words) then
  3301.     puts(SCREEN, "ignoring: " & cmd[i] & "   (too common)\n")
  3302.     elsif has_punctuation(cmd[i]) then
  3303.     puts(SCREEN, "ignoring: " & cmd[i] & 
  3304.     "   (contains punctuation character)\n")
  3305.     else
  3306.     word_list = append(word_list, cmd[i])
  3307.     wild_word = append(wild_word, find('*', cmd[i]) or find('?', cmd[i]))
  3308.     end if
  3309. end for
  3310.  
  3311. if length(word_list) = 0 then
  3312.     abort(1)
  3313. end if
  3314. word_count = repeat(0, length(word_list))
  3315.  
  3316.  
  3317. integer first_char
  3318. -- prepare char_class[] for efficient detection of a 
  3319. -- possible first letter in one of the words
  3320. for i = 1 to length(word_list) do
  3321.     first_char = word_list[i][1]
  3322.     if first_char = '*' or first_char = '?' then
  3323.     char_class *= 2 -- select all allowed chars
  3324.     exit
  3325.     elsif char_class[first_char] > 0 then
  3326.     char_class[first_char] = 2
  3327.     -- select upper or lower case
  3328.     if first_char >= 'A' and first_char <= 'Z' then
  3329.         char_class[first_char - 'A' + 'a'] = 2
  3330.     elsif first_char >= 'a' and first_char <= 'z' then
  3331.         char_class[first_char - 'a' + 'A'] = 2
  3332.     end if
  3333.     end if
  3334. end for
  3335.  
  3336. file_spec = {"*.*"}
  3337.  
  3338. -- quits after finishing current file
  3339. puts(SCREEN, "Press q to quit\n\n\n") 
  3340.  
  3341. sequence gp
  3342. gp = get_position()
  3343. count_line = gp[1]-1
  3344.  
  3345. object d
  3346.  
  3347. if euphoria then
  3348.     d = getenv("EUDIR")
  3349.     if atom(d) then
  3350.     if platform() = LINUX then
  3351.         puts(ERR, "EUDIR not set\n")
  3352.         abort(1)
  3353.     else
  3354.         d = "C:\\EUPHORIA"
  3355.     end if
  3356.     end if
  3357.     if sequence(dir(d)) then
  3358.     -- reduce noise in Euphoria Help
  3359.     skip_list &= {"*.HTM", "*.HTX", "*.DAT", "*.BAS", "*.BAT", "*.PRO",
  3360.               "LW.DOC", "BIND.EX", "EX.ERR"}
  3361.     if walk_dir(d, routine_id("look_at"), TRUE) then
  3362.     end if
  3363.     print_chunk_list()
  3364.     abort(0)
  3365.     end if
  3366. end if
  3367.  
  3368. puts(log_file, "Searching " & current_dir() & "\n\n")
  3369. sequence top_dir
  3370. if sequence(dir(".")) then
  3371.     top_dir = "."
  3372. else
  3373.     top_dir = current_dir()
  3374. end if
  3375.  
  3376. if walk_dir(top_dir, routine_id("look_at"), TRUE) then
  3377. end if
  3378.  
  3379. print_chunk_list()
  3380.  
  3381.  
  3382. KEY.BAT
  3383. 28
  3384. @echo off
  3385. ex.exe key.ex
  3386.  
  3387. KEY.EX
  3388. 364
  3389. -- find out what numeric key code is generated by any key on the keyboard
  3390. -- usage:
  3391. --          ex key
  3392.  
  3393. integer code
  3394.  
  3395. puts(1, "Press any key. I'll show you the key code. Press q to quit\n\n")
  3396. while 1 do
  3397.     code = get_key()
  3398.     if code != -1 then
  3399.     printf(1, "The key code is: %d\n", code)
  3400.     if code = 'q' then
  3401.         exit
  3402.     end if
  3403.     end if
  3404. end while
  3405. KEYWORDS.E
  3406. 1052
  3407. -- Euphoria keywords and routines built in to ex, exw and exu
  3408.  
  3409. global constant keywords = {
  3410.     "if", "end", "then", "procedure", "else", "for", "return",
  3411.     "do", "elsif", "while", "type", "constant", "to", "and", "or",
  3412.     "exit", "function", "global", "by", "not", "include",
  3413.     "with", "without", "xor"}
  3414.  
  3415. global constant builtins = {
  3416.     "length", "puts", "integer", "sequence", "position", "object",
  3417.     "append", "prepend", "print", "printf", 
  3418.     "clear_screen", "floor", "getc", "gets", "get_key",
  3419.     "rand", "repeat", "atom", "compare", "find", "match",
  3420.     "time", "command_line", "open", "close", "trace", "getenv",
  3421.     "sqrt", "sin", "cos", "tan", "log", "system", "date", "remainder",
  3422.     "power", "machine_func", "machine_proc", "abort", "peek", "poke", 
  3423.     "call", "sprintf", "arctan", "and_bits", "or_bits", "xor_bits",
  3424.     "not_bits", "pixel", "get_pixel", "mem_copy", "mem_set",
  3425.     "c_proc", "c_func", "routine_id", "call_proc", "call_func", 
  3426.     "poke4", "peek4s", "peek4u", "profile", "equal", "system_exec",
  3427.     "platform"}
  3428.  
  3429.  
  3430. LINES.BAT
  3431. 57
  3432. @echo off
  3433. ex.exe lines.ex %1 %2 %3 %4 %5 %6 %7 %8 %9
  3434.  
  3435. LINES.EX
  3436. 2734
  3437. -- lines.ex
  3438. -- Count the number of lines, non-blank lines, non-blank/non-comment lines,
  3439. -- and characters in a text file or bunch of text files in the 
  3440. -- current directory.
  3441.  
  3442. -- usage:  lines.bat [file-spec ...]
  3443.  
  3444. -- example:  lines *.e *.ex
  3445.  
  3446. include misc.e
  3447. include wildcard.e
  3448. include file.e
  3449.  
  3450. constant SCREEN = 1
  3451. constant TRUE = 1, FALSE = 0
  3452.  
  3453. function blank_line(sequence line)
  3454. -- TRUE if line is empty or all whitespace
  3455.     for i = 1 to length(line) do
  3456.     if not find(line[i], " \t\n") then
  3457.         return FALSE
  3458.     end if
  3459.     end for
  3460.     return TRUE
  3461. end function
  3462.  
  3463. function scan(integer fileNum) 
  3464. -- count lines, non-blank lines, characters
  3465.     object line
  3466.     integer lines, nb_lines, nb_nc_lines, chars, c
  3467.  
  3468.     lines = 0
  3469.     nb_lines = 0
  3470.     nb_nc_lines = 0
  3471.     chars = 0
  3472.     while TRUE do
  3473.     line = gets(fileNum)
  3474.     if atom(line) then   
  3475.         -- end of file
  3476.         return {lines, nb_lines, nb_nc_lines, chars}
  3477.     else
  3478.         lines += 1
  3479.         chars += length(line) 
  3480.         if platform() != LINUX then
  3481.         chars += 1  -- line in file contains an extra \r
  3482.         end if
  3483.         if not blank_line(line) then
  3484.         nb_lines += 1
  3485.         c = match("--", line)
  3486.         if not c or not blank_line(line[1..c-1]) then
  3487.             nb_nc_lines += 1
  3488.         end if
  3489.         end if
  3490.     end if
  3491.     end while
  3492. end function
  3493.  
  3494. procedure lines()
  3495. -- main procedure 
  3496.     integer fileNum
  3497.     sequence count, total_count
  3498.     sequence file_names, dir_names
  3499.     sequence cl, file_spec, name
  3500.     
  3501.     -- gather eligible file names
  3502.     cl = command_line()
  3503.     file_spec = {}
  3504.     for i = 3 to length(cl) do
  3505.     file_spec = append(file_spec, cl[i])
  3506.     end for
  3507.     if length(file_spec) = 0 then
  3508.     file_spec = {"*.*"}
  3509.     end if
  3510.     dir_names = dir(current_dir())
  3511.     file_names = {}
  3512.     for f = 1 to length(file_spec) do
  3513.     for i = 1 to length(dir_names) do
  3514.         if not find('d', dir_names[i][D_ATTRIBUTES]) then
  3515.         name = dir_names[i][D_NAME]
  3516.         if wildcard_file(file_spec[f], name) then 
  3517.             if not find(name, file_names) then
  3518.             file_names = append(file_names, name)
  3519.             end if
  3520.         end if
  3521.         end if
  3522.     end for
  3523.     end for
  3524.     
  3525.     -- process all files    
  3526.     total_count = {0, 0, 0, 0}
  3527.     puts(SCREEN, "lines  nb-lines  nb-nc-lines  chars\n")
  3528.     for i = 1 to length(file_names) do
  3529.     fileNum = open(file_names[i], "r")   
  3530.     if fileNum = -1 then
  3531.         printf(SCREEN, "cannot open %s\n", {file_names[i]})
  3532.     else
  3533.         count = scan(fileNum)
  3534.         total_count = total_count + count
  3535.         printf(SCREEN, "%5d%8d   %8d   %8d   %s\n", count & {file_names[i]})
  3536.         close(fileNum)
  3537.     end if
  3538.     end for
  3539.     if length(file_names) > 1 then
  3540.     printf(SCREEN, "%5d%8d   %8d   %8d   total\n", total_count)
  3541.     end if
  3542. end procedure
  3543.  
  3544. lines()
  3545.  
  3546. EXW.EXE
  3547. 73728
  3548. MZÇ  ╕@Ç║┤    ═!╕L═!this is a Windows NT windowed executable
  3549. $PEL╧{8αéü  └á▐╨≡@ 
  3550.  l∙ö≡l    ·UPX0└ÇαUPX1 ╨@α.rsrc≡ @└
  3551. $Info: This file is packed with the UPX executable packer http://upx.tsx.org $
  3552. $Id: UPX 0.93 Copyright (C) 1996-1999 Laszlo Molnar & Markus Oberhumer $
  3553. $Id: NRV 0.61 Copyright (C) 1996-1999 Markus F.X.J. Oberhumer $
  3554. $License: NRV for UPX is distributed under special license $
  3555. UPX!     3¥mª├*ÅΓJ╗l\&ë▌H≤╠δ²ÉSQRVW║    ╣∩■▌╗1█╛ë ëë╙1  o∞ ëï    ╗â■}ìIë╨┴·+┬╤■┐√▒°╔ëâ4â├â╞â√xu╚╣² vQ1╥1÷;⌡ ~Fâ┴â┬o∩▐╜%ëè╕ü·pu▀ΦT╞@¥0≈εúä╟ É╟$╦ï»"─▀7d9 ░#└╕├~∩n'╨╪ïëod┬F₧ñ┐¼@É¿ÿdöá@É£î╕▀■≡?_^ZY[├ï└│ë┬;\v┐▌kh█╕╣3Σ/Çë ⁿ╛í
  3556. ï5ì)╓╒≈ß╪ΘJì@ â= /╖B`âI╨╗2■∙╢7┤3ïO`┤IìP(▓1╞^`┤Gd##G≥Xêdd22╥<ê dê ▄XÅU╣nìyp1φïQë╬àε■σ╥t!IèX ïü√°Y~-╤ho√╪b@J A∙ε∩▀Xën9∙u╠ïkXà█4╪1╥èPòôyü·╨█    ╟
  3557. »}iX]a╡╥┼╛âïx)s▀¢KI ╟T▐² ▒║┤Jpïrà÷t(ïëZ│^ ë≡;╪ßAìå╚┤â-5~─■╥*┬9╩u╩yºDΘ╟~^0<Rα£ëa╪à7╢ß±└u(║δ;4ÄP╕∙■axtαt┼:ùDZ╦m┴MGAb«w╗╢k 0ìB┴ΦïÖñ╝ï┘ï█■c╢ïâΘëXië>ⁿxÅcü= v┼ ╣ ÷.δFì
  3558. ñë├âπ»≡ ▌ä?╓9╦|â└)╪Ç├°ê⌐G╗╟ùfτε1╔δ─╖ô1└Gß┬èB╙=Ü├ës∩≈A╟ë┴=«~ :C ≥÷┴°╢;}âΦ▒╘╬╢B±╖┤ë╤nk;å>â∞═R╓jΣæCûC┘ï┴ë╚v÷ìVñ.$ë≥╨╥ φ┐²t"9╚u7╪δMë╩ë┼ë Γ)═âτ1
  3559. m∞δ9╫5¥╔╤u▌rk┼)╚ï@▐╫∩ ┬╢
  3560. WG┴F≥Ñè╚Çß≥ñ_└`Ä ₧%â─V¢4÷╫çôà╟ìCJ╟█╢ε╖ΓH┬ë█ ▐▌w·╟≥╘É7ï\$/╗W█▐ΦSïL    QF╒0¼╜╫Z╩c%D'°÷«ⁿ¢╟)╔I√≥«≈╤ñ┬oK╖£╦ê╞■à╔~Bè]·╞àúè▓KëHⁿ∩╖d}╖╥┴  Ç_ª├Çp;üÑ8╚,ïë▌¢╣â{!h╥àπ∩^╠└Rü▀▌â°║▒ù╖; |6u
  3561. @─├0wÄ92 É!8cgä    ░╩╛ú9wë╚╙±)Xï@u█╞íÇx    Ω N≤┌)╓▌ \5⌡(╖╦┬2ïKLHC
  3562. ô└n    >;U╟ç╨ ╣Bïíφ▀█FïY├2Bⁿ=)εt    ≤å[πƒ┼δπïiuß╚7ö) B0¥\ë≡]╗ H╪~ëσü∞£ üφ┐▌╙çé5Ej¢h4∙Θ@π¡√ í9╨rPhxE░é;╥╗▒C╗) ╕ ─ë°*k+╤H┴αÜ!CfB²c╧]Ká|
  3563. á"┴πë·ïC-}k╜╡]vHß(┴ΓIín█╞φ5"ïpKV:Φ J▀k╧▐╤╪▌╓ªp∞┘╛²▀}JïEJ[râ}jVr ╪╚o ub\äQ/║■é2âxd}Gì@c▌≈ÇìEµ╘┤Éδ0ΣêeµPIB╪»}ú╨∞Pα;vú█yvá;⌠tj▓┴τ¡█√@vDb╥êUµ41ï▀RâFl╔ug╤u_√æ╤PïFéhH╚ütE|ipwvÅδ÷δE~ï≡φ "~zδ(=╛o%îm.
  3564. q4╟┐²┴QZE^ïuA}z┴µü 4o╟┌vuI~
  3565. N█]▌]Rµ╢╟┌δ%RïBR¼ ▀╢⌠Vδï    ZNp╢┘û▄VZRδ:HB░m[ù}*E╟╚üM╪ôZJÿ║▀▒DvBΩÄAü╥┐≡╢ì¢f(b UΣ∞▌$∩o╗XE1 fïUrüΓb║╪àn!nâÜuh∞oHu,$?å╕#aw[kJfNG▀mJJΣε╫πìÑ⌡≤├=2└| É;≤Äà*█Enügδ└gÆce║àX└Ü&±¢░╢╗k0É!kσ╗1░Éel) ƒ"'3xV╜ π# ≡#$└)╤úτ°}¡┴∙í┴ßt▄▐;▒╜ú ê3*°╛ £eφΦ(- á}KhWⁿ t╢╤╜A[R,Ω┼=WâVk╙▒_ªA┴`Z┐╗╫(╤óìΣä6sVû~ù⌐ü╕±╪Gt╤░φ¢Φ îhB9≤uµus║ⁿ÷au╛≥╙|ÑÑñq/²▌▓êWèê<òèFΣ╞ï╪╦oGâ╟uΦ_$+'C7<║⌠_╕á╖í▒$¢┐häO╖=#╬"Φ4▒1╫X
  3566. ⁿ{╪/1Cä    "■Fh    _RV╞~∩EC0[úZ≡~Ä⌐k"⌠=Z+<4j╧"ΦV █╢Z`╨oC ┬)╨óD{cº r!A╝Z¼|₧ÿ'╛æpgúⁿN#╨√╪Ct ìòêvπv¬æMsrL6@εα≈}║╕W}│┬áì4 êÅ÷▀Ǽ¼░±ïTë|^,$3▐╪%OVáαû3▒h≡B≥╨tz#6c▀f■O9┌uφ'▄"ⁿΘ▐ü|"ⁿ5'≥∩²b_I╫+°úû    ₧τ∙╛╘⌠    ∞╪≡Σy₧/╓îï8αΦ≤=╧╪ °⌠    ╘╧≤<╧ⁿ▄╪∞Σ≡M▒3
  3567. G╟:╕üVΘc╕⌠)┬┴v7┴\┬í@!?Z▐î╪c√╕─#_?Üp°╨Θ'═"╪╪?*r0≈ⁿu▄àåⁿc)┌^í£╪ß√-|"x▄╫jπî╦ïè∞Φ╞Åò■@Σ)╦┴√/Y⌠7>_╓ïYⁿ;%uìX<Z≡îà▄ky╕u≡Éä≤a┴50Σ┐o≡²▄R«Σ;╪▐fâzg┐àÑ■ê%ëf4pfV┌Üj╚ofIê┼┌GúñAt9∙8$⌐H√▒─╨╧ÿ⌠B⌠≤ 4Γåïåì╙├Q "%æÜmΩ≡sùδ&8│╒Ω7╫J⌠äì4
  3568. 9╙h╠@W┐r    ïR≡ µè=⌠0î╪I{HÉ┼É║5)g@ⁿoîE║ë╒τ┐x|7╕¢f╖∞T╒±┬^`█ZαJbΘDèR]#⌡ 9·
  3569.  
  3570. ~CRg╘n£~╒t▄Éw┴R▒$t╜m⌡/⌠╕)ax°┴■à %`7r╘·\O⌠╙ë°1╓µn╖█_X┬v7┐R²┐ÿ║ò°    ╖/ÅhⁿZ▄PΓ?╜AîëΩ9╪Θ3pδ▀SZ╥8╘ `ⁿa╗╜πδB99╩|╖0lÅ1#IÖZAñqOï▒|èPÇ9uJp: -╢mΩtDBv²u;hÄ├0╕;!pü8X6dök├╢Ü
  3571. <YÆ├½R\y w##╗╞(▐└ú╓mfs₧O»£πδ¡ ╟#1B╪ñ/K'╦N╓└╠U ï"ä[2─=2b
  3572. ùôI╬▐╕î=    ÖΣdÆ     
  3573. ╪═∙┤╕w╪σ≥▓Σ 0R.OÜ╦¿∞%V/╦σ╓\Ç╢╦*~Oncô«;τ (µ*B∩═₧u#C?;╖▀{ C"b,{═∩-#&║Ök#≤{o┘»?+╥▓7┘▓╗Å╢+═^X≈≈ ┬k7{ √;░K▓ù╜░ƒ°ï7s²û╜┘# #▄{6X╫'j7V½╢S╨'÷V╪Kτ╢ovƒ▀≡╬ç┘╢ w/f╗ôùç╦( (q╜Σ6÷7;R!Φ!ùù ?û_%▀ç'┌╫kä%ï╞√8{≈ú╦ =£gçq3. $¥ ±ñx╕╩ ⁿ╔╔Θ┤#ä¼, kôvd;v!%X}┤∞Hy. äpuÄåëì∩;╪e╛∞h/JÅ─ë╫╧â√N=║5ä⌐ï=ΣÑ%}9°s└ΘG6ï∩d╨&kvî╛!%|tïc<│└-kà÷#ß^¼╧\╘:∩─╢-\1    ╦#Σz─{-²u╗qï┼│ε2ïÿ0Φ ü²Y∩ⁿ╢⌐#\u ╗t\╢╣!,Ü$
  3574. u▓│╖    uR$,mΓ ▀lv9°te{≡ƒ∞|
  3575. ò└%T└r├    +,é╔âδ9
  3576. ├Üα│6.╗pS'"ç╡┌Ç░@"{<qúä\ î╚Jvç`à>.S'∙"≡═6Kù║î<`▌#∞u.*¼╢░æ╜≈╗kL»f⌡âpHt ú├╢@8∞vδ    
  3577. eeV ▄6FQ.ëÇz¿uc≡32ü■}æ=~░7$#å2äæ-ä¢ñü╠0╩û_)d%ñ(XTÇ"go╥â1 Rë=≡Ö`2-J|çî7èôuDà¬[╟å  ┘Rµ6ε─I≡mr¥▒T√9⌡äïC╢Aè몠f)ö%L«╪ 0σg2wìWxâ ¡∞╢τè»ë-²|⌡╚!╖à∞╔ï52!╦╚■ ÷<cîö±■╛k8½E╚ÇèφN`}M╤Çc╣╡¼├Q7waW≥ç8u$╗>8Σ7»j(auh╗AC─b# S9Y3╢δ⌠;8º[8`: 1;wò6▓G╣{Ñïà,»Φ>▄╧BºK▓¬·Ä║!α▒╤ ò▌\╝Θ=-h╨Aj÷╢Γô░ìjª-
  3578. sü┴└F,≡#▌+O[*ï≈╪y╢ekXr5x    ,┘)U╣▌ß√w┼╤toÜi-aê#6ï-Ç▌ÆΓ┘α3╧sìBle+{╤u5╪Éú+=▒·ì%$åΓÖÄc+J¢ïâ├ô
  3579. ëφ3ûâαVt| ⌡─φæ╕JèH5Ç∙éDë│A'_+iá$J3╞j╔╫)X¢ê8╜i÷áC0Å╣∞$╤å╚▒e!╣|gäo»    __ë┴9≥g└ü    ΓU%,!àKåäñ▒M-/+ à┐≤V░e 8Ö.ïöÖ.>$â:3a░ ß█êo :Vò ┬É6e╢ƒÑΣ6┴èBL< Hⁿµjou╗\▌╚H╛╟éjÇy$9&Σ╨₧BdÆôΦH╚┴Σ╚▓88)i@
  3580. g#K╚ë╚$▓ë!ΣÆô╨5≡#s}`╒âY╢Çⁿe¬╗ ╣ìB8δm5é╓■▀c┘    δ áz╞δl┬hâä┴n≡bΣÉ╜-Φ╡ä6Xeà≡+δ)%╧òh²öé┤= ░1≥¼<oAxïBé uó#▀;htδ<4úΦ:₧¥▐ûu%t¥[τ≡Wa░Y┼úò⌠╨o,ä╤╦₧▒JBbü¥cW; ï░&╨ uòs╦rk²k╤¡Æ»ÄαB±Xüⁿyφë-&^RÉû┐'S,lañ═∩6ç┴╚=¬ê    ▒6;▓0┤╚┐║ìh4ë-▒GÇîìAå├µ'ÑΓï<┼Z=;íG▀ëδNMΘ`└Ä`╕T1δécí    <9╤r╝B/F∞cs9╩v±«;▐Σ┬Hòφ┘░æ¿╞└1
  3581. 3╞A┬┌ìG
  3582.  pkî?≥┼Ç■D$ÇKæé)°╨v⌐d<ghƒ2bC»XΣµ╜.┼\ⁿp)╞&≡v)R½b¡L╠┐#Γcl4Φ~eF    A8lHo    9∙r┘εp)┤Ä╕; Lz╣ö& Qkê û0f╛º(3V╓äτ╨+üsÆhΦΦ░H\≤ ƒÑ    ^t
  3583. «ª├■ay┴â√u?'"ir [╗S¥    [u╞VΦjnàñX[Eêulåma-ïà╠!üE*kÇπ/ä╤╚=╞K│┴J`eQ"╚:H8╞c┌YcÉ╡jÆ╥Çd╪a<╔╦P╞Ç·O`W┬l╚√ÄÉ+u┴╚H&╣@p≡AHd4y[V┘EF║@H¡ñƒ7⌡τü╔-╢}¢░éÿ≈≤⌡ï⌡.δ╡┴eZ7h:▌√⌡uV┼\V½MP╜│    ▌╒╛7ïF
  3584. K?-╕g%¼!ëΓ╚╞X┴(c5ë±µkç4│qΦ^ ■!#fâ}$äS(àavD!ÇüäH╫≥ ÆC]êäJÇvMz₧ûu2ò4X√öÑ_╦q±èJI├╪α *èj    m,²╦Z┬tq▒4▌R╥▓xoKë╟a╖▀L¬I(èA    <H!<G0 r╚┴╞[╒╤!y╢zΦ?jYDëX╗|Ü¡dΘδR½ñ    ╦Θ≈BhPBo8┼B┬Lû╟╚╔!╡╔É(╡B3¢└U₧k íÅ:¡h≥Θ¢,α█!aNPjπ▌%α╞┬F°ºMâ╟jêFfí3hΦ[1ëfëFgq¼╘»ù$■@ïR?╖τñ, l|╟+v≡w£▀-L└││┘[ÑN, B%╖g ┐ 0x√wo╒╦p Ç╣w
  3585. uìY ÷û╜⌠\bj║âì<_"6 .└Σ┼╨║Pz)x@aD    ╞}─ç╢Σá    s╟Eà½∩ ╘oè%┐╩└c á_tpACëë▌" l;4⌡∩0f⌡;Σé{¥Ç≈ì«íú%ë;z{╨└PΦwKê|√╘▌Nc╦"Φ\╚≡Öh╠_!ëC■r╚╪:&├d$3K⌡╕9²ΦnÆï╩?╙î╨╬öTvu<#°÷═}ku╣q▒üxêδMv╙┤δZ┬Σ#î┐ äa(fùW╛Aª0éBΩÿíè÷v b@ë à/,ú ö╛5┌Æù╗╨~ 1█ª[X
  3586. >ôV0b▀▄ß÷lAX¥²9±|ΓF▓╗MÇ3:W║í─íK└ºµ$╝E]$╕L▌X╓~¿+v.┘Y,÷+╚]Wg;+≥╣∞╢╕¡╘>Rh_m7,╦╬ä<≡║5.Σ┬vD╘<ä╨%rB╒ hΣdè8°ªXε╞▐].⌠╕u╗╕êFΦí/{É╧    ╪DGu└RâÉ ß╪∞dAêR╥╒öìD$ P ╕QöαP≥∩╟εOVRïàtS}8.▒╪╪äA±ë5æ    ║Q█X;▄àV╒o▄ö
  3587.     ô╨K(vä/εOSRìtëIT06╘ÅKÉëδ┤3éτWT¡
  3588. ╫ÜTR┴ S±ÿU┌]°`Z$Θ.âx▌▄≈├"ê6É!
  3589. Çîⁿ░$δ'l«┌█*╕t├`╣D╞╒─F≡▀Å;j┴EîR.  :Gä╔Pqù3╓çΣ¢²∙7─ (ΘÉ!;;+4@█▓.LÉï┴=,}@$╨i*┐5ô w≥îV╝¿╤
  3590. ≈â-└╠*■ ╚δ╣PE▌∩a╗Gj#║
  3591. VⁿΓ3╣ o}o»BÇ à1÷f>╓,═╥mq▐Γb'═╥╪5╨╥0╢7÷½╫E¼4╘╖l-@ík─▄╣R█φûW┌1,≥ÉδºA¼â¢R ╢╢Sp*╔ïlëΦ╛Pë*·t■AΓ ▄┴·îîî= ╘╥îîîî ╬╨îîîî╓┌
  3592. ?Jîr]8VÿúP╤n9¿hpü f=`╙tìzÿh τX4═2C╕d░E äf LîI&ài6u,D╕▄>Sìε0≥h╗ªmëäé▀hεï$ñw▓=ì<SΦ+°ïäc╠û▀=├█f╚/ÉÅε╗ ╕ε∞8ü4Np H╣≈┐δ║Of,ì|$ Hìt$ì╜ ═`)╪ü2o[░»╜ 0┬ L.RÑÑÖα6s╞ ( ┴αù`π*Æ╪▒4Ö1╨)Å5x¡≈[╝ 9├~p7á⌡■ïåε≈u≈âf(*┴√w≈┤δ"ìF[╗5`â4V    $o=p░¥=Wh╘δ87╔▒╟\▓率═Ij╒BÆ∩┴┬$(┬Ü4çê╠L?à ∩HÑ╝╓0ΣÇπ$≡╪╠Aÿû Pë∞╞{É╜PO0 QJ%sOT┴π$    ë≥╔t≈÷≥T$║╪╡ôà
  3593. _2└ò╦╪≈╞,╕E▐(xFC:R╫╛O⌠òá╖Ω5?|
  3594. ╨╚φ¬ëÇá}4╓ê▌ äÇWα╚┤½ì▌%╚<    ▀    <ó╪MâΣ°π:Äf·U vÅ═" > ≡▀,$në∞]Z4╔KV╠p▀5╘$┐
  3595. ╕(≡ü'▒└≡ε▄╣ ƒ₧╨:½-≈┤└≡1¬▀-!àφ~%ì¡¡F¡ΓΘ╗%█ªRï:q÷üë2B¼┴Γδ#S╪|IPΘJo@ìU0Dl;tPεëÿ∩q ggz¼÷.f7₧)ì òf¡R╤AΩ»òƒ«╜Γj ╚|HVläα3ë?∩B≥└╧\δÉ≤lr$ß"τº∞(F Bå ╤eë&?ⁿ⌐┼,─▌`≡▌ù█u
  3596. Cêº╒└9kêv6Hσ╝ ¿èC╒O ä¿ô9ïL╢/r╚┴─    Σ,═ ╛⌠Q∞O -P6Dxδíh╥╬ölIxOΦüº■Z■├ü<┼ÄÖ▐╔╪~à∞αsG┤╨7K_┼H0cD╗]:i'╫àä╛/╕F╤G▀tëΦ+┘╫ïäj@≤¥%xD8VÅòj'Z╒`δ ∞∞FCOGèfìO÷─╡;÷L╗r┼ïÖ┤Ü!Θn=hsÆfHviåñd a╒ì═└ïFSä)Vzë7jè    ┬á    ╝3 _üö δ╓e√âαF.$)╧ ═( Yå∞|>?J#£ñï£/Q>╜% ü├δïöjBà╪äìq¡N▄R#8é─zLRX╘├│ü─┌]╖|ìvRw· Ö Mr k╫ t¿┌°ü    DÇ√╗åd▌╣?û₧|[ª▌Aü√V°ÇP║u÷┬└jM 2,╧3Zé Ç▀8∞░_Z╕M!╨A/0±p║¡ 6¡    ü≥,╙@mòQY░ÿ²kQ ┌a╔┐ODT╪─┴╛Xt)║X╡d╘-¿|*FT|!X6╝/╢╟&ícMyb╥ç┼`ÿì╨πïKQ┤üÄRQï≡x╦┐▌≤    ╛■O1╔δ(â√'ëôx-CO╞δ² ╚st9╬rë≤ë╩)╦ë°C=⌡|"BÇ¢└H.└ çÿÉCÄ┤e■╤c╦¢.ìP╗-ñ≈╨pxî9τ≥ëY≈{Wá`{&=₧;4┌d`2▀2_w⌠╗5╒,ç£1X£E"ìwHúvê     [%7!*A-|╕eçE├Çi╞)┬⌠Æ═FΓ@]ú-╙▓YS·"Ròï∩üO╪■¿σñN:HAö0Zoî▄╖"┴╟P└╞└îä╥|d»ßå╟═`≈┬çu#3ß╚à▄ô▐L▄5τ╛Ñ╗ ▄╫p█\6Qó╨1h▌Σ ?╖¥pΣ√▌X{`■╖╥├ƒσⁿPß⌐ía╧ÉT╔╞óτVåpëC2τ└KM╤tB4N~▌╪Z°7±·@èê\m≥â■í]╕ì9┘ptδ^¥Ω▄½ vm4,6TlSÅBδR#Ü┴k'êtr¼╢╪$≡╦╨°N╟ïà÷~╛@√¬╞ [~èH BëKⁿ9≥|∩i╪2`Dyƒ╛αα╬ ~}0╪1d    █ù-h╒╓K╥$ú≈\;∞ÆR?42Q}x»╦wå%ǵeÅ▐X┘W┴\┬┴<Z╖╪▓J≥ë╤ YCæ°φ\╧ë╩P¼a┌├;cß½√.w?îû£ NL@ ╤d▒√qó╬ühΘ█¥└ëè╤≥B╠╚se╔LYHC└N≤`hmY▒┐Zêïöv¼E╬"»z£ ▓æ╒└Q▓#]£Æ─╖δ¥V¼K├▀2ev¢û▄─ä(─SâΣ▓ } Fü~ñⁿSä╞^Bσ[áæzΣD@:ÅH╩≡ⁿe»φD@¡ÑΩ Më,jëΩ%n⌡╢Γù-*3ï:┘÷ï ïIå∙¬┘ó∞{═√╩ »ôOgg╒╫}═┘@▒ìQ╜à+πa<¬╖nÅtßT ò
  3597. ╘ôVLFw¼Kê ╦W-Φ⌠ïò╒,░yk'cÑb`\T^÷R┤░¼÷ÉΓ$uí 2x╢εUm■╛╦ΣC┤ß▓²<╚╠u(δR ▓|▓|LδFtδ:▓|▓|áδ.╨δ"><Y>═δ<δ░┘¿tLΦö@╫4ß╒q3╟╞  B{QÇ8xuÇx ç≈Vu╓;╫ôëδB@â·L|ï«▌σ &?w Σ├╥Ä#.]wvE`lzFiÜ«i╝Yü╣╒ÑkÜ«!=¢¥u▌╬4═G/gEΘ Æ4]╙4á█«╝Ki.]╫╚3±H5ªiܪKf|èÿ╔ÑiÜ┤┬╨▐JÄ4MsyH∞I3N╙4M╙j\}É₧]╫4M¼║√╞;,:4]╫uâΓ■ HVdâ┴A╙rÇyA┐┼i╤║8x@ç6 `▒D<╕123D=ΩP┴~┴@1ä"╘8w█è»)╣@╬ î XÑX ┐═5òd┬╬"∩£n¼6ag    ╕)╚7╚^!╘58 ≥
  3598. ê2┤ ┘+∞─'3X└H^!4≡{┴┬J-c }    ∞ï`    $?╒α,6ÉY,t
  3599. r6h╞x╩,í╖mü*    {`8,7∞G╚nb▓:x;▓ÑÉtFî∞:¿ñα¡╘└Φ-9a╚B.yY0┌0┬╬R≥┌█ñΣ@F«7╝= 2ahx√y>0σçæ·T] ╦89ñ [X+P┬V╪ôW@(}í v?Çα╓övÉ└ä╚▒@¿A╦╞B ╕┴ëk#PΓ&P╜    '╪îdü÷ë ┬t,J bí¥Çô·╕▒»┬┬)Ai╖ÿÉv;╚<ÿA&dBí∞$¬ƒªSh0,R:⌐A(─]╪c╟_w╘[Sÿj┬Θ╩2*≈QP;dWï╣σ┼²tÄJ╘┐░{Å⌐3èUäΦä╥t%}|Θ√\äÆpöä÷u∩╖L/^Q█HP?t·ßßó╨Ém-ò╖/Z· t^    tYt6q╗GuJ*~?èε@░¬▀,\ì</▄K0;ñì₧)╢¢x¥{└Ç;+ " ê╨╟@ê9Cδÿâ╦Z┬;╘è⌡≈⌠≡s·|(╘$╒å÷⌠ïvvQLπàtKnE┌Tx╚à\╚É└⌠╜VKN█,σßùU≥Ūè#Çⁿ-αφm    u╘±ë▀e^╒Zσ
  3600. s┬┐┼└╗ 9╪vè0ÄΘ█σ√t
  3601. Ç■<■Hwδ@╣G╩─ª⌡Uw)v┬≡■ú÷ .é╠▐è1 ä└tÇ>.> ÷÷¿¿    \uèfFäΣu╗u╖¬τ,)╛│H~W+╕┬r░O=▄K₧δJαδ└A/g╔█ëv╤Θ╟ì₧â*U#┴└ u╟└[hU¡î4éI█εÿhÇ    PjXää╪▌╤└`╟öP┐a├ φ╟Q0╔ìè*Dz ²    Nmⁿ▓²
  3602. @δΘ8ΘígÖ4$ìû┌╛é,╔@▒⌡  εì▀ "uëu╓.ë≥ t6:
  3603. t2@è^7√∩jB≥δ&ëURY¼╡û┘T Qb'├Fτ uµv8æ
  3604. ª';bM▒ùë83ïQê±<$°Æ·╫æ▓º|╟╗φ7⌡í%QáàÜ<d√v╓Ç=1 ì▒2Y▓Ç▓3s│O▓╢╠,fKmM µLáAìPαéÄα    ╦)╨x╨g▀╜Ѽ/ âΩ ┬'▓ÄV■âΦ i└@£│^` ì╤8fσûnûBDeΓΦûo6@çfΩ╥÷O≡v╣╕5╨1φ╗o▄óÄë┬LΦ='Çd_≈óds
  3605. δ    ╘mⁿ╥╤N@ª┘·┐[1EFt▓╗╩Ü;h░╤&j≈≤₧;    Fzña*ÜXò╗úéd
  3606. à░╥εΣvRGêΦ¬dL;▀ ╗ám÷╟¼¥Γ:MH8⌐@WQ jº╫u=ê∩╕b|ÆS8>?°╬zè╘╡    ä╡qÉGóA║ε▓▌½·ÑfÑñ¿l¿▀Ä·└ ╛ïä4 ñÅç7¬m: ä┴╗Ñf|O%@⌐⌐¬αìÇïª^ú6Ω≈²}±ÄÉ╕≥1█*ⁿä~c▌_ ╠VN\QpìâH-╪V %C~:°¬ï·°£▄¬≡x╓τ
  3607. δ╘yëé!éN TÇ█⌐■9·~"ìQì Z »µ╦ï
  3608. ëK@╜VlC#ç╡ßâOX[T∞ï▐~∩dg8çè╜K┤=`C╜[Ñ,íçσ█ÿ    ÿíL║l¬{≡a┬`╗"%╓εmºÆ6┐
  3609. 0S6¥l@[╚╠H¡┬v∩òα∩╗p
  3610. ■\t=s≡╞╒E│█Sº,w└σ6f│√tSÿL═╠·░`¢═}0╤ty─█
  3611. j╕#CT²h±σyoαu╦ïà╓åΣK⌠èe╧¿╠F ╓α╗ kdyε!∙û»ε'└ìÉ╚gf╒a"≈√÷TS≡t╜2.τ+cö╪sFQ'Σ─T┼|l&éd±áUeáç,═(),tºΩC₧°╕x¼(d∞ôⁿ₧) ±∩adX$0D╕ⁿ╥nl¼ßLD7&{≈=Æ:t⌡»t≡=¥ ñα╦ΘtΣR;
  3612. u┼≈█ⁿ2 .,ù╪Z(
  3613. L═░[$Γ┐∩K    Ç∙eEuì,¢K;╬\¿■è!Ç{    »ä╡â[╤ è@fïK 0Σf%Åmá⌐Z⌠C ÜΓb╪┴φÑ¢%èSQ·¢· bd ▄l^1ÖêH>BπP.å≡~    ÅB∩÷û⌠╓Bfm°"╢ßò
  3614. <ë╛╓NAá7V+;Vh`$#(ï@ï ∞╥X~J│╪[[å╟"▌ë2J>ΓQS+∞7┴;ñìB╤úbÑ▒uw$½▐≡+╫└╞o▌╠IïXE|@ùÇw$▄ïâ/ 29αTòα■uÅ╜E½P▄█}ΓK╖é▒içïè-─╔┤ ┌╤èYt≤zGτ°ìP; Ü íX
  3615. ▐╚ÄbUtíz╖c5æ°@«ú22┘,┐G(╚3╔s(ⁿⁿ"&çⁿ┤╪ƒab╣╞9┴~$å÷╪î#dê╘µn÷│%9±▄σúåΣÆ├?ⁿdÆKí⌠êa?▓D√■⌐A▄&tëτ╛╣▓T┤≈ÑÑ3 µo▒╜φ█░┐âûtU╜ ┘]∙-Bü²╪╔ cE╕úD╪÷┤Mü; h╟ï@╤Ω╜▒SAlö╒Dfµo0
  3616. ╞▐L┴ü='_ƒ=ÿ](╛è°δ    ìJ▄Äòtc;Lt=GMtG*÷£║"`(&=chìü╦╜ç╚▄00<Kìwδ▓ò╪0_ì╥Æô╔╪P2d     bΘ├Wë╙■3"~Ñn║'Ç¢äR╔Σ░╗╤RS?êâX╚K 0ïá∩9)┌╢h╤╟
  3617. Ü 9▌î¿╚É≡v9δtgv#ïü ~─:╢/¢⌐7∩#(W⌠δ*Σ╕'╣²║DCk~ï¼PÅò|Gïl∙
  3618. ┘k┐Fpt-Xx±r╚ñ'┬dε-v¥É═Ç0à▒ô▒3╚╗å÷bü╖Lâ∙£dh╡¡Z╨cΘmÅ─╗^╨è~
  3619. <Ç╧ê┼╚¿ WS⌠T▌í╪R≡Nïm ┬ É 2du╜-ä═u▀║ü%■]{╠░▓Vφ54(@/$];6Fhc¡L2╕[å 0<GΓ-JN2æMÅXδMα%ç≡
  3620. _╕H╔`├<Üñ╔Æφ¢ZIí╗&wÜ@Γ (hz8Hu∙÷Γs&▀üEK█µfΘ1ï?²öë╪=/V£╤¢╜h▀▓    Σ└bu╕v≈╢Å+⌡⌡ °æ
  3621. ╢M╟█Tz_*°Y▒¥Ä╞B▀ß a83tBÅ<uí╨┐80ïjU aΓTl⌠pPmò£Y║ò∞▄¼µ.°;9(Erñ┴■¿El6╧X4Φ╝É╡▐ƒu ╘.P╚
  3622. H≥*dÖ╗,ëÜ╕X4╬`┼
  3623. ±²hH╛╖αÉ%=X╞S    WR½I`─ï÷Tαa∩┌    ¡ YP╕ Çδ,<Q¼ü∙T╝=└│
  3624. t    @└`X,!Å\╪Γ╣É∙=▒Ö.║a╤5─Z≤£└ÉôÉÄ&-tÇ'╕Tⁿn╓░E\¼═½*Æ⌠F╠¼≈╪
  3625. φK° Yw>iv 9B▒e∞┴.═>δ─╗@<1W ═ 
  3626.  dñC^H┘;;G4£-d∙u &9╫╞╞æ═ δÅuâ÷┌X═╝oR ╧2··BÉ|╫°╪a ,Φ¥^e╠`#@ñ╟    ╞+0Q╦&XBl|.AfX ╙·┼█Æäⁿ╧_Åw?ûpê`_«ïu-░r+dâú  çå{⌡<▒9.Å─┘?5à |1ë5t√ü■_ÅÉgC≈²_N-]Zp╚ NE₧φüì╙Ö≤Ü~?á│@æ╕Å ╕ÜìöâûHêeê╘æBëΦ;)%┌╞Ü├φàdGl3│l[q O╡O╦╫v)0á⌐b┴àê_H)<Xf√α╢0ô6▐At ╚╖"~δApn
  3627. úαε╪c╗╙bµxu╕`%'Å|δêudx╕!"v]kppu x'X¬_'"É=2╕TC╕@>ü╕┼╛åxYït
  3628. ■cC╓╜C9≡O`(-»Ω╤ä╜÷t9Φ│m└] Æ├kÇyl╨l└╔╚Q╝─α≤▌~╣;µ@èy& bU▄á J    ím╖æ■%Æèa
  3629. Ç╠ïê ü·±nB 1φ1█êdN¿Iè╓{z┐▒Çí-C=ö9ï!H╕ v¬fò^ù.í+Θz\ÉQ4$BbÑ╖░ò}ö╒c╢╨ΓÖ/ΘB_2Ω,╧÷╘h*"ß,╧≥    
  3630. r▄hQR:R«êδ▄█Gê4δ ╛S⌠míZ(ü╩≥êτÅ│P+≡\└╕`▒]ÆUeó A╞ Coò√~ìD+K╟*"çq^»l██[$╟ùZe⌠₧?╕,╗)░á÷│╬╕û*3▄%ΣD2<²τE=ú└;q\ùbî*┘âφ╕VEa≡HQ╓8£L1âƒÿΣ├"g╢áE╕W■[F5Ö    fâx$}#╒╣├╥┼a}4╥7X#└u║é"G╚@╨║USñ fó»ùLB╦Ä£¬╪╕<í7`BzU╘< Jv)░    z▐5~]╓(,) OGⁿÇI[┬⌠A&░ô"┴H∩NÉφä▐'╔¿% J╣τ╢+xqÆKφ)0ÆP±▒    ñ▒┤╔æ=u$F/Lu½7╝H└]ñc╣╕(~q    Σ┬Ç4µ ╨Xwæ ü ¥[`6%t[î╬3UD╬Z╚eâD╪,-#?∩\1 +=Bë=    àQ%±) ÿ¡ïΘ-╢K∞Hsgµ▀u█└ ñΩ┼Γα¥të°BFë½"cë:┼8┤bêæö0ä╨å-éjÆ╚≈X╫zc7_╒íJ=@GúƒΦ ù]▒ëV(]ÄKê½│π,ΣÆ5F5$    ^äu.ï┼√╬8⌡-&M÷╥├DεD I¬ ·Ç¡
  3631. ó█ñL┼J±NBú²à<C! (#éß5,)X-îd≡B╕≈┤"╤a╝╕⌡ iR┬?{φ∞ûÉWV\kl±ñ─èyZ<V╪èYÇ√╪A
  3632. ■wfüπ k,k÷wPφmΦà╞A    fëAowâ·∞QïY$╠ì4*o²7Rï£40WSë┬j╖y╣3A¢ë£7    ╗ÜL╨{Σ▄ëå!90.î8░╦8w\╣@t¡╨yyü≤a≥üï▐wßîdü)ôrüÅL@Gúä Y∞ #ïH≤a1╝öæv∩δW"─0)F"-6úî84Σ"┤·╡sdZ╢╞@    H#≡╢ÑAB^(Mì±)╣kHùoºr±G/┴ ÇK
  3633. î╙╚Φ╕ô«#P,RΘ°9@b╚ö╪πÉûûMö┴!90ìAó╟▓÷╕5|Næ!αñ╚Φ\J/╥òÜV½|Y&╟B∞─└8/w⌠0èP█    tδtµá═]
  3634.  l╨[-mxWj▐Åh⌡ü δV:ä0Φ√QïpVHè6å╙├%₧▒╛±5ªFM▌é"cë_ò╞ß1/uö┬╖╕▀%┬¿π╢÷╥n█╛=ìF
  3635. ≥êG    2/░⌠╒à|ïw-■AG ë8î╙╡¥-E#B¼o\Ax─╬h<C]y╞Gt┘ΘÖΣ@6╓{$₧u ╗@φx▌bw _.a╤HN≡& ç $╨╤?][Ec%₧εû┴CZëY≡ü"8;-╒ɺö -╥ Ed  xén&╟ìsú,╥[o5`]╚d╠rY5>┬µ3±o`∙CïXèH4║ZR∩ä╗:xàKb≈TX/5    qâ}um╨ ╔ ╣2Dô╨⌠£╨:)w⌡δ%`╔X╤öÉm╜
  3636. £Y┼Ü─xAFKz╕#│▒·(
  3637. oD:V╦bÄ¿N²V
  3638. ₧α|;Ä≤
  3639. Y▐
  3640. <|&«?î6└fC░í■£b?╪█│évrX.tT    | ~&┌ó ot28î!rL Bß╢dl≈b°qKfⁿ9$çk╚iαæÆcEpTe╨VaL┘Çq!¢ëjDyT╕ ûôêô,TR┴ÿqydφ∙25ÿ1πBC≤ ù╚2Φ`ræq²ñAÉ╪°Æ╙╨o┤èKuYïHQ;QJné▐╝!)ë╙,±ï@⌐°à₧@k±½û<RP° Il▌Ö,╥$ª    ╕¢─┴¿ò(1÷≤NÅh\à α└[ⁿ êâ²¥┤ ₧B⌡╚Eߥ╜K,┼╖\ⁿAD4═╟A =¥Æ╙a_D'($âL║s#Vg¿
  3641. ëkäτ ╒Ñ8r+┬ë╪Σ╘XVLXIsé≥É»µ▓V\√â√@d√√∞¢─`}ìCúï ₧¡"╘░▀Tn╚çjsÅ [0╔δh╒τ▀àφ¿]°╫-á¢fïQ$ªfÉrv¼àΦ83HêBhv∞Mj░°oêv╦&Kv@;╥░┴╟ó╟Lqδ FbCZú(∞ì₧    '∞ßEï│ v+,║úΦs1<.¢mCCCσïHì╖v╧╩o╤äTæp ╜xt─εT ºh ▒├═tD Åç,Fp4 uΩN╛╚Dp    É* û╨!=&■d┴B&WÆ Fº╗xí^ê╜≈â²ΦΦ9╨~ú
  3642.  Yb¼X5tD,│K ╚8É┴æ┤ë≈│4│«ætd▒è╚YW,d"E'O╠Γîâ,σp√O╫4╙╤ëë#öÇ GÆt$###c@8dv*ê╣Z#Ríwñ (TZ╙àΦÉé»°{ⁿ≈R÷é╦µ~BσvZ¢°│ä8α4╕¼Φ
  3643. °ⁿ▀ #l{j<åà╚Ö∞0.w▄H╗d XRdd▓g═äª╗|∞'`é/r╢zT,o±÷╗¼!Çⁿ0|h9c8#, dÖè¬█ ┐uS╛}Θ0»╩@╦è(ì╥▀Y√⌠äφuδ[┤|■í²)æ¿cô┬a╜≡Σa|└αh█ΣÉαö·*HTçYî▒/▀Ü╟@äR"OèúGⁿ⌐╩┬Væüâ ñS÷╞ܽ0£nl╓)`<Rup_R╕!┬F*≥q0ªx≡P:Æ∩≈^√░^pÉê[Q2;╜ùö°ädX(1è5%\├Γs±é╒ª╬P█<G╞ò₧àí|HFûgd3ñ)@⌡yÄla├Y⌡°┘Älz«úΣ╣|ô£A╧ƒl╧bdæ∙{π¢nGçΓ╒zτBå"╠à£ßT dys█|22<'
  3644. |║₧╪{.|╬<@uQ╜Aùg┘
  3645. >▓¥|íµ▓╜î₧~(τ¥M_KΦ▒uÿ╜I,äM5P}ï8Σ╩$rH╩lôtIÄ(àTR_┌ÑaqΩ    uâ;╡g√nLδ¿á═εÿ|δɽttµï|Oƒï┌Ü"cα¬ëO╩¥¼┼ J╪╚lk╚`öÆiα%ú╚├▓ö -≈Ü£8aD╔╔ûdw ∞╚1âcp; ~((dτFT╫dÅ"╓jwh`%î(Bàα!0'╕x╘ú`0╧¥═éz}U∩±
  3646. 1Öú(ëα!zâÿO·┼*╞l5,┤²&|╤,¿ ¼ï½■Ä╨`,£)╪9╚}╝QCx    │l≡+     ┴,öCS>
  3647. f░¼Fαg }@f$▐t6    ╪|,(g?k-╨P~    ╥P╔(╪+⌡rtÇZ9╧üL╪░ZkBM2╔╚5/%╫╢$ôg┬*g?G∩└=ñcδIgδ
  3648. UEΣ Σu█Æ∩╦ê=??%*╖6 #*$╕α╒ÆKÖl╫Ω
  3649. @¼P├ë╙┼É"hÉ¡Φ╣╔┐}|▄K»7║
  3650. ;⌠╣C¿xΦ7hp,┼ \≈í ²w╟àB╗>Éδ<öδ5║>_%ç6*£δáSαH$¼5_hìK╨Ωÿd≡╖√╖°÷─t+Ç>u3╛3¿┐2º2óqë·═Çò}!░;-Y¼&9Yc35■╔$n& í_1 z∩⌠0uämg÷l┬úû≤┤╒δÇ2û-!<j{    !▀j·┐S─Å┬í╧╓cë╧Θ    :πI╚g£üßR╜
  3651. àBî▀=x┘$╠┼"fë∙â└±}∞░!.àÉ~%ÉZ4uF°╣ß┐/ö╘▌â├ ╛~▄*49╙|≤≡B9■}óFè~!8v√)·ìzaë┬¿[G│≈(╟cuc}ä.èD≥iP╦m╨ΦΓ'¡7╞>5v°t&σNhÄw=:í┼>0FDPÑ,ΦÉδß░ ╤A╪⌠°ó╚X≈G ╤Ω°äx║2∞!Ω╚.e⌡├O,B∞╖ú╖δ¼u»ƒ²╖G╧²ë√9╧~?δPµ÷DQòΓà╟9≤╔pÑf)¢~Aé≡µâ}-:Cnuí(ô¥    δ▌ ²»₧≡═╞·l░`7÷4)■F¼6ê@εD5⌐OÆ╓·bcÅ@ï┤jçÄM t┌╨═^z╦.╣&0∞    ÿ┤a├=τWû┤    iεÿ┘ΦH╡tVÇH"ε ╕c2éá    v"]ìc▌ j┼*pDfΦpù.ΦSm╕Y{'Ω5bw18FTB⌡╘kèb ú öáC┐╘#Öf⌠KRÜ─IK:╟╪âf#=╞`8!¢dAφ■┴EáP~EîD<#îr╪Lá₧∩!┤áΘτnE¼Ñ0┬█UÉ,0pÿ;\4▀«.Eé╓)╨(
  3652. æXM╕*#N╛¡58<j-─╙╕ê6╤¢■âδ\αG~â√}∞|~▓C£ë╚ÇW╘#Kδφ»6}h&l`,äz≈■nùZá$≡Θ┬)τ¥7æ¿╜Ç£âⁿ╞%╬@╚ìZ(╓{┌╦½#QΣn⌡èb    Dt╨æZ½K'½ùï╨mKáK╣δπÅ╣┼R ┬─┐ª@p┤oEF(┌ï<=╟¿t;tku ╞≡Ñ≡╘}W╒δS~/P&0▓ⁿC┌Z▒«ì₧≈╢╦}√â  |1,╟#t"D┘
  3653. êw@.@ Q▐Γí╦ó°ï}▄τ∞╫Γ{YBïG╩ïs█╚╓F8\╩╛ (Gÿ≡4K∙É1{ê^ó *|$4N▌■k╨ ;¬╣╤├û4]"╪"z≡=πâZa╔*=PyΩ3╝ûδ∙|
  3654. ;0Fl≈│T<ó■#≡εcyH9├}YìSP²îC<ï9╒uBF(lα9╨ìδéφ≈cëC║,;╣~1÷█nuk╙ÄC|α84Σÿ╣{Vén╡]3ëXöJTªy#╘És▄¢)∙    Ä╗╗Pìç4ÄëÉC0ë¿"∩«,╨φ Üè@6ε4₧GÅ╚╔W/µü<▀äá┬t~ìQI@τf}ä¼δ+J
  3655. !W +┘úΓ Y£╘%t<"@!ag≤>_Ñä╗àHA7}█A╫Qì9▌H²;@ε╛δ/¡¬!╪ëΓb¬0TñÄt$,╗` ╡/nûb≥¼8ⁿ)┌@ïA í[├ΦºΓΓiFÉ W╪,╤"JI∞3° R▌$pnTßïwδÄåáGXh`╦±ë╘╔u╘K&dÿ`≤>#~─WàX∞àº}ΘqδL▒~[·ïA¼╓,ƒµ+[bwτ $k╩ka ╜▀ùhµCÇ};êZt≡$Å╤FK70ΦXΣû╢#╦╖zi├┘x%┼),αèÇ\ ä╒Cα≤,0S╚/╚NM,ÿ0∙└7ïîÉ%áoäJé∩½µ╝√-êó¬∩~
  3656. ┼Ü≡Ω╝O}â,ù%äägío¼Xδ.≈≡ê%╛7▐ÉílGâΦ£Ωñ▓+ ¥,¿δ1R∞jÉ&÷~■䪰φ@%B9·|ε┼¬ΦJçîΩ8╕    ╒A,î║    │x▒êα╩"▌Φ3√%├=¡h73() /┬O┘RäKR
  3657. ╡o╗_V╛╚╠ ^ç(fïfë.quuóëIαD┌ko│}Qu=2Mp└╞8 =PA-²6b║=I∞IΣ╘)▀k2╖.9╠Γ└aQ?ÖÉδT┘ìî,
  3658. ┘▄f =Q!u2└√┬┴ê╚FuY+é°èå3_╗g₧é┐-╨á$=;ñ$░╪æ*è\╡₧▌?t≥;5l÷■#hδMF┴δ½'╟ªN╒Ii╨9hOôBHÜàé~▐t┌ói╛ü">OïWê#┼ï├ê@FÇ─Ñ¡¡ë≥xƽ╡2*Φ«╟c)║╕wIÄ╬▐d-bQù |Ö±:lu╔(tWæ┼Φè╬Φï╨Äê°6|    ÷┬]K¿h╜┼┤ï┼[ëαΘ@R    A╟F"L∙╕RBQnß^∩≤7⌐ëW,Xï▐â╚S°#J}ú½9╩}"yk~uüGÿVnîäN7;ÇX≥|σ@¼▌╨4B ~ô(ClªΩ¥-τ÷σb▓╜N⌠)ÜP[ⁿ░ñ▓┼ïròfxV9 √⌠ⁿu∞╪¡·¼NΓäUAxÆ∩ δDï^S£ï~XX/▄7x,εùQï╣J"î<pX1Sä╝Γ7 »┼Q¿P╢Q0÷ΘÇ*ë¿₧>Aä▐F─V╢ΩlⁿF"äñ⌐@k:¬XÜV╟╬Q-ß     }8K<äáèF 9╛- î°!Rm─d│C├╒≥ì░;ïü∙ ╗≡≈╚Nδ$∩├⌡Çà╣m9╬ö<UùÉ °$─+)ó█£@ n%ÿB╗gK┴ ┐Ωêd$!ëδê&W,W½050l░E10îαk`lKÆ1àSt!┼KW┌"- ╥G£mW╖/Y)Φ╞    δÿ3|ô╜╘F4Ä7O}ë░vïrèxA ê∩╖/╪ B7èCê «τ.U└ÄR K¬ma█ÅX·$;·ê╝P<¿-°ÜeπJ£b╠èìo≡ºG4╟╠ël
  3659. ╦^║1d0'+`╙²$/Bδ²ÇP[|τè è<Ç_╛╢╚
  3660. #     H0█Yⁿ ╓δσ9┬~CælX╩óûôDê╝δhS╞éÄ┬#─OVτ¬«.pÇ+╫S°/K╧à√τ£P··£té¥░+¿Qfα,&<äî─Pcë"YCä┌÷σTa.n¥@öj∞s$4áà╔f╕b! !»"ìÖΦ¢]ⁿδfäπ≡+Φ-OAîNKÑ6*9√]▓oΘl
  3661. ╟π6╕W_ \4≥ⁿ├,Çmu%édπ$░ ░║)pkδJïkUV √µ;0F.ïCP*≈@₧»ÜKSD║  p,úSuCE│╒Üσe/h╨X∩R0ûÉúU╞rXwäræîä==ÿ;─B    f £∩áä└\Ö┴ô╡ï]{,⌐▒`╣ßC
  3662. ΩΦ ú7bT╬$â¼/,ï¢hU╣2ï╬Xl61o6h┼▄@Khc2B╠┼ÄJj.FA ▐%∞h╤b├*¼╬:èè╞ìäëjα+╘JïóX)≈ ≡-┤j╨G≡ï│#╒∞┼P4┬ìFkX    ]╘α&Z▄úïowèx    í╪áΣ▌~▓εÑ)║áï;é üN╖e x┼▒çl≤Ññ╡╦&å' ~>░5 f!⌐
  3663. ë$,┼±ⁿδâ²d}sqB    πîπáci!lïⁿÅ$>E=¿0÷≥ $ïJ@!≥q@U!┤a┴╪╥Θ`^f≡┼.Ä 2Φ{┴\0ε¡¿╤t╓Æ\ Zß╪┼ÆÉÆD├π╜π╨ 4@ß╓"0 αò£O3SñÇ1■╘╢v╗»b*üu,~IΣKvKN/`V,MëFT∩╣ö!`├é╘+í≡ö▄í▓█H≈
  3664. `√∩ë+óPÄèôD6c#7+5A*`oJn'OP¿ΣT▒Å▌}δUÉ╕áδM╨δEÉ+$Ç╚σ)ÉKíΓöσ`δ
  3665. ╙ΓσD╠à┐║■ R╚╖h¬$π▄Çσ├ú_╣r_░═£ ß{M┼[h7Ms{ßùⁿÿ
  3666. 7±4R├ïHδ╢è[pw+Åà'╨êⁿⁿⁿ╜σ┤δ!╝δ╚δ╘δ `E≡ⁿαδ°S╚r ΦRYµX╒`2 »v╤56í+¥╣ ·╒|`┐δ║75Aü 5ár╚D6╫δ╠ü ╨@ïÇ#;,└O░â║lJÉ╝=zuεC"
  3667. BÇBF"·ê┬δ,«á[Θè₧ê╨█h┴b▌├╕▓úúóT√0^┴ë▀╖▌l⌐n1ïSI'╒┐PK\uìCï+b½┴B%├äφ╜òh╤S|╒    ïë~W┼Ö¬ë╓┴■sαC┼╓╞PB⌠)╓█'Dë°Qï00█M╬>ìV4m²DFP99╟}J²"(1√Më┴┤3²╕¥\æ₧⌐╔é╡S├c█å¥┴s┴┬s└╢²hzO{├t [╢R═à᢬n┼╜!^¿ÜM}ì¡≈¼Gε┬ù}┘6▌\    ë╙u)⌡╞¥T °ëh ~é≤+îéƒ,⌡[┌ZïI6E╧ë═6ⁿ}╟D▓╥ë<▓Ü├m÷     ¡⌠\[F≥ëp/ö0R┼PO
  3668. 8ëzí≈c.æα&Mò┬┬╚    ÉY╟
  3669. Mì √/    hî&8m╟ï┴!Tl▌A ó▒d%~Y8ì'┐π│üµ£<ºlUΓφ╬ïAù{;üµ╢ ²ß┘ây¼(·+Q ܱpíσÄ£ï ▄½°M─ÄLïn 9∩╧uluδÄï .ºΩ)F╖\┤ αô)╟ëKà£ä-┬█|╚┴}Θ█Ç≈!α╟^2!±*╚YzZw┌"ïv    O╪p╗│√CDⁿ4┼ëÅv3╓┬C"°*└=<ç▀/Pⁿ îφ╒▄=
  3670. îΓM╗"â├a/ä{G½H├∞s╒Kë½E≈┴∩'ü┌½8zBIτ╨BA╕q*Uàδ1»R5ÉÑ╓╒╢_Σi⌐╕$╨h    DpK╞"
  3671. mF─(╬S_8VuFå|)f(ëZ▄,╦▓mαΣΦ∞≡σ╦▓⌠°ⁿìH÷Wíí█ à╧úq+ûú█É╗ìo 7δδE∞╠o7Oë"|δφâ¿ⁿh√æóT ∞ñèU░=╒1*°╘╟Xïf┌┼¢Bë[╗¥·4Ç64æsδ╜*| 0t∩≥u"cQ░úΦJF╩¼êoyBδ█ìèR┼¡⌠pσu╦R▀╙╜`┐c-ú
  3672. EEÄcÑëδºτU7Σ⌐δÿTßz#    ╕cS╒╓ó≥-µ-àk2kii≥àQ±B⌠├█a2┘├/) p$hW_á┴├dδ╤┬φlj=;à]7Γ?₧╗█o=└ÿ}B#ï\┤¬·π╢Ñv;!a└! ∞⌡gh■ÄD°uAA▌φwΣ6|/»Wδ9    ²╣{£╡ïÆJtGü·ε[)Ω|Y%├δ█.┼Γ┬v╜▐╔┐_» C│û┴bΓx@»0dÉW¼²£Ω╡ñHO▐∙ï╡àLJ*&Px╘ï│█Γ`?╜σ2≈┴@à÷\zT└~▌▄2E╟$óa3ä¿┌╖└╞╪X∙╧Oj'W╪W╪Y¬T╚>è0\g■¡■τ9▀α₧r' ╔ù╡═Aw4▌âE┤;v╟Xτo!¥;#╝╨ú4¼_áb░M∩▌s╫┘╔▀pàì≡▀─7φÉZk!(╗ ]\}ùM"{XK    g"
  3673.     1╨
  3674. 1≈äCXFëIofçgΣQ    εâ╨π═üt[╤{tU≈╖τv·╤BF╨@)iúùn╚a|∩·+è ΩCcT╙°ó┐=╨ 6T¬ÇsC>τ\)] é:|=«½╜8x╪Nô(û¡∙|,ü∙▓▒<╚ª╫╧9╧|-ª)╪/╘A9┘~°AJ│`%}¬ZÜ77â,ΘH0┘εC░├▄6ƒ<█ ïzWï*÷_└%tA╚û|τxm@ΣÜ▀¡b?C¢ Ü9uεH:WAï£dHådsƒvådHåòt₧HådHw¥╫F dr░
  3675. ₧ß    ╘2╗ïX<╖wy≈├┴tïr:≈₧aÉ╞ 1óµ6┴5 Ku.G Gu╫@SH⌠└ç╨"T5Q94└┌░├    $ú╤╚ÆE8db╢äd(OkíÇFuï╣∞╨.E%█≈╪sC(αΘ'ÆTQJéτÅ
  3676. ¥A╘≡▌ │,¼ 2åë╔H¼ $▒#╣┘·╥╤qè∩çtv     2α*É|+█WI■┘ü╣░├/ ┘╔ò ≥▌╪½╜XÿK3/╜≥É7Φ┘≤╔g!à7'Φ.0φ:┘±+rφ╚å|Φ<.Z+ÉéA╖=vìt┴╢║SΣ▌Z┘ß4δ╙>Φcö▌RêܬcaδQ4ï6δIV|É╬√
  3677. nI╗εKⁿjπöç`|Æ4╨k┴┘Gα╕â┘úpép    ))╪rÅó╖ü╗┴ï&Åó╦ëá╡'jeÖñ:╛20)£ô╥±▐Y╕ê█2■yuσ▄$σ ╤?2≡╛N}ë╫6)≈Cëûáo
  3678. ╛µë╧ÑÑ-    │_┐juⁿk⌡t&`╢╜m╡■'x╛@Γë²@±;ë5*δ■║ñ╤⌡┐╫èíái4$│/Ö*fàuàx    ▒ª I┬)≥9≡ü┬½5ë■p;9∞║&╬Fát?⌠₧i₧φEF╒)!╧7_D≥)┬9╞s╖╪áäff1iITïW-╘
  3679. a<êd7_ ê╚l╬º∞≈≤tÿTlZ╦ZA^▓çΦΦî$Z,2┘╙¼@lå6$iQpOB⌠
  3680. L'#LV│öjgδ╞\|ôì<┼Ü
  3681. x!.ú ùeΦδKd╕╗qV╗┼▓ïçΣï     ≡å∙ ┴[▌║ oëCrΘtoτ\²3⌐d"Φ^░ΣWà«┌/ï╡,│┼î¥à    └kp▌ß°&■_1 èêl¬■ε}? ≥ ôèδ?█╙ ║w└t#│*8½╕╗!¡~█êB▒╥₧Γ#£▐&╖δ
  3682.  
  3683.  æ+J║τ ┐É(┴Æ$Vm░h ¿$ê╟▀┘LnHa¿▌o╚µ6╝═Dê¼Φñ'■N6G└P█╬═⌡t'q$« ┬╜H╓Γ¼-ü╬╓N7²é^┬Oµƒ▌U╧±fò┴τmîü&|å.G1¡Enß≥uï?Bàk┴╛πâ╟╬╞Θ K≤ xFíπäe▐o≈L¥û╚8B¬tn+╣╗╚TKë╤h?%ô╣]{!'#ïQ(╫╧┘ÿsS≥δ=ûÇB╢╣K║Æ:?╩0ë╪¢u7ïD=òòP¥▒ Σ╧ vQsδò╘Hc├6±Xî⌐%òo-!╙Rä■9┬æÆ ⌠tPRXΦ▄!Ω▓Y3ª8dp/ên6    sbµ
  3684. å ! ¼sA╪åY∩┌q╖F[G═!▌ε[╓▄┬&╣░Kl┴º▒Θz∞wΩN>ZΣ géG≈═w╪â═ò9!æïSçTt î «Çr╟║EÆ
  3685. █C╤èS∩╢δ#ïoJ≤Θ╘6hF"⌡║Kqδ@ε∞╫Φ▄ëZ╣£^ñ▓╪░ùñé F ègc÷|ïu3[M\0ÇΦ╙à▒v├]@½ä[@╕
  3686. úEC∞@ ╞    VG╢▒~2¼≡$▌Ü"Y├_╜<U°}ÜíàºVYEM╦δ╘╒îh¿≡yΘ ┴στÖ÷â⌡┘k╕]2?o╨■∞ö9┴u≡%≤ë▐ ┌«@d7»1/╢∞ßùÿu╬+#nc┴░°}F<═ëxäë,░>Ñ:@=$;ù V`╚e<:╡▓g·vNÆ╩δ%É9&    [
  3687. &█º≡δ╚e_ε=Ω<j99░ⁿlπCÿ3Ç#▒Ö^└ï╚£q╒ûpp)≡I┼@ç.O╙ßt╩{ |Jh╨╞'L▀√ ñ8i╚"?B╔╝┐╨ vpâ⌠Nu═⌐ë°)╙⌐º-@,î └┌B4i╟Θ└ºKPd╘á}┴aüD─Θ≡│9B6[ VΩ╔░àÉgQ@Ʋ»{√¢ì{╦·.~"9┌~S7y║C╚Ωd9▐!VöâA[╓├╟èçZLδ/*─@╬[░åZ┴^ ▒:┼╓₧│╔Ω└# ;₧n╔2▌/
  3688. Σ├ç
  3689. ═╨ )╓l¿ @F[±ï░·»φ┼╚ìδ5;8à│=úºÿ{LZ"]Zh╘┐┌╣s(o₧@+=S ┼Ië ┼┴' ;r╪T▌i╚⌐y╡Bτ4i á1σ
  3690. Ucd'M<══<ëân?[s ╚)°pv╦πJ┤─_S )s╜⌠6Zï+ >░H4#*▒▐V<ƒ½┌├│├¼╨Hóª|╫═Çe┐╬╚╙┤░╔'┼╙C(ó~Φ1«8ÆΦë╫▀╘!l▐I└H╥D.=╤'â\╚┼·δÉgÉô··h%ºΣ╒δ,╣    π╥    ëXrJBtAt┤ⁿ¬Ω3┬╢H⌠πUù!ΓÉX┤Φ,₧²╘t⌡Vg1G£&p╗n├Gφ@h
  3691. r≈IPß °9═╜ZΓ.╕&δ╦Φ9╬gQà7ä|δP╛PÖ[┴R?|ǽÅH╟╧ó:*9ε~_φäö1φ"═δ¬à░┌ └≈⌠└mjSZmk╨[ZCe eYû 4Ç7│m$RBêⁿ¿!0╚¼╣çZcù≡Tç¼δ╨P g≈ÿ¼CêC ╞■╒ ├=¬δεt Cê:√b) ß*└▓α▒Zü|φd⌡û@∞É╓╤WrO┼îèR4&8~5ΦÖ| î▀δ¿▒6BR╫:P┬╖î-≡MAÉvå,─à≤t▌ê]╡!è±δ+¬Pä╛≥L└é▄:▒Φ╚[.Çü+╩ çp∞▓`╡╥╝$Å°A3@=S0≥V∞Lα    "g'±┤ÉâAp,÷ô¬┘ë╩ì╝(X7YAß║(ä#î"/
  3692. ╜Σ"∙₧╤╖LêîïΣ@ªÉdH.Æöÿ∞╔wδU£íá╜<▌;f'-ñéiüà╖▀Gà(╥╛2¿▀≈zßN▄╗ÿê╪ê₧Θ░±┼}ü╕⌡eac)`∞}ΓcΩ∞Γ¼n╒£epîXU⌐ìö╠╢┘¥wα!J╠╟å?6>¿7!»▌9ë£c|bπ─⌐∞Ågô░-ü─"▓∞ x|RV║∞íX¡╪c\òâ║ƒ╥|-▐ïéZΩHëE    b½Q╛├Ç
  3693. ?@Σ°~/n¿;Tuü*≡í`-£¥{░¬Z'╡d"ê1;9\\Æ/╛ß`Φφ═,uR
  3694. G6⌡EÉâL-.╣0x─/⌠o¡÷A uè8Ç _¿]u√ùô[SU√δ[ìZ ╛Y¬▓}îJaúδEïy9 é,╧Ç··ngΓµ╫óu+∩j╗RCÉ│%▀o Fi")Ω╪αê■
  3695. u(└∞╨╬╜íO╝î▀íw]δE¼°║-╡╚aâσPα \ü╪R√⿃º<¥d╗}è<ª<Ñ δQ╡ «═8O륢l║èπ9;ì|e"╓C¡▌ç:BêÜë»▄JδO╡╣EF}╘┐'αAÇg⌡╣w╡├┴δ▌├┘φ├vF ε¿jΦF Jà^â[ⁿ∩σ?∩s]±$c┐GΓ °&£D┘║÷ƒ▒&┘GÆ@╣ç╫'╧àµà╔/┬ïYK└^α ├┬┐
  3696. tFàÇÄ kAö▓`ααê╙╓CQQÇ»├ IKB≈╒Ç╟δ│Ji┴ÆlCë÷|EJR /6uN»µ`,öh2&║[j¬∙H[tUèC⌐KA╖`T?Å╕/p um▌╒π║■w-╪0╔Iêúz[OUæΦP$;▌*~√!┤'êT ê$$0÷₧ê╫╠[Gƒ1¿WΦ╣»½7ñ,╤ÿ╥QΩÉα╦╟-ö~?ìrE≈ ÷Q∞_kè╘|îH╣É▒▀X£╪╪$T─▐ë-"{è∩5 GN}UuYp╥╝<╖éç░rP{∞▄ì¥ëW_τ■-üè[$íÉ╬ï╠╓√Zê»ÉWa█6╬ XÅ    CG∞ü:┌┬ï╙î-|╛    ïo    wα τ2╚0á  · \7v╝ ΣÉéÿ6ΦvúgK¡ï]½ìnî~^O    Dàì&8Btï┐╙$└æ|B∞FA╪ƒc│Bu;t'δ╖C^≥,åt?≡ ≥í┴┬╕Ç°ÿëc▒ ╧ú∩N=$0╬÷1▄+╞êha⌐ªóBÉ∩DÿNB²¿ûKT$╚δ┘╛
  3697. ╞▒∩8ö_î1Q░p·R5úè╤G SU│F╫b≡½╙²{    NC¿δ0─/h¥ü}╟yÇÆôu⌠uå)&wvÑ√╓#═`z╪╪╛╪╘ »9ê╓èt▌çΓ]¡u0Σπê%▒AÇÜ┴ë°
  3698. é┬ç─└5'3⌡≈B+ë·Yb ≡%Æ1┼└4├aFÄô╥[:≡Ωü²▓⌠ëxW»╗`┐)╒ï ô*<è\└p┤ΦJ∙üΓ¼L═é]ëd╟íδ/₧╟√╛╘╠3∙⌐╧ÆóΓ2╖Åms▒└æ┬═Γ∙Pp⌐ètî$╟▓w Ω%ë■éü|]|Fêm╡â°"Aêöφ┘P▌╚v ∞⌠╞sr╪RAß ╝┴ê┬<0|╨9~¿ò.B┴╦█tú-t₧+tÖ¥ío]ï░~pfë┤$ê├6G4oszkUαí#╚/αx ╖;╞┌E(7
  3699. αîΦ%p18!rAC>£dC#4≈╞Çú(V=/V╟óΓmUA≡ïô&╟½÷f/;║è°∞φ$╞F7êï%╚=åεì}╥~Y╣Q╗x8[up╣δ╟ ∩╝-jcsW≤ÿ┼é cF▌┴é<╬xêìÿk=t┬Cf╤éΘƒù ddYhMÄxoVdxwcA3lu▓XhQ=/■    <0╝²─┬╙Ví╔u┐qVσ @á╪P3₧4φ[S¼Äk≈█ì▄Y|σ▓fp╞D9 .u∙bK⌡0δT╫£(4,PA╛kh├uÅq|$dvdç║,ï∞Θφ#√$┬╞l
  3700. ]╛6ç ╔┤√ê9╢A∞fu#ïî╦≈┤µ!{äδ`╚╚┬lPôöRà]û∩xòÆ┴╨hüz₧efglu"₧a`o6°
  3701. ╬█;öûüÇ╨(╒ú`µß=ëöpÿ╒φtgSï/PÑÿ╞÷ÉæîQë╩¼'╣¿₧àφjê7 └n▄tα╒╒╟t╚╦1╡M¿╨╠! Ñ*éεó¬X¡.weo;dn¬z╞Iφ$▀Φ╨åφtë°í^½¼`àíO
  3702. á┌<
  3703. ñH⌐╘î@.Æ╞i2█Ω╠6╨▒ú₧!╪α┬í" ╟>    ì¼δY⌡a═4┼9,⌡uΦ4åå
  3704. ÿ╪╩d>Γ╨zjLyçⁿ⌡
  3705. ç╧9àbß»W4ç┴<%╫«óD╟Ü╥£/sBéoIz0^èC≈'u'â┴nç÷■c|^b4d≥ 
  3706. lbF"$4¼╪çc¬╝ªçá_{;¼ö~φx┘NrtE└D∞`° ▀üU≡B<w└@LN}"â≡ïTëA0φk4¼u¼lEëBä┼.aïe├eå╥5ΩL┘q4)t#╥òä┼b╨°ækBme└äê─ï¥`-ä╕Y¥óÉ@ò°≡/|;B┴M¥╦*|;l«°à~& ▌lUU ΣRφá5⌐HXΩ3âô╞èùDºó─φ▄ï&┬,ε▀hgrB*!Æla~ε8cΦv.6 ┌Ad╡▀uδ(╬(âßñ1ΣIF LÅÅV1≥▓┴ƒεXîT░╚     ═₧┘æ│g╠╚é₧╩1╥ë╩ÖÇ╘πƒb+╘╬ì eÇ
  3707. 4Bl╚4Æoñ╧√└╪ ┌H[¬|└æNÿP└r?≡AKüü╟π└é╨ºµ▒╥≤l└╢ ╒Aà╖íαΘ╔√├wNFƒ¬╪─P?é╟ ╓@'òù┼h    Ω┌└ Z╫UFI]ë
  3708. "A╣/╪+8P;Öë▌─∙á8Vò╕╦╒ε▐æ@dA²èV▄q,éM╢ ñ ·`╠}  ∙V1√░╚ⁿ%V╦╓¬L:╒₧∙DÅ~ ¼ïÅ<<▌Æôn╢OëBΦAûeΣ¼ ÆÉA∙¿ï(ü²φφYF.╗╚à¿%dOÿ6u░░╔▌àV@│,#ùDÿ
  3709. (┘V1O+êK;2|EDâ\ûæö─á" Hé╕╜>1ë∞ä¥ô╦}£ï#ùrL£ LÇ|/|<@îP╕}#ùî$;╕Äö@gó╬3Ç0 EÖár»êDì┼Pî╝φ╪╪■lëïnoC╨f╗M##AMnεΦb┬Ñ■l╫Cj╕xV4Ä>Ü
  3710. jä ╜h0▒c#9
  3711. rù!╔1█4ÆÖÇÉ#$MGk├%≤#
  3712. ├bô=#) 'Kéæ¥ 'ISU=∞┼&/*u▓ª{s, *(SfO█Z(V/$^[δ3X╙òá0.,'çm█,F|W3(_Öt4?╘<╧X╙42000∩Σ░[0U7,]8┴╪75┘^zP5:2┴ ▄ s ¬SPñS5░╜«4=╖δEK∙█«└╬QK÷C·Aⁿ╤▒ Jk╥└┘@ó╖íWtú╜-1=\pc·±╗⌠╨╪½└╖┬┐OW╬    t     x▓═¿┌⌐3°╡'Cw╨>║τ-░╛)ó√â,║≤    ╣ë⌐éSæv█╤,═÷/¼¬«ó╣¡y    ░7    ÷á⌐^iu±╕┐
  3713. ñ√Θ3╕=÷*∩╕é║+4ÖÉ╢áFÄr╗÷ÿ2V##çl╣≈ê╓╛é┬}╗°╕
  3714. U    ╓l}╣╘ (5┬;╢{≡fτ.╖.
  3715. ┼.âjûφ╛=(├æ▐»≈╕Jⁿ╗ⁿ°≤╚╚▒RF.*,>rrΣ-■-⌠ -≥╛·╓▐╙ⁿæ²■╗'#gµ┐ì─ª¬
  3716. '''fj┌₧═Aσ-±╪?NF&{⌡êⁿ÷ç╧A.╛íl÷hûtΣºû: Wí±√Å1"£╗9öç└╫ Å=8E┼~}3φ=º]iáæ2F}╞°bDbîCüú7¿τ+Yñá├Xr⌐xⁿ≈╨ë╬ìêPX╗R─Y╢╔╣mëÿäb:BåÄΩ┬±êé¡÷╙╠A#t∩∞ë±┌M√pñf[F┐╞J═M⌠ê▄ú}ßt╧ ·╡d @_¿è╘α·tQEΦ#CbΦIº═DíéP¢Ö╛Kç╕UY3ⁿB╛èÜïë÷ê`╟)╪ô`|⌡V╜╜Ç}LZ╝éHV VüΩP:s½î²╫i5¥    |CFëë┬n½ê═=½╨αÇ▓╣ÅÇ@Túü╜═BóH
  3717. ⌡ë■9╩â┐╫B ⌐É<≥├-Më-φ}(ºjä▒Ç     Cºn╢╡r─8A6séût∩X░ìd)K$b█⌠▀Nòt7┬rªèb JÇⁿ⌠║KèJ∙Æ≈B╞
  3718. Bí@kv    ▒½ê▒φc∩f{MtXî┐á=)╘¡╢é¡{Çz\úφRµ╞4
  3719. 8CR└╬5═2Ö,(δñ
  3720. ╙ü∞öd├▌Uçs\u╗P┼ƒIè(äφ½²:Qt⌠X@δφB╞∩@░0m╜;éA· à≤A╨∩0R⌡¿UD <úbª┤°E@ïb%Eêìqà'τj9╗╩è/αë┬ê╘▒╢tH<£ëµU±└¬╨ë╙[╡KÇ╥Ñ╒P≥▌╢{╘ë$°+╛φ@[û{+¬T▐`╧░:3π¢ 6[FΦì┤φ⌡XÜ"ë┬─├▓═éDm■DP╩2 ═L¿1╞┬;SW VBéå┌|ìÇ:b ·\tHJ-⌡▐≡┌√╪@_3A╢÷─ô ╛t╧Θ    @╜PD^)┬┴ΓΦα«╙ACδ█S@%^N╬╡Id ÇWƒ3F¢▒1H¼╩go ~äQ▐ε,¡╘╙ JU.|╞┤GΣ∩`╥ô╖x≈M1@ïâDî±T2▓|╢t┤ ╕╫)ê│# H"╢╫)êE#á═│|4  3$è┌c∞╬êP(d'~╚╢┘)φ 
  3721. *1╚æφ@F#+$ë,⌐Ç▒b R (f1A|█í÷b└√dú╣σ=är÷(≡▀mê÷Ç┴₧± Æ]1φδ ▒▒-Θ-µ]║⌠ú ÷▐uoµ⌡▀╪N╒%εⁿÿè└0
  3722. δ!x
  3723. ÷<í$#\¥╪¼M¿╩╗l│σ│t iæσ│î╕4 ƒ-ò╔# 4 åw≤,$3%┴·&bJ-çl &d'█/c⌡*l<(ï@LT╕)╦q▄çúl╙(Ç=∞x-5áδφ└Xi|_░N└îj8▄▓ó}┼√¢üεDNo∩Σ{ö!Ç╣C    ─3èΣ∩╚A╞▀óG∙╠qà╤¢ε┼éѬ·vΣ┐┴ù"O<èZ9Φ0ä█tr∩ô¬ò└Å-┤]}èzä    σ-ÉR<óGEânt>sH╖#y<t     'sHsH'""\#HsH\rIA⌐Φ╨'ÅBî4╫t_m8╝æ²╖oDP·0|+9&âΩ0ë╢┘╒d▌ü▄ΘCΩ∞J±÷@▐┴'▌(*}╒φ╝╜.uT1÷@~ ╛MÆτδ▐$@ J94l¢tn▄#N 6C,δÜ{┘╔▄bT X╟≥╡åæá╓█3âN└█    E▌µF╪╢_¼j8≡-&╛6
  3724. ⌡■âÉ≡α<▀╫@}┐║é│Ç2αkÅ╣╔▐&
  3725. ┌ïÅü√░╗╩α≈nt»╞9=4x~J▌╝N╘X±Θ¬⌐°å9T▄'∞╨±£┼X::(é▀7└┤┘┴J╪╔k▌┌Ç╣7Kδ?TG₧Ç╬┐=δ▌╪M¬3ΩêGA╣▌ûU∩Σ.πIδ║µr▐MΓ╠·;ég╫╜µrαßúÆ#t╦&MáKtn░εàαV- íâS=Ü├∞τqôRY"╟>■ΣP⌡7°jö╓F< t∙<o╡░┼⌡╢êΩïU▌è╪╜â┬çAâüxA╡Γ(¢╞üë¡«√&╫█Ñó╕░]HB¥ï{íF:■tµ∙tß<_t▌SÖê5hN3f`_■`Üê,CΩPΘΣcë≥ÿÑ┌°è:FÇ â╚╡W≡IΣMN┘ahδûhsúΦ    <#    ìδä ╖¡╖A▒ê=Ez^π╦7vy°∙LBê\πÇ√.n▓/[lp%_√Nδe>ñ┘ô{Ç<$q\ⁿÜb╫vv╖.OBPê|IS^┬┌÷êτ└Hm╤≥█τδE≡lQ½√╢∞EubF6Bá╤~╓P╜îv√-tg╦╢σ╕╖NDäB! ]a_ߢÉ^ΣDï#╘╘?0╔Nê φ┴╪ùM┴ï╚█!X▐2─╓ëτ▐r$≡∙─ô┘tFvd⌡«D¼▌Φt3═Ü'K\≡±╩!ï}|+£$αGär(╢R=^⌠ÅÇ╞╛}£S>╚AÿPbµ÷4Ω-▌┘εO;9▀~U±±U
  3726. f┴ëb!fKÑ╖≥ï █ ª δ <Ar<Fw 7"F"";αhGn½÷óE<!u1╔[=╣ vñ≡:▓ ó14╒╚°Ü⌠1╝╥r│y░üR│ª:╗ªÄj█äÅ┴∩┐"ê'}á╞(±╥K«F[tδ&°·╣&g«Ω¿0ë∞┼▄;X≈,°3ΓOδ░┌çLdª*-┌éf╖êN=ïÆÄ
  3727. ┬ÇäH┴╣$ì#┴Qô⌠╡H>V=▌Ω á!≤Nm≡b│( ClæMJ.[╚╚┐    ╝( ∙╬C╕ !F2≥░    J╣î.y╪
  3728. (║öí┴√çNÉ└cèV ú fl╨ì:m[ƒhF~*    æ- 'n╨'∞¡╚±ë≡è╗∙'twd >╨╗÷ß╧&aE₧ìï=l╒}é╗6L¥c6êv¼MèN┴=Äó
  3729. ╖9fk╓═╛4úW⌐AñZ`à╛e ╘ª1tÉ3╫=AêT╗A¬|É│Qñ0└┐≈─ü┴µ¥║ü}« ºΓ0■(5l╔■=ó╦p]B╥(╝IΘFr╚+E ╣d√_ABxÿ╢ÉìUæ¼▄É£)1°Å    äc¥D
  3730. ~┼l6ÿüΩh÷\f],Ç≈«rPÆπΣ<8@ù╢╨°V_░⌡ Na£èF*╝|ëJklÄ▐√ éL½l k╥d9z└n╨i╥HC ≥ö@Bª·▌█Goαp)▐e3ⁿ-╛╤FCÇ*ê╤i╔^wD╘±⌡╚ α-q░≈▐àqJ║2¿3÷1*è└╪╞ê┘≈-h·5Ñ╔d ≈╩"-┼6╣%<┼▄í"Mß 0ß2ê▀°ëƒαù,é%ÑÑΣñ{ß▄ó╪äA"ΓPDol╝í0@O°<g.6≤HÅâ▐|∩    Cêô^»δßH0╥╘w∞■░╕Z+éäü▓¬º:╒«╚┤┌-▒ûè╢X    ┼■ceëpfëH$è∩óå(?xw êX    ╥m'¬è$-]τΦ è£%┼÷╒
  3731. &L┬ S╦nW1AÇ9GK▒▀ú δ    hA<¿≡ÇàΓÅItí│zö1╢}▒▒φǼ9äú    ;▌èü─>⌡êï╖██/Σ    δï| X@A▌A┴1√ä█-Çó╤O
  3732. 1┴j5¬}ü┌╤^φQèF
  3733. ]7ÿXå«ïNjî¿φP┴∙Ñ├╢è°╓â  êCzαÄ$ug⌠╘ⁿ84≥ÇzAî∞Fê┌µ¢^%≥└╔ε▒ôu!tδF≤(≤æ}êδ./ápδQ0r╔¿xS╘`]ÿBK┌Ωαm.ê    ╘{{╪o°/%@ âx u≈{Eâ╞ 8┴²â²Yé═IíΦ╘ÆAΓδΣ░#éFê╩É∞┐Sà{"
  3734. ╟>ê[~ß05z$τ;÷│nlE#δ^û≡├F9╦u╔EäV├>a'n∞▌C6ä9≤t"tl)`╪ïAw]=!Å?√u▐ü9üº┬¥ßH└╒εε╤($╞äèbÉ≥>9╤rαnnFvûÉtCdl ¿╤9╟ú≡Γg»┴6C┘»6n╙≤%▀≡u┌δ    uë≡ä╤╛¢9 ÿò█ë╦9∙æ~9èSG÷ëów9Φ>╬jÑ{ïe╦├╕│╡ ├═¼Gv+√Yδú|Éèc╪jO▄½╫T┼`ÇtMj╔dw╙├t;▄╗╨║'₧!9;ZGδ╪|▀t8╘QÆΓ╗Ñó╕B%$uâ]╪░╟-
  3735. K█*`╛âî!EK0¼░▐n▓E─âçΩ─"U$-çα R^##^█≥9⌠╣╘┌nuP$t$▒Væ▐V⌡t]E∞├▓`sK∞░T⌠P╤<!`M╝u√╩;4Φ╨*ìá JB╓(■nóµ²╝;░?q┌Ñ1{F.;╝Ω}ß$¥ìEúR│Aÿ°#:è┼;╟íE╗4éN╦▐rg╣bî⌡║5êBC6░█ó█jn⌐DSî╨còhèô└Ǭ╨eé╙Ñ1ì4à┘┌[ÅjWZî╣hΦè:?σ4∞&½åî/Ç~└Wü+Rè╝@α╟½bî0╘▐t°öt 9â°¥║;Eɬx<ukεA√αφqíq6
  3736. ≡mNÜú╕ñ¡Pó╨╔ìk╕╞╥|ì"ûòG∙ëI╤óÅâ %v*ÇXí▐%o ±@πεδgEÇ8tgp└{çgQ[@[÷Yâ°┴╓æRì<B╪    ╡*█≥úc╔╚▀°h█ëÆ─¬X 7ëµ└Ñ╗aìt∩ëΦ+┌≡δ├£v Yà⌐╣)╬¿A▄▐/B"Çü    ÷₧iû╠rº╨
  3737. ß∙▐B"º ░    ¼eñ■▌¼;0Dî╡┌Sâbº Vfp┐╨┬áâ┬⌐- ╗²Dæ└╪4╛'╙4VW═ê┌¬Üï?╔ù(╕C±8"s╨hXb    à# ║
  3738. su≤ÆïB█┌y¿┐ ~â0%╒╧┼8 C ƒ¡ »ê%ïxè`    ┴ Ä¿Gn*~è⌠⌠≡ín'=Ä╜⌡¿`¼(E0"[A(ε
  3739. ╨╚»Adw⌡:⌡°╬ Ω⌡╦6$â¡╞δº╛>J·b┌úun¡%i'║â0»%{║>ë2√g┌¬(æ f DÇ>µΩ╟ÇbU╕yWSV(╔3ú╔üùîáδbä╜T$r;Çz╥t(4[(╞⌠]B
  3740. ê┬≡8:∞─&gôÇφ╖φFQâ}R╣5w╬┼r█l╦Iö:/Hê║=tΘò▒┘ƒG┌}┤▓KBX¡@ê╗╟ó║É W▒≥╕a╢ª√φl░âz~⌠╕A│mÜôÿZ0▒°σd█ëB╖ê9╡╖▓dd¼█Θ-╡Çüñydd╙╒│ê=Θ~z╡êàxaj    bC%C8┤eÆ├ô├Ü╪3l¿o    é*% j─╓Ç_èôÿqlδ╔k╥]Q╟C`┤^öS)√C≈}|íXäC\)≡"dPCa    +pÉ⌐s∞É!+ á≈C+Aæ║h╘Nτ╪@úƒa₧₧è! ╠╘-uÇ    ≡"HU╝e╘Nhr▄è¥èIhª`ü`w∙P╒H█ä╢╢èú█εVªìå╡ÜU∩ímö·√uE⌐P
  3741. )îï6ùo▀A&ƒd4ïûÇ¥ÇY)thΘ4╧²ìs (C▄è]<~┌%│ë≤p)X,╓Çδâ│ ╛#D╤=≡)Φ■
  3742. ∩¿│@;ç`sVë╞├ûz ¢⌡≡E%═┌█▓ó]╢v≥GÇEM∞£(¥·[Ü{_*╒∞uA+e∙} ╕D?╜┼≤l3aA6)]│┴a╦}IQbx°[4»Æ-uüv¿φü¼ß c┘T6╠}-nW    ▐Ω┌φ
  3743. büL╬
  3744. ;+ìê}∞-/l6=|╙m╚Tìkgå▒ Ç╫═ó ÅIEHvTf8┌i█t}╔S╞1x╩z÷ê░$z<∙ü─d,$üj;└f9√ÜEêè¬ZE─ü8&ü┘ÿô5┬`gÅ⌠{ñj⌡╚ó:ê9Γ╤╦ÇjO└╦¿ìⁿqGΩ÷R╣+äP£mD]8ì4 ▄¢0j,"╝%c[╗ΘÇ╗VVORh∞╪YVl ¼^j÷`    j≈µ╚4Rj RE|█{Σÿ╨jⁿUÉ    £Σï#+¿úI├Ròú
  3745. A╫╚æ┘
  3746. v°ü«<╕Ç╢K9╪Bf▌    á╖ δhâ G╠■·~óì┘;H∙b¥îl,     ±.S¿Çφ╫∩S-▄y
  3747. $┤ò╪m@√8OQ[BSq÷,>É╘╔V' jα]«éC╦╖∞¢@4 áΓkc▀æ!║⌐f z~#¢+x╨ë¿x,╞è#|äΣtâφ╫█DìC :è ▀/ ä╔uπh0ï>₧░≈╪S└¿Qh,ó≡f$▀Σ╢í╣P 4X╤╖R»ç└╪C╕Θt¡½fYï▒@╟▒Y¼╜╬p¿A½ΩKc┬╘yY )Ωö>á.¿Θ=Å=+╞K1▓lt*┐«▒âΦ¬X9▀<ì╤N│▌    ≤tNuFσ¡U0║Φuª╟è·     uGìG $°ì4)■╬ì║uà7≤╩)pfhPG9▐ó╓êN,tGï )ª║σ çÅ\Ç╓┌l▓ΣU,%è¼îg│╫NáÄêΘƒl¢u≡/╞C]BGêZε{4!öM╦╪çcIü√t⌠╪│w÷╛╕╛d5+φ┴cYDτ+ZƒN╓ë╫fÅΦª? ╠ë╦?╗P∩£ä`¼Qö│╠ßcà ñ▄;
  3748. ¡»╟°ö~èñü┴■B╡^,Vc!ö┼KÜ╜+∞█áñWí4f1▐ƒI)╪┌ú¼kXîΩ╨/>TO╘=t&u0δ¡,(oe5Φ[Y?##╝îÇ├û=*¼p)┌φF'îΦ╗$╒δ+╙ë▀╦x├49ΦFS▒kδë╞NSfΘPhNûqRWjöQ┤p┴T╜qGuWf¥=,QCF ░Hmü╜√ä4#áô┘a
  3749. (Ä/╫"▒≈╔aJêñA)á·æä!P¥Θ╗ä╩S├h¼δ[┘
  3750. ¿δ╙J⌐¬Dp╪ä-¼α5ä*b>+z    ╘FW┼+PSüΓò≤╠═è╕ò∞Ü₧Ç,2┘xw! ôÇ■rPä7î∩Θ"êA┴9!┌»δ?dA;Q,q=▓+└u(Ñ⌡ê z│$ x|∞▀Σ\├δ2=[!▌┼╖U░Éü₧E2X∞k·⌐º┤O
  3751. ¢ìòñLtMU░k °éÿ∞∙÷QYE±╬┴ß⌡▄.┼ÇHÆKV4    i ▒│.êl∞▒\┬₧ É╪`8ÖΣx9Σà\÷≥}3\{bë $>·╘,êo╣¥½ *▐αZI≡╖ô┤▓°öúê╣⌠╢J5æ▒_┼zIJD>ƒææI■J(FÜGFS$êwFFFF2FFFF3;è<FFFF=>M`FFFFabcd~A╜FïÜ~▄tAê#éαz┼Ü■≤|AÉ╗▀8╦:╤:Xƒ└╟╞6╘Φ ^éΦk}4╨┤▄≡OΓ■lºα╗σr╣}Z4\.ù█G! m"ì6[s╣ï▄pσr╣▄.∞¿9>Ñ₧\n═:l+$Ω╧╩█f╣▌`■╟K*╝+≡G,r╣▄6    3?i/E8╓▄║═-.LCc7₧╬'╫5╖═'
  3752. φ å,;α▌╬u]@7=k╖╣':v═╓u╨#░/&;+æ5╖«δ ═'W£;=r╣=╣ù0$v τ>]≈╣µwQkáôô╒║«█lïWó⌐╟ªδ>sδ?ß1X≈çì╫▄ܪö¢╖¢Ö⌡├¥iÜ[∞?    -u[;║«δ║▐C╕µ ▀┐≈JΦv«δ─g└3╧;Ü⌐¢σ╢Y/+¼≥[╫\n»╠ ¥■⌠█<m╪5<[æ└╛C┘,ù╦bÅp╓▄vªPg*K=Å\.╖µ%]û3╟56║╫5M╙Rq
  3753. .Wτ╓\ÜKö-∙Θ(kd√.║µ4√ ÷ !9╥=╣\#;$U σ n▌f{ç╗>á'═π0i'QejA╗îmá!∙]/J╟Y>ú√─v║ █U∙α !ü∙¢wA╖êªx$╦ⁿéA ¬╔*è▀
  3754. T ┘ïï(xë▐VKïzOâ~    α╖╞┴╕ÿïqⁿ╨█O833|ëWδfùà¬ñ^Jëüz[    ╢äxV╨#Ç ï>âlG*╣}4²²¼φ
  3755. !░■óÄ─-╪zÖδ=C╢Rr+]KDü└φ│éL(ù─ÄQ<ùEd ┘╚"÷B█`Q╜├sS÷≤ ╪`═m∙ ÅÇùô5,äì╡°RQΣ┘¼="ëm'l;;û$gYd╩Kûâldï╪├fëBñαy╚óÖoA╨Y?╓a≥6ü÷█ëy$╥<ä    dà:ÿ|    ┬ä%zí┘â╨ φ┘<ëäô¿╒╒┘C╚U    4ΣN≥2&αY ╒╨∞0yεNèÜ.êw┬Ozú╖▀`+╞sB┴µ,≥,2╚GêëS|Σ_`µHë⌡╢├≥ë≡$qq6X√d0┴■Nδf
  3756. ╓╛=!╦'⌡u~NvrëìF╚╛╚┴╥û╘    °æ¼┴ïmrf    Γ9÷╕⌡æ-`(`H╨1npåç∙ZN±≥t¡█ε¡z■sK╜¡¢≥┬& ⌡:û6ë%≈▌Σ{A≈╪░(F÷NÅ n    ■αj*╒*3°╗ 1≈┐Γúà¬Φï8É╬k[░[Iû╙    ik▌l(ú'Qπ>:'&╪n81;,,'T╕Ü^?-u+á▒G?ƒ}çQ=Téτ╟e°Tn|"ë>C₧èH╨ⁿ√╤Æ┌╔╝¬t)4ÆB°4I<= a╞Ü╝·╪W⌡Ä/B╗ÿmmjvUü≡ÿÑ▄g1¥δUç5ï┼bôÿɽìuV71═ë:╨ΩA#;"£┤j┴jåù!δxÇ╟┬φjv▌╦₧àD à╥▄I 6╪▓┼*A$£0o M7+αù<Sî⌐sE_@B    ΘM½f»òw=√ε ╪BíQ kY$Sïè╟⌡▓I,h+┌▓æ┴╬â±╕K█└eNqjE"│.,»K=l#┬@á╪##"╜▐ααïxÆ«rFΣ╚`½âΓ&g}rδCKÄ&KV¿o╤E╖▐ "Kï4k╕ UÅeOïö╦Nµ° ëq┌Éû≡
  3757. ¿    é|Σ»Mæ┴ε╨M*╩Oƒañ┘A(*YH╚∞Lgç(D░╘╙}│ +Y+ !y ╦└▓ñ¢!ö╜ZW├╝bYmCEBï@«êI¡9 ▀:I╝9▐Æå.!Θ!Fd░hn~ß8ëâ±Ä    ;▀B½hNXÇáåäêÜüR╣╗$:!b,év≤FVê╩`ÄdÉh╣1
  3758. æ_m÷éεαQ M╞êⁿzº3ܬ8i«▌ ñ%KàεÆ⌠┘ásÆπ/▄D┼kö[ñê-▐⌡15
  3759. Br╓⌡▐▓ö░M≥≈$lOp8Lt┬σ    î┤A°σr4└₧─4£X}╦·j    ÿ╬¬EÜⁿä{∞ká╞≡ÄÇB╚
  3760. ▓Ä╒ú's¢∞ë0u^OJ 9û2┼ì/½ÇY#!VBgEα°î╟ê+ε_æA8!=²²k╝e╝<ó<ÿΓ`í ñ¥└╔`º²N£H!  !ä═RXNLë`Çàñ8:!{1
  3761. O>ï╤│±╤}=Å╒=½ ç:┼Iδ╕∞@╒╕ôX?îD1ó(z/╛O???(╛P!╛Q╛H╛I,I?? ╛2╛R£E▐AJ6 ⌡Qé¿82!8é0Ä"G
  3762. yY∞`░»[3\5√BîÜ{ $═PCÄî6öδPM?╕ü⌡δ0╕kÅδ¢tT╠;⌡7{Kh6┤çα}'yÅI▐ªlH╞c┬┴,ODmJL÷▄╩╔&20¼╪≈┌▓òá╪ YH$╪wxÜ╨y7ùÖ┐éZ│H┼¡≈|Σ{!ZÖR$gA6╛⌡ÖAü╪≤2╕=┌¢H!<╬<tYâ4∞y 8T"Vß╨╘MûÉAïeE≥Wφ├1[7ë    ½rüÿ=≡_╠Ü0b&╣!û┤╨≥.⌠.Vⁿ≡âÜE÷▌]÷ƒⁿδN╙0ÿu:ε-kp¼DC/U÷j*k┴╬&#KE-úV5S,+hü╣<J╘Yß,c_ê:╘¡└|∩┼ûiS=G-ëéΘ6₧⌠X%X+PQÇæ
  3763. ╝q6╕8lïìé=-Σ$4"@₧0px╪P¥ ibΩüΩ┬Fà!z9X┴l·úL%ç@ì»ε$lzü£1 ^⌠öL╚ É@[rB░-ôä╧4$û     ∩,╝&ó╢í²-≥iY╡#/|%î½╣DΓH    yë╚α5(%Pò«╢├¢¬
  3764. OT>)tF╘B*<ü\#jδût√@÷ê*╘íâé∞Ä¿÷E;ï)6╨ub2F╘ü√l╟Z    4₧Cu@?>╖ù'â5|->»gδ= #╩m>{D╣φΓ>σ~Ω┬
  3765. $,αúΣ¿Σ┬α╬∞É)d"4' Σ ô6■Hù£ÆçTôôénûëu>&≈è:
  3766. ε?HQN]*\Bê┼δ
  3767. %"0ra!0¥δ▓Ʋ├ë≥╕Å6¥2╖┤┬d8MOδ    çle≥~gLtqá▄`Σ▒┤≈ëÇÇgu├ÉG╔╔■┘Ωû¢HªFá8#N«▓SïΩ├F?0 ∞O!≡fí    W╚╢ó67faɲΘΦΘó≡ñ    ≡:ôΘΣD2àEZΘÉï░Eó1$S╚    ≡Φò@N╖ΦóΦ╦UtrSLiìaC 'ó @»2æ\G àΣ≥τ"0║└K!÷Pt#H╤°└&¬]Z~█Qⁿo|üöId╤·δ║:Æ^fΓëa !ÖH {Ö){─αÉR╨╥gE╞<eî╩R▓: $└wFò6;─"∩'▄è▄En}≡zg▒∩ tíæX *σ╨hÇï@+ñ}I0ü▀┐├â}æó¿ä└ââf≡ådU┘ßsⁿw─±▌En╟}╢]äφWïPêWδBhn!ßä≥├┬Çh#ⁿÉS▓╪┘¡l╔éÉ'QMÖ┬ÿë≡NFôó>G9╞ⁿΦÖ┬xTσδNIn"σ╞`#îIºgÇM>ïI¼Mqπ╙yto6&⌡≥C    )kπ:£ÅÉ!AΣ1└ÉW Σ÷πa$W |
  3768. B«\o |╚ë0åƒ4π@N$S√Γö\üµΓ┬╚
  3769. 92ò!Γ╚ëdΦß╙ÖÆ+Éßu
  3770. 9u₧2à£ß╚ΣD╒α└αüL╔~ä à~¥"ÖBN√▀
  3771. Σr┬▀¡▀Ä@ªΣ}}M@UeTnt ½╦räß▐É╔¿▐ô▐h2($?IQΣÜÿ¿%Çè#ó FF╛$╠[ï<╟5┴⌐║F    ºJòaqw▓▓┼n:è▓f9$SAÄçΩ83║┴ü┌TWx⌠ülδDcδ9░Ω$m,(╪0$'[╘τâ┴ (ƒ $ÿc\à÷ £ÇíY└*ö└!┬¡╔≥╚|s▄Ö%É:▄%▄á£]Q┐Jü4┘d└┼█r"ÖBî█¥ëΣw█ä+iAa▓╗òQΦ █tFa%I⌐tSI)lè%ì@2─Kâ\rE:-º╒jÉ#╒╫╥╙«~╡JYⁿäl─ë\Στ░Ç╚4Në4[±[≥ë╨╘qM6FÇ▀ ÿ;}>Jï≤φêC°%╫rQ²╣Y+l9x<ìä° ⌠D└}\═,;u>}
  3772. ▀TYK0 ╟E25ΘÄ2&è / #╥+~ 6¡23å)¿ Ü;≈£¼┼
  3773. \Ñ°!QNÿÖä¿╖¼δ.ç 0½úÅ╬æ▒╖ ú#D(ú]@àâ@U>\┐óµ>≤δ ⌐Σ╖5áY=▄┐=p3╜.`└0┬á╗2ïââ2╡▄┐ï}aïé[⌡Ω.R«E}⌠âxδ*IÇ├╕âÇ╦╤J═Q  h|    (}üδëa ñα3$:di╔
  3774. Σßδ¿ε¬δ┼▒}<çûäOóze±"ÅXì┌╛φ╟j~─┌í╚ "ô&ÿ╘∩%╜Θ²╡w╬Dz╠°ÆS┼H╔Xτ¼┤VZ$Uj,╜oä£òvÆ°é╨┌EfòûÆ&kd0├)├⌡ô*hvç┘\$ôfö≤I▄;J~Ñw ╛í¬z>"QΓπ9╝ErkLh╤½▀║░╟`╔┌r>°`┴G4ü╨└¼l|<.:ƒ╤¡┤;-ëu║└p$╕cFO=V·aKIP╖XÇær8&%Æo!≡S/ö>░▒ >á╚G]:1!αÄ¿öèC▓╤fá╪╓YSr_πïÉ+∞Æ≡'╒┘]!Ñ%Pï{ƒ⌠v KI═WHïs¡ÖáyF∙▄Γâ⌡≡åë 2Ü    t$ ¿#L É╘e¼dé:O;╨é@½è█9δ╨'εpâ└;("G╣KÄ#/6Z∞\│╒▐dOA≡tæB+░ºαδ ê ≈¼x&δπra=$Ur■[▒▀M: uk¥╪N╟PΣ∞│S╨"÷ ∞AEoE╟%╙_<CÇå√[QERèWëh┤ïxñì4Aå║
  3775. ée?±s:╕└0╬F │ë∩b⌐w▌H`°ôC;│┬│Ö[▓$=√AúΣí}#▄p .┴5\YR!≥BO ░ò▄╣╦ï╕£yc▀!∙4┘≤Mp┌Ç+⌡íªü/▄ⁿ$Xz═▒NKk    G>.Yå½-A°6±Z╨∞£ëⁿ├èB    Ü.£5<;ïjZ!p┤╓⌡P`!Æ╢=     ~┼ΦN tgíà$╥G╤HV║Hü£V;╟î¬▀∙-dQ2nû╣!]8░]ä[>δ╚âän÷t4;z╠ 0 ╣┬"¡ÄBX/âδa1B(4kAx"\σ, ¡Sⁿ¡÷4 ÷¥╗á,#[¥v÷:Q3éΣàhxÿáSΘ6`ΓÖvΘ(ƒh$â}√ƒ!4 Θ\K3üEª║Éô⌡ü⌐=∙∙lí!c
  3776. ¼ë╛è╒à62æ=FOÿ&≡ 9ÿ≡} í¬e⌐╔ ¥╞ñαñíσ┌√V└╓µuδÿRB@óô■Ü╠≤KªαÇ0£xxAÆ ôëx«¥C┤,â₧$╪a{%ΘCεCK^XA>8ì,æ|ÉLΦ╤<ⁿÇa╔╔O∙╚6∙ûQ<╞g"°ö"    cyu£Ak*π ╢¿
  3777. `\,░─:Ä ⌡║;─╢E;°╝²╦Vj█╔ö█ ç}p≡+Qδvc÷$δÇëy╠ ßvÆçOa«Pë╞╨ └a$bRMæ»<╟%8
  3778. =êG ▌αú&▓≈ΩälB3A    ▌b═╒,î¿ é`U╚u  t
  3779. Ñ·≥ ¬ù·`Ω    Ü5s∙6su╘∙/pΦíôèJó+lQáJ╟2░@╖g┴╢²a▒?v1█#
  3780. é|`
  3781. "ôÖ&B42g,"╪+bp╕a┴~=b6╔╓╫N~<├∙@"F2$╨∙(Zñ╥`S╡    ñn*E^÷B╬û¬/δëHp╔^^╒jÄE 3!\
  3782. ┬╕u*,h6ó4│╝₧┼¼;┴ÿE!9₧TïC╔ÿ╠┌Æ╘6Cr%╩▄FÄZ╗²U2┬9é6Tm
  3783. *)ë ▄ôhGδßqo%WF<¿7[╚A~CÉfì3±╧à∙t AY@a3δ/Vp ?ÿδí√U╢╘çèyêâL
  3784. ZfmAé▌,'~! ╠-**<p}*ÿG─$vO╞Wë}/δα(Gtα'▐ä.₧╬µ╠┼%]-▓ΦM°¡,╗├Σd0 ╛Φ@(æ─╢#h `     :1£▀(√╗0èæƒ0H%Lûq6₧·╢A≥&δ)
  3785. ≡\9°╩é U&≤aâ¢Y  ╚╡▄▓╫]ê╚dC¢+°£!EºKVdp╡╕Cz│ù¥╖∞Y⌠└÷
  3786. ╫≡2╪ô8Ç╙t1╦Ὤeî]£{òB╘+≥└╧W5≡√8≈í$ïx·æÇ/lèÇ√r└░╪╡n:é▐{JìW Z─ºª(╤╒δ7$c¡ôô;æi`O H8?£ahvH^`╠╕,Ü│ölC_[+¿$>îî2;Iαè?êZ)█ ╗eªƒ]69╪s(îN╓ 4δτ?x<Æ▐Å┴+êûlòåfε╞í╛╝╫.,l22T0yÜ89XQáΩ⌐Ωí▓+¬N1F≡\╫oH₧«5ú,≡╔0_)¥pX╟Hk╝#╟X╙Σd╪√:ôk╓µπ>0─└AAór╓h╔▐ëP≡X≡
  3787. ╕▒▓:╪┬ x1└úö╘ú═t╣(E≥└ƒ╚î╢"└~EMÿ░lgè∞ä≡4g\q,dà╪RÉOsΘ┐√╡¿hò╢t├f≈╞e▌`in╪ò├ ó═5÷òT,gAßi(=hêYP!ÿΦÇJ@4]╬Ql,Cë"»{D▒X¥ üPΣÄÇΣíû!nδδ?M√Çé╧ï#Φ789°~▓╨;╠ë╬ ò}Z
  3788. }~H¼u8Cß1╗4}πÿó Φαà?⌠▌∞q¬RΩéïb¼¼d3)üäE2yJt₧DIÇΘíD¼@╤dAï₧║ åEæπ ∙┬■,öúuå╡+(¬#└û1∙Zñ┴ô1îÄ╠è¼DÆ╧âu╪áC ≥à/⌠ZÇ┬£ä
  3789. ër
  3790. Kv₧?#ä⌠KÄΣUï╨╪0ó    £┌⌡!$'2!╤^ε≡╪°≤█Γï∞╒ⁿ@F4@K
  3791.     jǼ:q#T0u╞áëá4y┴o²
  3792. =JÉ╩    9±ïr ■w;qr╨δ ╨ÿ6jr╤íÄ⌠╗Σε╕î┌£ë╦▒▌┐⌠h.ï-╘ëHéR}Γ9Θs┌╪Zé█i╕e 0ΣF▒╕┤r╫±ÇoìW6l╝êPC╬╘√╗sE¥▐A╕╜kì~;.QlAa$τⁿ╨╧▒ë°ƒ s╡∩≥╗¥t^v┼╘uFå¡8s}┬8n+┤ε»Φ╖Θ    ègå╜HΓ╣w+▌«AGú ∩╣ó╘I╚║─²ε¼√+j=)
  3793. ÿ¿0╔ê $e╗⌡ªè$0φê-π─¬éJ┴(éSÿc]âΩⁿ$■≈V∩ë╢+│╙╬S/ßf5;Ω½ê╒B┌à£╗┴L≡aCí°╨UP·C$ⁿà╣Oè4"Xh}ⁿé ╤?ôÇΓ■.å∙*ü2≡╙êé-"+ε&`┤~OÉ≈┼░=zh╦d]k└/kè ▓±còf;$u5■¡,K╙╫vV╥∩ááë ┬╓F ;)}φàr,ΦïlÉ4█║╓█P╨èODÑ ⌐(╪@%T1≈}{"Z╡19╒r@ÉÄÑ╓┌┘\#*C7ô▀^XX▄╟:1φlîÑá╟ú:T╡╦└▌àZcuδ
  3794. BG╜┴-ÄÇX)C r@▌U╡}├òÇ╦├╪t ┘ëá╤ó%î4X'µπ╧Nε⌐¬D∩ F╢▄NcE╘┌zπ├Bîµ    Φ1└^╧╤fⁿÑú┐Jê @Γ╖╘▐Ωì>╣úÖπ└vc@┐MkE░*╪Φ@J █o|P¢┘t¢ 4$╞!┘,$┘ⁿ┘lªho|¢ìd αh·ª╖╞íè
  3795. ä½BKê@æ±tAφ¬uK╞Θ⌡@1^k%år^¿RG)8ì╖Å┤êq┼°rtwt¼êûaº    ª╖ÇÄ⌠w(qD≈?╓èí°╓╥Ki╬@∙+u%Æ╝ò¡╗èC@0bttJ╖╢wO$.FÖu>δà╨ ÷Eo∙buè[üπhQp√6√=! δl∙t=╔¢3)D;+δ╬╒u¬░k«.ÿÄuܺ├ƒ█'ô    éδ⌐>é║H7⌠ê╪¼╨w╛Ça ⁿ    ⁿ╦Φ÷░X╪╒uK÷├▌NE!9V    @t█F⌐╣H╠╠«    +┐MBD╦!Çt ┼ä╡í╖)h┤awGδRPVYNêΓëAnëZ,ayí°╚üª┌xbá╟√▀9Θ\FRå:á≤┘24jë╚ó]ë-┘╘D.¢wφë|!N w[ë╟P┌▒b┼è▀bD _Q╢Σ_═ΓEu<cî├Jëqêí⌠╕à¢╒5)~÷Bjìφ&└t ⁿ.H:'î╗╗½ w╙║1öï3J¬┤;E"L ┴√6ßFú╬═╧åqWì▐╕@1└╪ *8é╗▒╓j3┼Pï╔¿#÷▐≥ëx,
  3796. é╓╢;FΣü`û@S▐┘Yú]δ╫eΓ├1Mc▒σ|]δh┴DBçt░[zCI]h,⌠¢ècô÷,êΓúΦo▐∙ê╓Ç╬╖s▐u┤Zí═╝Mrë┌A╨'│æδφ(pU4C$0lí┌à─πêDm    R╢.5wy *╬)╚C,
  3797. ╬r|;S4í╨Hm?å ⁿGE±%╠[σ}G┤Z+D8¢êU╜éV8>D.╢uQσ'∞δjP╒╛╫çⁿ,âÇÇ╓6║të-à[â╫D^u┴δ▐₧╜{ß≥u∞1┴°╞A_Aσv╓'.    tl+ö╦
  3798. m pq ─╗¢P╤φh╒âx╖a@+Ö▄è  ùà`N÷t ╚¢╨¿@wHσT2╒0A╒╙áU .°j█wnëñ
  3799. & z    ╞÷k)«
  3800. pï└▓░»}wÜèQó╒    /u^TT8∞|älX¼è!_ XG2╛┬zy;▀╟╪╢%^¼åM^z»┐Z¼cX[+/OZ√hpπÇ∩;¢╖óX░Zª)╦1q╪èδz[)▌b═╡╧2▌ |9╟îá'¬&-δ╠¥Éí╓òåè}╫QPbα5╤@GÉq(å;Ç╓╕H}7Or╓    Ü!uöL1█pò╛É≥²öçEò█à}╗Sä$£    <r    ╕ü╖┌v╤Aδ⌐ßδú+åo4tA°X│I6GH)·δ│Äòh"êzz≈{{·░═┘)°& δÄ-∩ån░X╗êQ é5ÉΘ#èT▓╥|Ñ.ò"\yxoU╒▒≈è`5T \±/₧.Q]FQP├5è@╞⌐>└Γ╙╧~36<y    2{δ0⌠ü▀ë· ºq#╣╜╡▐«mΓë╙ë~╝w≈÷{l    ╞å Kü─Rî≈c    @┴╕! óüi╪K╟N│╗#|╞@ëJl^ë≤ 0ëÖÖ6░T∞╖█K└╞F)èG$╥α.│d2ê7(║B+╫Të╦█BM·φ â·@äRáZ╤Æ╫D─φÇë&ïæRΣ│%éÑ!αlΩj░uw°δô=6*û·m≈Ñ?T@A=«|₧±òR▀║≈7∙GAêA╝@ⁿ5ä÷≡XÇ╕} 7╓▒]D srhD( _lèD!l]4_"TV¢b8─╢≈╕8ƒΓ XF`HMQsÿä/└δ·âbs~╕òαfc00πL╞╞áÜ┼≥╞/xÅYSLµ°▐÷ó^⌐h ;f@╙▒W»è=δï╗`@═╕wo¥φ/δ(9≡v│ΘµAë    ²▀î╪Ä└&⌐»9┼]Eêq¼┼NC{╒êå┴Φ┴¿└ï êÖP}?*vRQÅ`
  3801. b├└┼nòenº.∙ B8iòLZTi7├(D╒    pèNn∞@'Nâz▌7 f.Äxÿ╕k;T4ökZé ▀ó┘K@s(ì<9╟v!ìw÷ ▀╢     "OÄ┬²NO╤Θf≤Ñ╔FGt¡ß⌠ñⁿ4ê╟Qz«p3@Yâ?▒¡K|/PQ7┴Γ ≥|èh[ùYX~ì╡«╠FπÑP≥PGªRδS1½ç Z;Ç|a╖P╡(|╠t╕ < å[P5├|⌐╤ì\▒âµìêh~=æqrP±
  3802. i{ ╗▄°60mS5║a ΦÿsÅ░i=%}╥YÇj Ä
  3803. D∞c c 5╟║(∩dOσèdÅ t\╣4u_M└í#`,≈ö╪║╓╨!4÷    Z3Φ
  3804. ║Ç╕ªXöv -ú=║X,╗$",@┐I╤█ü~δ┐`@uφ┬╬9x
  3805. ë┴P╢≈⌡0U├HΩ,>çÆσÑΘ!W\SïLQ6ïπ
  3806. ╒╦1┤╛δ▀2≤▌¡#GQäⁿy*Z9Æ╩^Sτ
  3807. ^p╘Q{s    6╨èl╣╢┼-╘á-∩╖ Ä┼yHRR(mu └╨%RlA┐Ü┼ß╝╟F"R├A$g^/%í▄a╧δ&╘░TsAR⌐₧9
  3808. é╥`=╠Ä Z]q╚~¿"X[Ç╘7`ªCü┴dPí╓?èos└é@$ï ÆΘN*╢A┬=R?%Σ┬φì{│ê!|╝û1Zh¢ef,ìì╨┴δΩ ,Wà»═L4}ÇQ└ºπSU║╧Büdε╦Ç.δXSE│m▌o£kdΦîë╗cj"┘ß@╫nφµ╫m∞V`»╚▓qDPßiOP| sOöÅtjìaδΓδ6ⁿB#┴µ∙u+Ä1\⌐áo7á╪.! :#╘φ■╗·╓GBê .@C;,r─werà▐    )╓a ïPíw▐-;5⌐%(─^7ä½╩à─1dvPä├    ì╗êpDhè4■╨▀g┴ T≈Dät▄BXê╤╜:n├[¿Φ≥*@║±çí(Fx┐x+üÄ&è"ên┼╖╗═A|ZNêπ
  3809. ╖╞∙╥▓8αZb∞@êαi|╚ÖH:e╝ABNcZ▄û╤Wéâ╬fƒôQRΓííûUEZ╦üî╨` 6£Z╤É"╗Ñ╪ë    i╬ä╟OÇà!6á╔    9∩É┐>R╩LÖδ9ùêë╚0qΦφ┤s\â╥╪3▓╛í"■úG_íVò6╓X'┴ï▀lΓ⌠jr^δhl─9δ0≥ñK
  3810. √}áë é╡ù;╗¿÷⌠ö╪;▐í$óT╜£)∙┌(▀!£M┌:─ÑÄ╘î÷ï0╢zâ襽:╔█╬ Hδ█\╝úI 
  3811. ágwal⌐â    aá$╛yóíáαfäç≥¥¿5púÄä3gÄZG»$ä
  3812. êΣP]╒P7╖
  3813. 6╨ε δTm8-¢Tk8Φçá▌ä9∞╢Çå>c╨*e$╠▒╓─S║ßS-Xh½├;Σ╟╧1├≤°┘ⁿ6V${UTZQâá╚2D.ΩÜ°²gf╨J╚5,Ç  ┐    ±WATCOM C/C++32 Run-Ti■φo²me sysñm. (c)opyrigh┐∞Ñ}by 0Inrnatin┐φ╢ol!rp+1988-95█m¼▌
  3814. Al2ses)vóëΦed.o·"ûásl
  3815. |{ü%wi¿ ■!╚%Çt╗é╪uTJO╥,╦É:5D│,C  ·┬6Pⁿ┬tö)K@oé[8╚um≤[|╗└8∞òÇⁿΩ┴ΦP╤Φ╥t▄└╒êfw╧vä>#ÇδQÇá@÷√!k╓≈W¥δQtÉÉ·▀╨ûJcƒΓ╝╙{▓Xm╓╬]Fâxx;╧₧l u@â╕└¬l=¢Pi┘qRÇ╟l¢¿Å ÖVí"┬╞eì╖}$á&+ó    ∙tj│î(é}`l,nü1ù6k╫╠«º┬┘D╪Xα╧V<°Ωéτhåyê∞a`╢°°X√6W├;╪4@h3B&╩Y╤!b╟@Ä_,ò ΓÇb/5F    ╝█îÇ:|£ ~ ▒Hâ╡íon?─╠╒W£E[%â∙n0k- π]Ä╨\Θª
  3816. XÅ ║ƒεYl;ü>╦T    <£vσëLV÷║╔5∙┌    a▐uQ-╫W╠╕î∞¬ÄÇ{╓δ?╠Æü,┬≤m∙"é0ÿk╧╟▄F▐c"7s/4Y∞]╧Nα'ƒ2ì4╒Φ■ï╗ì~Xì▓├&zkBühuαjδnì├
  3817. ÿÑZm» └m║ª╣t{ÅSJU7S σ8┤$@╘[¬2à<çl(8ècH│ln    Km d┤╣┬%äsv╒çoçÇLY¿_5╕éü√Y≥Zù╕å    ïV(8ƒÇ°
  3818. ╕üQ┘·ñ÷D╧ê±bH7dÄ Å▄:`δ
  3819. !█ )▀ío▌èJüß0üßÅ∙[+[▀ì'ûφ█&újR&ΓΓεQG·01N 2ADsæ liäf╩╔╙ΩâΓ∩º╗ó╒.╕âï'╕ä∩fú· ÷F!∩è╕ïàÿEτ ╕àuú:ߺ<KJ¿∩gnó|HJ¿°j≡ V v¡âùAǵrë
  3820. █\≥ßU⌡┼    φ<╓x ï3;t\uIÜX╞Æ/█0E t8@╠u"╪+z₧Yx─┌!├╜?nj┤Q╝uA╪`~á öKn│╝ä└r#{=û ₧å√    ┐7vX=² än{[Γ=╤┐∙i    =t?δ^â{B╘ò√ⁿîû≥t Wïk Uh₧_(░í1rxqδE╜⌡5ePφ╓K Q■▐á┌
  3821. ²%S R
  3822. ZδΘ÷┴;²òδ    +²╟F  ╜ █»»÷▄ê3Ç*₧ Ñì╧■ ∙ènàbâ:║G'(▌T¡rëτ+ù▐▌L0½╛$'PÑ░E⌡5. ;$Æ°I╢█ཪ$▓¡nºïe▒$ öª]8órsa─7Y=g╛S╦_╙n    åQ9sP⌠ü╤╬·Tü─9]&ßé└═f½hl┐àPT=dë6%√Të
  3823. E+Öx▓ªÄQdëΘ\kÆ√<&┴:Q╬╟ct┴δ░╚t"x êD₧l╟Ç⌡═0p/4Å┤á╡4δ=JX╡Å╬⌠'!W]ZÄuïWB│δ╚╔DIΦ-δÜ∙¿3*RMeó.≡}αK╧÷╨╧┘°δH╩*W┐DzΘ▌┘├N╚≡"P^0Yⁿw    Φ┘Σ╬¢▌}°▌UΦèe∙₧u≈o,ⁿ▌9≡ëE°ëUⁿ)■M`é3d_é┘┴┘ⁿ╪┌n┐φ,·¢*√s;░.╙fÜM╫n╖f,ⁿ▀┘┬qⁿ²`¡╘₧┤█\Ω]{)█┤êa\╪δ₧▀Ω╩WlRcj¢'E÷f%oé■≡f-≡?fso█]ⁿ s ?■f    # è_ìδ+f@v)ê÷uQf ~≈╪l';┘Φ±▐±c»√╢'╙äK╥°B°.·2ùn╟
  3824. kP╤αcα ═░è/vé^qû┘φ╪╩±]`ï¿ßö░≥╞+ö ╨Φαs┘α▌┘F µób¢Ω=Φv╪╚δ≈}smπs┘2     $▄╔δ≤2!┤╓╓îeZ╖╢■pP┤ìE∞5Uï]3²çΦèP┘ε▐┘d.m
  3825. Z    ■hi∞⌠╢.▄ ìe⌠╟X]╛7ƒ·u+α/i=\|gà ≥╬âÜá±z╧∩$⌠╘/ 5¬╓ìl╕▀cj▒─D~?#úÄ╒àÉ╘▄ôr
  3826. $▀ÿ &0ë±)╙║DB¿tPëf─ær`+
  3827. »ié!╤á╝²ÇìÇ^ Yδ#╝D?KëZm ╤V"R|╘Pδ╫b╒KÑè@*╝=oªó╙; -rN X!╦ër÷Q√;-èj Ç═bê
  3828. ╝├è%°Σ┬=ùä(S÷╬è}w    ÅKAìë
  3829. èA ╞F5,╠┴]kΦêc╘iaXX╨Ö°n "╒]┼┌ƒèq├▐╓¿▀|µ√%$z=Çwφ╣Y⌡ëY÷ûe╘(½≤∙±╢ΦüLm╩7Ω¬╞╢ü╗ δn#x$║ûçëOq⌡¡║╘]ÇIÜt╩÷ôΦy ÑÇ╧ ê ïZ┤¼êç░     ∙yu!'╒├(lb╔H╨(┬:.û¡m
  3830. 3è= ¿'.▄"┌9A╞m2F╝~í#ë2Gïj±9∩u{╢ï&ïδuú&ê║éa@¼Ä+ ▒∙mÉ∞;;ru*ºt2É╠}ïààY@$─óÇ4â╣═■┼A▀%ï╠Iÿ┬d«»┌vΣd`ë╪ây┘┐t)2Φ▌ è_1÷âα0┬P└B╧d%╤:zêB#nÿ█3}huD╕_°4;Er;M0├Çτ■\┐Ç╨`E├√░ b'╩ P║=lc òMíδa╠v░Täu)┌P[  )?╩t Lï»}┼h┐╤ ╫è}ëk╖╞V╫╦u@ ╓pC▐¿Za]ki÷E╫£ß=%╨FZ╞ƒ█▐┼╤)ë╓)º¡╡▌╫ëtg,å╪+i²╖α[èM┴<ê═Çσ·êΦ╝(ôP╒|╨TRB╛Ω▌Fε:` .αJ(┘à╖╖Fδφè▄<≤Ç╦(Φê¬ó╜╪]åfÖ6Såv@èQ═░ ô¬5▄    ├+ë    ╓:┼ê]≈≈±nTíbσ≈πÑAè:y■pΦ╥≡-æ{Ω7▒Φ╗fRε^áLⁿê╩&ùíP₧<╘αk■■É>a└─ÅjÜ╥ä╨╖!^t8╝Φ};{┌    9,8¿&·ùJƒx@┴╩Iu≤┘J╘Aµc
  3831. ╓Ω█nIpêP,┬α.6g¿├ì▀░}╢3⌠t:")÷w_.I┬P t8P φmi║, u▌ÿ¢┼╢≡('j∞┘MtαÑ#Z█■°â└ r└A\┌╢    ░├┘¿╗╓|Z}oQ▌u[┴5¼╟¥¥úÇ9Ω&α╦_┤°⌐÷g?]εï╨╫D8¢    Φ≥)F8D░⌡?╧╒≈#áp╚&Γ┤┌q¼iè∞∙"e╪* _ñ"∞¬º
  3832. (≥&@=ü┌
  3833. ─■~èÆ╛gK┤\u"║∩
  3834. Y▌┐m─½╧æì┼ôÄSì╠▄V[WA╚ü%óⁿ_Q-æ|²┴·$ ¿εå√óⁿ╣D╡b╘QKplXïπ╬╓·c0∙δ]╤⌡I╣┤dí{╞ï⌡╜âK0╕¥Ç╢û6τ ┴_+>║ í╡°6┬░SYcQÄ┌îóΦZÆ╢ r@$°┤⌠ )╨⌡╔!╚╨;Cw+ïs{o▌nΣw    ()ⁿ9╨éù╛╥v½"╧≈ìS ╖║D╡U^τëM)└+xk┼δK∞- Ch╪j Brrë≈╟│╖ì¡"J^L_Oαo╦ë{╦δ K-╓┌▓╡╧B~wl╠ú▌ó÷âⁿY─9[╒M÷i4º±ε¿╗²≡√tµ$■[≈9u;cu>δ╬φ╢hSïfïo[c.5╖δ|} ▓;¥√▓▌dwn (rgδ%^,mε ì{ ;s$wV)╥ï╣/A≥I┐╒@b%┘)╩└éoφw█m>ïh¿jÇ╔.-┘┘[âÄ Hu∞XSΦ═┘┘Q δΘïWâ┌╖]ç·ë°¢2^█áOm¡■δ╢l à,Vⁿ~w┌∩6├╫░s;Kv$â╧╓±FP]─è╨¼]⌠¬·    9┬rjë≤ÜZ─B╨ôS54╤uú╨δMP7─ìZ I,╟B⌠Q:''█Σ∞≡*Φ▒
  3835. îâΦ,TU∩º╟û╨dGâ$PFÉ▌1■√j4└■t≡≥jNj] GíèjtB╕v╞#╤║╨«.¬\Qöâ┤?Γ┬Φw┐8r╖e
  3836. ╕εHYi9├▄Ω╖]")zÅzGì└é"z¼`BΩ£    h»zVR=¡ZîA┐í«ß├┴l8P└<;s3|αU⌐Tö╬M┐Ö║c╚3 LrΓ0└ÇU▓╢Σ╝ÜüKdx█a"ó─2|·░úbDÿ▓£█Rù∙0¢
  3837.  S¢▌-Ω]ót,j║j┐wâ"#áéfís-\¿á^9.u╞ Φn╝è%
  3838. ▄■K─▀▐=ê    R╥+└P█π#X└⌡è─0÷£ºZ~[╘TE╞<≡ Bl∩÷0:ê56⌡├÷╜8 p¬î$└│ó╪0█Cê£9║á{í<█Y÷▒`│
  3839. ╜lì£)ÑÇç"£nª╕═÷èGê<ä},╢°▐ KÅn0)`¡¥∞Oèä╥]Ö (▒√$@èñNÇ MmQ,v■Γ╞╪∩é°─Q°ïä~~i∞┬&pδπtMδë╢m┴ûdⁿè=╔@-òjΣ▒╩¥i%`÷U╡Sì╪▐▐·òÆΦδ╘ëΩë`Rⁿδ₧,█ÑöƒtI▐¡┴*
  3840. ─P*M╛CfÇÿΩ;¼T█iΘ£Çfì¥,BÿδµF█╜ókwl─R°k≥>}╗╢68 ΦXPⁿ4ä╟ÆLìîcG8αer"Θ4╥p¼tÄ┬"Fu8c┘ª["x,êHë.X█¿█╩∙σ┬╫äb«sTëùo'Asⁿ║├!σM äH     ▄εà)║0uL╓reC╩ôt¢é#1sZSuñ;ß░lZ 51ö'¢Ö3T&è╢p░Pâ├¼╧0P└▓ötA,Cδ╒[ █╩[*±¢éh üRâ╝Æ=│{ßÄs≈w+a│═∙&Z║ AD.─î╥Bµ$é■Φ╓╞C±o╕  p"╟C被é¿î&!kQ⌐╟ΓK
  3841. ºΩ0@±ªs═û 2~ßδ+ ╞╟g─*u"ï°/uQτX┌èS╢5╤Φ≈▀ÇSê
  3842. @d▐√∞└@1.uIu¼9É├B1₧∩m≤#ò┤═]
  3843. æÉ@ÅSπⁿ÷_hYÇ·NrvVlr v"ô7W╜wtht"┌ y√Fr>v,LtèsÇ╬ @êÜk─╟e░«ε6Ö█S╚¡"Çδ┌t╤s╞    v6╛âG-DJéσ╦#█@
  3844. #δ5+uèφ╙ ΩÇ╔²êjδ Eè7m╕3
  3845. ░╔+C    ░p█¬N0∙«tt╫W$▀▐(┤Ä┴bºBäj╤*vΦ·∩50÷\#┴[╦╒q½+¡#┘;ï9æfé╢tS▀╟t█'δ╢$b╒╗┼å/áO∩τñ║â*dXεHì ┼ "ì(δJè
  3846. Hê K⌡┴ 7m(PH╞0Jδ⌡,$╞E┤≈éìΘ]Ç\é╨B▌7º ≈┌Ç╞-â0·^ê∩╟F≥
  3847. ▌b═»╓ë╩ü┤è!╨Eu╣/╣ ╝δ≤.{,╞.%@#░≡ì]≈R]k╫
  3848. Mè Ç┬zp¡Φ÷êA;R|αs▓┐{û₧!Ç ^a9┘u9ìKα nÇ1>v&*╤ìƒδ≡g-█40₧cöqm│╗εAδ⌠AMδ!I'R¡Bâ    9C│a>St╖rδ$δΘ⌠ ÖαA$s▄Sα&!╨,A3é╔∙/╪╪(Ä@│ K╞à╞■·iråg
  3849. uyvyk█╩xär╞    oÇⁿ.(~XrVväEδMèVìó & Q2╢└OïjΘ%╘φ╦ï(â┼(╖m
  3850. ïⁿÑ╚@uSkⁿÇf∙a+]8yT╞F╥2y╦c╦▌âer`┌
  3851. or<σΩæ╦cÖsr#oé8
  3852. «∞óBåLíPY╢¥âÑv0pX╣═╢/grb&Ä┌▀[w╢'Pr3?/╥Y▐6{.#c▐¼B╗.Y╢7S°Fa ┴^Gt<⌠φ4
  3853. 6$αó≤ë╨x─Ä≤?q&ê┼jZún╟rδP╣=ézr*╝╛íä°:èF╗\¢éV7Do0G¼|:~|δñáuu&▀/:sW┬ΓpüÉYmçLôBë·ÖÄDδ╣Ü≥æ-╝┐E£▄/δël 2Ç#m╟qΘ 8ïO°Wⁿ╨nM4αf╙┐δ>▀xÉ▒]ìδ40@ï«aá\3,∞;î█t▄#δK>ε5[êφÄ╒^û▄ÇφBΘπ∙ë╖ê±╒╤a≡"ê╪∞&v+╓ΦdA~╕,!
  3854. ï^ÑéE╔]┼!Xªt│.┤╣0h┘Fp ╣6kVj¿XíQ-å├⌐w     aY╪EsτàaÜ▌¡    8δFt∞╪σ(êµ╓αpªσ÷/)^á"φⁿ╗r█#|▒╡╚ ìWç╞≥░WαG:kûp╚▓ P·╟z╡¡0è─7╧╦_W~αèvSµ∙╕êa∩Σ.δ)Ñ∞√+j[φ2F $*╞ê    èmk│$
  3855. ▌O╕&÷å╕5A2-Hδ&²î▌2 δ[╡5â+Só╓╣ëaêêì╨╙û^:≈─╓*92'╫åfé½    Ñâ√
  3856. ûo)"cR├│8πì'<íVtîΣïn[~δ
  3857. ù`Φ╨▐R╚T»^öj
  3858. &═°#0╞Ç:*è╣╗êBδφ╦¿C    ƒ'α)0"ƒδ ╪╖$h├$æá>µ"X6JöwEzπüτ▌á■vêCfâ╧δG+
  3859. &2!¡+óP@1ó╗íY┼ì9U┐oohπ#╛?Φr╪.{▌╕"┐C&.⌠¬Æm±'φ jì║jaëuóφπ╜     ╤à╚u╕É_iêÆT╞╘╕R╕ °%ïHXk─ùxëìèI ΣêK (┼▐+╜┬⌡ :fúè}Çëÿ0ëJ▀"öB÷@ ùÅ^Dü╕óxk╡└èZ&╦├÷├ó≈╛▌%ê┘_êJN/┌(?µâz8b╢τª%80BåhôF>±ü    NhBïß■`¡J!Çß°ìBZáo▒kóÇ═¬jδh    ┌╥áwKéï╥┴ÜhATφ╠╩u÷ àƒτÇτÑêy¿▀÷ó╠Ü╛
  3860. ÅA▀íèφDk é┴    ╘╘àz≤¡A≈εv╖c╛Y ⌡ë┼êδ¿Φ¡ß╕ în╠ ╜·A┐╜~
  3861. ╫)╓δêt2QCc    Γ∩@(8Qk(▒;L≡┘Æ╡î÷[ A╔(╬á$ö▄Φå=A[╩≤Q "⌠┐ô5ⁿTlìéD1÷╠!à╛ Và?│;'Eê╨a ╤}ïWK─╩Tk╚√╛ç│ÅΓJ9≡xÇZî]uÑ⌐fT¿╔GÉë╪Tê$óü╨/XDÉw.A] PÄ"¥√hΘ%wM≤{■Θ\PD╬    }ôσ"╖(jv┐)v║╛ïéEà ûTæ──
  3862. ╬ÇX▓├? üΣ╓é╬╛SVP┴;M éƒ;C! ßQÆ|╟
  3863. ╤┴Q▓^a╛MZS(¼K¡¡nê≤ìX╩òk]╛╫"    Aºî┼7èαFv,ëA1 óDΩngà+▐ü╬@àâ5╛è╖;┼╟┌;ⁿÉáæèφúV─ ╗bo▌╚~ë┴┼F¿ì¿Ö┌DyH oCêP¥¿▌ÇèÇ@}╪µ╒ΓßpÇ8ù£╝öhä╙sΣ║5zKf▐ ┴πé╕£═╒tτ7h%≤ì7ì@├¿∙¿g,═φM61█ß g₧jW ▌:ë2_¼-L┤C▄√└1Ä#╝B┴ΓÉÑ┬¢┼■;úë4ÉBë=⌐│a╒HAºz
  3864. αê
  3865. ∞εJo┐δ*╨ΘWj÷δ⌡δαf?,⌠¥ªë±Y£╒ ╢U
  3866. s╩%'Åm┘F}ìQ'[üê¢╟Cδ▄⌐ó]╣╕δ∞└╢1ΩFAétí8 4!¿ú╞:éw;t}╓cÆ╢Y3GéѼç¢╡╥6¬Σ└¼╓L⌠áΦ┬╜ ⌠añÄ%»R║\Ω;ÿ▄.ë!Üç╠£%∞┘╫D═Σ╠─
  3867. + ╘°.P╨╟╬Çf╡fîìK └t±]⌠╛* ¿m(▄└Z╩p`Åòπ@δ∞G├∞îÇ@))v₧ô∩  04╪¿0ub╔~ñy⌐π┴â∙∙╔êßâ∙ái∙p[C╖Éè%½╧δσ▀!,dö╛`XW₧îh╪å¡ÿ=╔▓rªO┼1v╕7`√9H÷┴┘ⁿ═@; ╒êh^▌
  3868. $cÅ-ÇL     ïÉTÇ╞╠@╤╬@GB▄aÇ╩±ë╙╖Φ╓ºHâx╟@
  3869. Yo¡┴f=╙wv█í·pà═ä└!öé.─$!7╤>üjôx≈5▓ÿ&ú#τÆ▒)╚@cAƃ L¬╦╬¥>╢í
  3870. ╚⌡t▒CÆá¥
  3871. ▄╛σ└$ⁿ╞)─,t±¬\åì╒æܬε}g∙▄╤å`í'╣Γsª⌠@τá∩K1αUó3G╘S╘ú.╖αº#Jä,cH√jP≡π
  3872. PR╓P²J╠¬·µ_WΩ╠R┐4¿Öex
  3873. çm;âF╔PëM∞Å)ìóMⁿ}∞6┘?¢í▀u∞░▌ε71┌!≡    ╨ëE/¢!` P1òΦ ╒C]▄/]°F C·ì╞zâ¿$Tèf 2╤■à╒ÇΣ╧âσ0ê }@≡('\N╖êªF¿üò>àc&kEFìfα└╓C#πì≡ê^O╬ F÷F·XQ-û~     ∩çh¡% Sêxr▀)*6╕iE≥/äy$à»êû&]╠
  3874.  
  3875. ÄÄ ΦδO╡GlX│4█δ8@1 **╞╩≥rr╥ëUU>V4qªü┴xs5╬'ìUnß▌]Φ5âß▌EΦ(æ┐g╖1
  3876. εâT░    ▄┐lÑ╘≡±₧v<>`¡╠m¿╝░N2f
  3877. g(▄w┐≡▀{δ┘Ω▐╔┘└╔╪ß┘≡O
  3878. ▐ ┘Φ▐┴┘²▌┘░0qé─ └²⌐┬ÿ█l$EmDz└âÄ┐⌐[uπh▐∙jÇ╫╪┤╚Y▒]m9╜û▌g=å¿A╤`┘@╓'Çα?┬≤╠⌐êt█ ┘U +▓║`«╗╪E╪ô!Æ 2µP▄▄ZÿkÇ0 òt▀ÆV"mÖò╕t'2╒s*#╪V░¥    r'╔z└jo{ìΦα█c ¢s!X C╔|üénÄb,│$Σ╪₧╦▐]#,├═╪°
  3879. ≡▐¡ï¥┼▐R ^£█@ε█<$£â4`t╚!g╔8 ÷X
  3880. = 6%s├gF-l▓æï╔Ol6É╧cÅ╩w
  3881. k╣
  3882. Eo┘╚▐$>wëô░eRú╩22$╩╦╩v╔╚%╩╦╦E▓æ╜$>w`╦▐ïRúddH&╦╦╠ÆæK&╦╦╠#{+∞╠E$>└û╜ewïR╚ÉL6ú╠╠#ùL╚═╠╠═÷V╪%═E$>-{╦FwïR!ÖlÇú═.ÖÉæ═╬══¡░KF╬╬E÷ûì∞$>wïR2┘[ú╬2!#C╬╧╬aùî\╬╧╧E-┘[$>w╜╢∞ïRô▐╚r¢²"d-%[â▀åM=t3í8ó;╫Aÿ┘&êτXæε55PÖ∞7≈┌∩Θ█,$¡ ╪t)K╔ü<═ ≡≡▌≤òLr▌▄rò╣ù·üL╚·|· rÇ·|ⁿ((╝2┼ƒ▄Θ1ó▀D▌X¢┬ ╦¿keÄ÷tp½¿8lïCd{¿Vh0H
  3883. Nûôφ    
  3884. n5YöC ò½:{D·èxÄ╛ ≤=Q5G╗∞ÇéÇéïE╫x▀┬~√⌠}½î┐╖âe┬╣0*∙ùó■K╘}Nâ╟ δ÷╫ì■╜┌╜åó▓Æ┬IÜìN3à1m°A±┴∙²[T~┐{ï} hφR╝ ╟O≡Oå┴;¿'í D∞U¿τJío÷}    Oü╞ÇQa¬è_£≤ëΘë≥N¥èS'ih_*C] ╓ΦÑë╝ôªÿ⌐°BH~+5Y@╕╓óOü ▐cä╫▀x╖GTy;üε∩:w4Ä-#°è°ìç-áL└!£╧▌òm3╗)^°╝Γ½F⌠√G~èâα+²┘c╖├ê≈╙ïπ    ┘ë▒¢êè
  3885. ╝┬è-°s╒Γ ╥    ╔~─{ΩCºü∞¼ç%≈R4EW    ▌à═.4╬5(âPê╤}─ 1êé¡D]½ :q*óàyRV4├╢ä▓½¿jíúφ─≈.╬"▄ïê└-v)╪░T≥+│ ▌╧α-J/,╕8"
  3886. ┴δj|@─kèê6φ┌E σ/,X╞&Æ»*W╞]DäτçµI½└ö¿8└°àhX@ix?éWá|╣4║é▄Z╜p√P┴è LΩ\╪α╠n╣É╩(U%%!Ñ(n k█Bñ
  3887. p @ìZ╨δτëlcΩσ⌐g¿:uìÇX√ε≥╚U─BH {╩╦[┘b,-t+t╕² ╪MEEδ{Φ)C≈═╘┘j~╟e0è┼L/üE¿▐-ì╞┘ÇX¬^╣1⌐Φ&AÜY+'n╒è[0ªtZ▌b┐oìµ÷trå δτ¡╡≈ατ╡σ─Γ╗╢▓çú@ΓYjm╦i≡░HªΓ≡)[▐¿Ñ≈$yH≈┌V░¬╓h║ÿ+└╔V╤ß╖°,█┤J╛≤÷«ÇMf¥Ç¬┘%è q q■Q5╡ß    └AδMÜ`√H    _5û∞5*±2-)░äv ∙êêv╟J≥üAx┬└ßo┬ë/u6*@.íPA├T 9├sΦ╒ Vd╪á╪7^╧?FvWíå-«@╨óσ`7éLEî╚ìÖ4&}╨)╦SâÆ⌐α█=,u<ΣjÅ{√╠▀α,ulUZ╒k╨0▓VWA÷╙ï█)╞<v¼9k = )╫╪│÷K╕9╒ë!$#ê╪ë╙]ocR╓▌ü·└sª|ü7~ì▓)▐i╪▄x≈≤íδ╗ é═╩╞╫ì≡!7╙╛╪ ÷▓k/<╪?╗n)8G!÷┴┬╨wx/l╨ì3√)¼v╢B ┴w'â█Φ ìéUm:9├rƒ²┴█Bδ≈╛⌐ëQ ëY√Ly╛╜{⌡┤░╤e╒VZÄ ·@uxFA[ü╪C¡7 Ç╢εï╚Lh@ÅG3╟B XAç¿âå┬áfΓä(èæΘZCÜ°ô>÷├u+"d∩├ j╚zl╣É∙Üç╡┌3σ8SU;╬Ç$xH |╦\╕0÷╥»±(êE╫£ >Ö∞ÿδÇ~┴■¬X·á E╣x╒a▀n╘\╬Y.úxD]W½α ╣áú╪
  3888. C2Ω╪Pê?╨¥u╡-═)H÷╧╡╢ε0₧)╧}≡α\¬VßÿúH¿R4߃@╤ú═╪$┘r█#v@):$╤╛ß└dMp;rAá ¬%·
  3889. ┤|ΣY│Xórº┌<
  3890. K▌┴!≡╣≤[Θz¬┌ätjô.¡ÿéHJåεëB┬τ>▌*Γ}?▀ ╛╗δ
  3891. ╛╗E°a#WQïiT#▄P║▓ìD äïÉVÇ╬╪U ÇP·¿ßjEÄy-Ωé┤t ç│    α/âO┼~
  3892. ┐glì│=ö√╒Cù╨A3M6    R|ù+┤ h╨$ '░[4 æV!Hà╓!Ω"V0òÇê»%Ωôqï╣╠ìHìs╙u«3}░îb.\+0└n]äê0@H*    ┤}~;δ5Wu b╫╜î]íφéΩ9┬Xë╢▌{BJ&8(\ë╟u?6αI╘7÷û5)Ω╓8üτ'
  3893. Gú╨<₧Uó╤²G■╠╫Θ#&&τyX7÷,ûCY°J╠ )╗kÆp    GΩ╜²$╨* %▌ü]¢╠ÇHBk KhDdí²_▀╡$|Φ|îb└ZδSìEn▀╔    lΦ*@(╫B^╪}4ïSâ¡y╖δ╩0├Aà« [bF,y=° @,@W┘yçuú4I╚U╒}rá^¿Hòu▄ áÄÄj|ûè╘}@u¥ ⌐]nD?êΦ7Σ∙T┼∞^D■⌐74+ΓU┘╡Fü`╙#Ö┴≡"bH'┬╫╪bTüñj┌Fpü#üì
  3894. Qiíα'O¬h╪δ     
  3895. SEƒ╢_╜E╫U làφA¢ü+]¿Çâdεt╒jÅU╕Vc╔2vX¼0"S b¼· 0å¿┌,Φδ-jƒvI~≈ì(│;$t
  3896. √ ┼baú₧L/à╢@üc╝:▓├E"⌐⌐Ö╢Γ┘-hα:⌐═ªD¿áú╚iPV└²²]në╩╞E~]r▌φXX⌐MÜ╟ÄEVPJ▄╛ZìM^]bûkAφ!¬;@ΦÉxⁿ╠¿½ÄìÉ╦o┤    ZEf*jÇπ ▓£D─├╪|(bzEb╖-¢√δìeFNdJo;{tBüΩ+PUz^∙█>U¼á3Vbj▄äEoIïUV* vs┘ïdkr#╕▐╨^M
  3897. ┴~U≈MΩú& Zì╢└MmNT√6;░kɼΦ▓6éªv╤F#H║ó─zÖÆ'Jù¡RDSq≈╝δ^▓,█v(SnbrzÇ┴╤碫╙V@+FTP Cö┘&    >0╕ ▐(┬zWæÇ}~║ì_╓■êδ,Å╛å╔╠æ▌dÑñf╔Nú5≈╡LPN╬EO▄ò àGü─╛H>─ùtcσùûàXrn≡5pì▀ü┬╤½Mfqj┴▌¼U~uΦRäG¿X÷å█▀Pσ┘╙╙P£░â╢ÖOjWfbóσ0"5ñv╒çΦ¼ßÿì\":≡KGô\j=│`(,╚╛[¥╢ P!▀M⌠Å┐┴m▒ôε+#
  3898. ¬,mε┼\é
  3899. P╕╤jl]uçiFσ: φæ╧─Φñh╤$ùC┘@åF╡'ê┤+ºα⌐εÇ9?║v;▒/BE|≡/s ¬┼BOt<╟°q
  3900. ╖¡■;.vπxùy╠M╔⌠h╩ìàΦ¡¥}RGC
  3901. 9£┬¡/êPsF\@ú▀¢{╖x≥ï≥" ≡ìò%ïÇp▐àΣ6u([D{╔ uL=;╡úbúu─Oô¢y╝jF»z$▓}∙─τd¢] ╢kαg╠<£÷    ¥XX╡"lΘáb√J∞δf ]└Z≡░Ça£╜φ{¼Cï}oZQK7.√¢1X▄δL <gàgVëoF±½é/╗≡┴╞?ïKφ÷z╙+Ipóâ{╙3≥uQQ|╥ Ä└┬7Yj<+╦vëbU┤ σz⌐A╔a¥≤▒▌
  3902. ¬ìëX    █ñα█60V    0pÇ┼W}╒≡pwjö▌W0
  3903. ░h"V7┴µY├█D=Ñ▒s╙;█Vt@RfÖ ═IA$ëâ┌w▀èM╤;dúb²jv▓GtzAêe/áw +Qoï@=â═åúèu5÷ó&.ê,ß╛╖Çv╗ƒ»H|αD·╒S°bO┴p^┼n┬e╔Ç7JêΦ░≈-ïÿ▐ΩN▒]Σk╟BQε
  3904. ºl┬XP─n√₧uÄ╣¼URX`äs│┘│┘∞nΓ£ç╗ö╣ñ╛⌐┐biv[si╜ }╕·ë_$╬╝üÇ▒┘Särêîτyv0äO¥\G┼≤Σ∙₧╓╠M▌τêdddΣîÉöÿí∩a£{á¥ε;H/╞╪f¥W₧╞èñäb²?é⌡-░úåQL╛ÅîK¼░ïéc¿|8Å█░U pP!╘ì<^t^ü╧æF ╥R>Mî8é3■╠α¢@ú┐╨¡èYí╫
  3905. ▄ñçYî±ε░ïgΦd-Y:ó₧╠ EpΦf8±Ü▓ A⌠∙R─¼âe¿¡P}W╨░├/▓╔}╢*>    @>┐üT`ëz√ê╨■ùÇ/░U╞8Æwë≤u½°»]δΦ9√KC╥¡Ç╖âR Z¥½ò·╞δóÄ╛J&dΣ∞ê╓êKvé:w╩~J8≡wO╛N╠H@Åcyí'╗Çó]h3╓éump=Y@1R6;n/p▄,╘u┌█ δΦ≈Ä┼? ╪ú#JÉ
  3906. 7+O    «ⁿαRPSídï:U╤*t┼G⌠δVtF_Q5ƒZ&PW#Uj√Θ,ï21╖íΩ
  3907. ╒4Σ`    ┴ntα`$î█╟G}·G┐ë±èW1φ┐rv(J╨┤f═6%≥÷╡Jσ≤    et"Eé6
  3908. ┌ v»óÖCB&└Aì⌡ÇΩ╜╩ì╪\U5╛ⁿ┬îl( φèºëL_PºPjα[á,ï_┴hìp@OÿφT│╤÷²¢Æ*u G*╞åφX⌐ uFδ⌠ê(ó ┼╒½âk╛[nπ⌐ é[
  3909. ┴VqèR|µ⌠╤LY╬Ñ╘┤╔7Ω(>╥}Hâ√G\╩╢9Γgu ■0hHZá╧ .t■B|ñ▐àää÷[^▓╡G▌£4Qƒ?≡╪ó▐ÿ╔fP¢rΦ` X
  3910. ¼∙|αφ┐┐)▓░₧t░,$fç 7ÇΓX├0J456789abcd   efghijklmnopqrstuvwxyzQ-└╧W(╓0╥åZD"⌡╤2$33╝.èéT╗ΓBO½ê    $A-╖]wIè%F└÷@âN(_¿■[C├
  3911. }≈╪╞-Bñ[h?╠7Yë░/[]$ìÆñ5êë6╠ïñVδa'Elznx┘7╪EK!ß°êΓê
  3912. á▀Φ╩VêδBC÷─VVyƒ :P;╨"dW |ë╧:┼*╢B╖╒*b╟æÑQ≈xLô&è╙∞æ╙▒┐╛Ç└╞Oδ+å▌ El@jä@uc▄-⌡u9≡$=ª.s2G1íΦ┌┤CΣö╤┼HÄE╬LÇ:h╛x'TtOóδ^Ñ    Mδè»Θ:A╟═╪╨ΦxÇ7;o┼`èJΓ▐[É!s╦[≥e@┼a@Φδ┌*°Ç ╝ á
  3913. *}p╫é⌡ªè ,UÇtè0╖t+;8≥<Æ≤A0$ZwΩ)°v▒(╕▒8φ@hs+╜▌lí?öNúV"₧┌ ╔IôK-ê°╒╝áÜ@5óΓêC°÷φNƒ-ΓΓ╟√╩Aà»o└ zçá&î─£0½╢¡┬6êÄ;Hα«éP0+Ä÷≡Qσ╓+cöÜ@<╝├∞]û║.MC
  3914. Ω╔/"HP┌hó5îéWp|(─!δGÄ0┬/ä╖:ª╩Jº._)ZΣì|1É└Th╒Pe~;½pçó≤9RQ²éX~A▌h#╞#^▌ éÄ)√±▐╔▐Θ▄»D╤ïα&ΦÇ⌐DZ*╙x3V±ÿ\ Åóª¬WαM[D≤÷EΣï
  3915. ΦïC∞╣t│¥: ÇY₧µO.÷┼"σiûº
  3916. R▒┌áù┐á₧êè╥à⌠u4Çm    ┐▄?⌐@┤6:╕╓ä}<ê[ tv}Gmmδ3x≈≡?ëUφ-╦▓]Çí3AçG╛┐≡╝δ½≡⌠ìE5a▄°╖«ìe°]├√¿m⌐°èUǵ1┤é╛9_öδ%ê95ê@>₧Ñâ╕Oδ8sv∞Ωgφrδ,7╙Ç╧üƒ¼╒a#Ç╬Ppék:º╫l3Çä:═├á5b|Åτ0Σáæ┌<WùT╡@ÖáΓ$╕*R╦N┘8╙F"¢╘ è|##M2└X@ô≥Ñó+╚êñδó╜úà1ê₧çª┐    0╘⌐▌µ╪9αs)αππ7VP╥╞X;^ε¿6Dτ ├Pê)┌∩LKÅèL1πg╫~╤üδO-≡⌡NxírUS▐¢@B GC5≡f╚╡─┌⌡ü_]°oï
  3917. `
  3918. 
  3919. P1└PZ°¿on├εCâ}╢B─Üφ╔íñ╓ǃ\â├µ√jf5δ*1~ O0√
  3920. &≥îx█ï6ú3╓½GïUÇφmH]"-òp]!Φ{ëΩû? ï■,╤╢⌐pâ9ö≡▀▌°°1ù    @@ï`▌!â>m╕Q▒Äδ╪BuU¥»╞èδA┤^╝vü┬╥,Éúτ┬ûíwP ƒ∙n▒e\ @K}¡ÿka    <R]ò√!δΘä⌐WgX¬VàYkW;≈P▀φ╨'u╩){╘¢Γ┌ü·Gr║|╣`a
  3921. Ωⁿ½⌠öƒδ║╔f╕:É{0Sß ≡@B⌠└%ÆΓú $a/(└/07╔u%ehí╜▌²èÜB:>ìó│W]~êÉBkªjs.*$¢+%~ÄÇE░≤ÿ╗£╗╣jñ├;ß¡≈F█>┤4P╧ÖèÇL1ëΩ 1L┬┐╖.╪s╞í/u╛Iδ╢â«2Q╒«Ωó╡%│½ºI░ pk∙E┤¬┴╡*#ÿP╠╫╙âπc∙ZyN°    tA58¼ε┼Q┼.ÇIáMè"Φδ┌K⌐    êe┴╞:Γüª╚▓|;₧⌐▒╙    J»╫Eaú╫3╘    V∩8,àA3∩╜O┘    v≡E┼í a└┴] └«4Czuëíl"[w\@╠╡╜^è ╜+¡█αV─M█è#êgg█8d1ì]≡╔┬¥{╖╖É╚@;t ₧Dà┬▐┬!▌"σ;peç├σEö<Zτd⌠¿╘╘αAj{ê^@τs⌠yê╨P:\Y.t)å┬$└·,╨¥{íα├.E è┬êMΓ0╡-`H╬L=I⌡Ü`╣■ª`«l▌XK|ä7*~EâxzÅ╗Dj"X<▒╢D"*┌T╫P╟Ä<5î5V╘L⌠Äï1
  3922. bñ)»Φë╬┬+#r╖Ç└0ß=┴└I_]=íB(╨5∞è¢æ░Öt xëÅä0å>hΦc╢ ╣ó╜QQNël$Tü/TΩb uQjdƒTcQ≤φHR~4▄}H╘╢ütV{vBd93)|W^4╕O│'7LëDn╢)B;cHQ    .½ê
  3923. <≡ìpRâïc«ÿT    êÑ╥Eπ╙:9≈:ò+*¢┘èBHα₧│èpA1k▓`D┴▄q₧(2°æYj|█╕╘`EëV╦#Pá╙╤1XFè┬/!▌╤î▄╜⌡
  3924. ■½ëZ║Ço,δrUCRëB@LXGw
  3925. Y|╔MüÜT╒ñG%┼Å|á╗'ïδ$;J\TßF┬z í╢a┼U?`]╙é0{á6╪K8.Ut╠<⌠∩ï┴ûò<88î²δαS»÷ΦM?Q┴ê▒Jú( 0úY¡f£°÷¡:O╥ⁿ▒-≈▐╝▒+╗d{|z■▐}⌡óßdBÖ⌐Q1$ ≤S¬¿╕╨ìh$D._∩=êG6HMB7δ⌡ß≥╡Æk>    Ωc▒µ└┬¿ZG
  3926. U±╥í öÖ╤┴┬ù▐µ╘n7p╡╗0@.@Z,Qj$φφ╩╛BNê    NüüÇ▐≈#|]ΓuσF │í█5KJ1ê8≤4º╡╖óI₧║o·[¥ÿXë}∞è@╓·[8;ε≡ì>HJ
  3927. fⁿ²
  3928. ïM∞K«±1╚èl7át▒▌o>+-uç≡Γ≡┐
  3929. Kèê;0ZΦu4╫_PφΦ_o8ï}mê═o└"6JLFV∙P╡57╫╛;ï1?+╨êé ñZD▒uFè¬└-Y┌■ºτ╡*èMê╚gGδg jÇá│[ú@m$3╘4┌åÿBGI▌╜_┐╤au╘ìP<└_4█iïoDq+Dⁿ|⌠▒╡E╚ò╘|"nDm J)≤▀╝]├Kå▒Fëà└sE(╘┌Bëgδáho╨ìCV┬╣⌡*å░&µ+ó/ú>│╗1ÑÇ╢φ Å~jn╛║≡δ}▌4"▄ï]▄    é«+⌐ε!l▐┴dt2╖┤]╦wk╟ ▄P╚~▄*vK⌡$▀ΦΣP4Uαµ6[î▄└¢ä╠╓╘╘Φ╚@
  3930. ⌠V║Q    ╠#äφ╡╢a+k¢f▐è╪ 1╤9╧├⌐6ï▄ Å#¢k⌐φ▓9V⌠≥)_ò▄▐äPìê)MU7    ╗αù≈┴n▓)b╫b█≥]RΣ;H)±Pf[ε─▒û+≡>╖²┐B)╦≥┌9╫|Σhp±╢D─P⌠p    ╞c:αÅAOê╩╞g0£8°8╠è(RS╕╣j▌è╔┌╞∩    |╨n╦ìFΦ0╔ǪèJ!/ &▀═█╢0â ╖ëtèqε╒66zÇσ1■½ √}ú╙Y2Ç╔É■0|(█εy9#t    Σ╓ ÷╜╒¥d√}F+╚C█_¿,>╖ê╬ǵ■ ½.¬≈■τα$U4╛l─¡ëNÆtìxéφ∙fⁿöE3 \uß√^zpü■«k÷
  3931. .ìr    á░╣╨o╫╪╡╥I±╡&ªP7öéå}ΦQ+uΣ┬┐uº~¼δ▐╗¡└Äáû"+╟*D┴GöFΣ;Äå%ë|]¼╖"φå0ë▄êd╪Q±æ*║┴├▀ ²éEπ⌐*■6pT3α╨╣kδK>╢åw£▄┼δ>=╠╢}j╔a+P╟2ëMó(E░úñ╞OcδÇ6B╕▄"─│P«ü⌐ö=p⌡╨!¿Çσ$%è ╟¬⌡RP╠δWVIDEO\AÇ7─⌐â╧(╞╤┬p├⌐b@Ñ0█Xkèê^e pµèí
  3932. PûD±á 1
  3933. └UΣR¡αº⌠⌡fâ;ƒë+}▌#╚Σ▌Cl╘è┐Pè
  3934. êÇ∙╥╗█ìóßòêH└uµú╘ëXô║░j""■ApY*▄╪╝YÇ0`áö∙Ü▒A╨+AτLêS╘:²αa#╙=Kb¡!ä><▓g╛ uφ)2╪0h┴▌╬Ω    ê╪╨å+Uo5æ.⌠GΦOè¢5Çπ│ƒ*yⁿò├ + ─CJù╥_9α0^\╫ö->ìqa▀▓ΦΩ< <╓░╜|àPë╓Aδ─Q╟ä┴E╟ä÷â╢┼Mpl+;>Lª)
  3935. 3└.óÉ ╪Nó╩┴╙è╚ÑΦf≥¢├╚G£ô² ═│U0d█┬8~╘àè>ε0╫:┬ªÄm¬├ß F
  3936. F▌äφvΦΩ+÷°1ì^xΦ¥[Dt└#E╣!mí₧7╗tÿDç₧;₧ ▌ß¡&k▌δ ┐ ┬¡/ @▒δ╢9▌┐ìkû∞╒∩ê≤+└kgΘ∞(╪½e    2ε!@É╔[.'gDZ├╫║¢ä$┤Φmù²`2R┬┌å╗mV_=4èå┤ ≡9ÇBüë╦sj-░▒¡d!j∩ñS≡v╕╣╨:9
  3937. û%ê┘K■╚ë-Ü m¬╦)áb'Ç7:·    ägîONC¿alD╡b,┤    ├ÑcT'VZH÷╟æQ}âà êr┴ΩêR█¡╕Mê ÷─<u╜▒0ó1;U=Å 2δ0TrU»╕ qLSìA▒αP .ñ¡+TaÇ|ª┌Σ¥╒^DO½∙G ╞ûWB{1┬nGQNìë
  3938.     Oïä≥tá(┴µ;ó╨tJhïÜ╢o╖
  3939. ┴ß▀    ┘@<_òHU{ìVσw.ßs£S*?¡ïo $@╜eΩú ╔ê╙╤{oí┴πb    ┌ëd{╔^Q╜T2ÜÉ,╡φàú╚=@@@╬Ω5úuSHÄGóXwrQ╜╪JPW╪╖]gtèFíÆntδ7HwQu▐ÅT °ë·)┬╗s«O)╫JAá╬Äü+4485ÿN<╞Äçê▒▀5ë0f«ßmç╗)ú╡█\P┐╪ï5<ëƒ=D└üz3D╜ê`)▀A    ╚╜o¿ΘwÖ=    u[▒0ë-╢╪ÖÇ/.Φ¿%┬╞-╟⌠.╗fEf▀    ╙ Y╪\┴▄î0 »ò°▌£.uÇleÇ(]Dló*PÆ.2U¼Ω;^░
  3940. ┘Σ ¬R0I▄w²U╣┼▒░δ√-á²┐∞δ
  3941. <    │(áà₧H·#UΩ░    δ╗░ DV₧T≥╛╬ ┐!pf@jτ╨¬T±MbéN@ùóúò┬RàP░╪¡VSÖ┴AÄ─╫╞(┼εß-5i]╜P>E▒kQ┴▒X ▄/:┌│▄╣╛ô²╣q≡δΣ┘≥<⌠°$╕,┼Rü}∞≈╨íV$L5Üai└ τ<╓╨²■åëJ▄ üΩ╪╗=I9ü∙7m╨:
  3942. °ìæ(F\²O┤⌐╛½?┐o╤+ ë▄H╡pφ)┌▌8üuo▒jΓe
  3943. δ▌î!Ç?{ε 7| ▄4$╖ß╜▒i≡`
  3944. ╩┼├âX═]>⌡ó,╝MT[ R¿P*P]US∩▒"DP╟ìOEâ₧]┬lF▌mCTδU╘}╓╪0t┌ù╪╚=uV─(;ZYΦÉ≥≡U╓UââH╡Q6P2dé¿╚╟┤ï▌àíαj▄$░σ½$╜PL┐
  3945. s▌₧    `9S6ënU╦Fu;╙α»¿ü╟Æ~▄└½$UeΦì7!h░─P¬╗╒°F·9╙~áÆêE$╗xXú╘%ïT┐=^zâ#DG}F?Ç}ΦP├ªn√p}∙└[v
  3946. i?Q╘╛-∞⌐GCë9v█8!E╥$Σ     °EF▐╓┴ ╪ █╜┘ëk╦)╙e]NÖ┬(hìRA█u└4 Γôí╬╕╘°:∞_∙MlT▄JS%┼▓}ëjÇ¿çεëëóu⌐#üßâí°-ó-Crç⌡)σ-└n[Yk├[n√┐╕ΘfüΘ rµR║-%∙ù╛ußv ç╤^Θ╙°╨╙·Q▌╢!K!2≈╥Y⌡ê>R╖# #EwS^    ╥├▐ç╢⌡µ    ≥oVZï¢zÅ]╞)╥U╪oQ╫─┬╪╦╔╥╥_Γ≈┘·$Iâ╥Fδ▄╩ └╞▐┐íV]J)÷    ╞    ╓┌┐╞tHi¢uü∩æ∙~╓Jµ<tεδ$    α ∞÷{ü╟╤Ω╣╤▐u∞÷â╨Ç[╕c'°·├╗¿)½ΣGv└Lⁿ]u[U_ZM±G *ä∩0└π ┬o▒2┬╪uOf⌐5Z▄Çúu╞èZÇ.á)@m∩└ F-t/=dαδ6╩0<t ┐ée¼ï¥y┌ⁿHR└Fδ1π╪9Y
  3947. ßµ≡)ûα╒₧ò▄ⁿ╓ÿQ[≡─δ$ⁿw°ü╒Y Yα+A êPq¿ⁿ°╡v'DZ(R[QΓ╕ Uº╜εΩîêCwÉ@vüh}▌∩u¥▄/≡₧e┼Å?τü┼╛Ωzh░ )$]"╘pí,(╣üσè ⌐)*┐Vt1óPE z,.é0P'FbÜ∩}±├≥:0τÜnüb84<svCQ(_─ U$ü;UA82 ⌡,╨O▐ j w4vzQ'w<╞╞á╪ε@óRδ╕ó²é·÷>≈¼Aìjû ┌Zπ@úÜU⌠┤½â
  3948.  
  3949. p9╓61Σ]¬uÉ╢ù╫δ@:Oì│j╫╡πñ²DPh⌐@d╟Zo%▐(╔Θ.;Or╜àê£▒â∩á╤║ôsH╓R╤⌠ü≥VR«MΩ±â⌐σ>?1δü≤ &▐°└┴φσφ3╒5v    ╤ß╤╙Mú±Ñ÷u∙δ*]
  3950. ╤δ╤┘▄╥_
  3951. :}Eu⌡=u╞     ÷uÑ╖÷m»┴█t`â╙?⌡@░lVë^lU¢Φe∞hE╒▌▄PX├Æ)¿┐)¥    ß╜─FD    9P┼≈≈æ√½┬|▓d÷≥êΓ┤╘
  3952. Æu█j⌠f╝ ┬âφv    Ç K╙eÖ■V∙ êU¥uKu▒X¬2C(⌐┌∞A∙^ô
  3953. dM~╧|(.â)áå: LA¿Çûÿ(αÖéë■ⁿⁿkbCΣ TΦvHoÑ╘µƒì╦@rN≤Zz~ì▌o╛√╞ñ≥å#\┴oxEcè]│╢αüºï┬{≥#╟è6 ï5br≤╨zDL$ RZ₧╥|│╔j*ërC~║╨äKuLÇ┐ ╒X┘╔αes¢?Ω■âLÿp╙}Φ^ëçÑ≈╖╡*M⌐àâó»ÇRq┴Φ òµmφ3╖ääp&%ü=╠┘ôφ\.%Mm¡ô┴B,└L6ü`≥£ *Ñ╛╓=└?║0┤ )α░^
  3954. ê≥m┘üù(!σm∞
  3955. ¿)ôâ╦Θ┘¿VfkgⁿJå:(τ3+9°8önΦ°█|}╪δóC│║╫¢54d█╙Y4╒┘8é╖(▀▓ec?╗├Σ▒ kpÇ%q├ë\
  3956. ┤≈┘ßúφívCÖbΓ╪ßéi▌∞²÷┤âΘuΣ<æ+¼k▌█-╝ú(Ç4┼ïòh±t½ê⌐l█ºφ°╗OV▌9< ▒ÇL÷┐k╡Y{╜ñHsftí╓░ÄCV∞    öüdPú├5ª╝╖O┘φ9:Jà├rù╟hΩ°π⌐≈u╔▒╚#h«╨#K²ê░█> 9tyσ4╟%╩M$$;╥4ç(( =╛═▐╪╢w'á£i    Z@&█oδ <║ûu╔!$êd
  3957. ╩ê╖├Jª⌡⌡&"║è║r@^╩▄╩▄(┌₧%îîîîî┤≡α╨îîî╚ñîîîî╪└╕─îîîî╠∞╘Φ∙îîî▄╝ΣR(X╝@`d∞Σ╨╪╠╘¼ΦTî╧τ≤t√RhRêRäR∙|>ƒ─RÿR R,R0ƒ╧τ≤RRPRαR|RÉ≤∙|>RDR\R$Ráƒæ╧τR≡RxRÇöQîî¥<Q░┤Hîîîîñl└¿îîîî ╚╕▄îîîî£Lp<!╩Äî48  ÅòYour program has ru█ o╦n tf memory.
  3958. One o_╗╜mnple#e.;t╢]╢hcpir;v█v╖#c_\c/fc∩║÷C: bad52ibnumbcƒ▓wH(%d)'arguÇl╖¡Ö█ismu+ ïquno%ncel}doenoo╣█▐ret╘nvalï╛egssK┌█-Ö~%()>eed%soK╓üp,S+ w┘vTh| 0w±mk═
  3959. .Ég4%.kntini? 
  3960. ù▌å╜pn2toCsa╖e╩ms''²é≡nkd'/6╧'!ím╞╛'by' ,&'á▓Θn[÷t,t'/dof>[xel;'if'O▄a╙
  3961. ┬f╫Ya∞╖=xi?f╥s÷\Uçöq
  3962. v'  _global>7>=m∩═ `7lSgkìFú"6.p7╖╢╖░ßcödÄ7{⥪k([<C-╠ù«u *¢--lin≈éìÿ3!#₧+ε+'ú?Ö⌡'i║.Ö
  3963. C})]╢╞lå¢JScg╕-[aÜtr╒W>├dto-a╘≈µxo'T)abl1C░φwi%'╝ƒ╬╞√┌wh≈{?Gt▒░pÉCToµmyôcs═Mëm-on╪Gr`-≤-s╤q╓╤▓W":¬
  3964. h¡╡≤┐w;å│-7╙╓╨╕rΦrz/ag¼Zäe┐+╤
  3965. ╞BBΦ╨cΦΣ}k3\9q[ize,v├c¡ÇúPub Doíεhç╗EdiΦMEup▌⌐5╫▌≤yXvåm_⌡e-$mèû▀╢╓1ês6cs. Iy┌0┤╓ä*çb|
  3966. â╣f╞?Cª╗] ╢o`\.═t╢╢╠9sPñ%p▐┴5WαB╝Mm ÷?σqSΣ∙g╣╓╪\2Ä.°3Æ}√o¡ª&4http://w.RapÅα:¼╣r.╧[
  3967. Me¡≈FhR╖,åτ{AxhAeyI∩mü╨1H°p(tJLµ ª¥Bπ╦tá╡fpTôRk┬gTe%.99s:%u
  3968. ╧ºα
  3969. 6δi┴█XK7∞wBΘ·OWWkn≥IN32v▀▄ï╠rå╘ìc3░m
  3970. l    Wdókaü╙w_Yxk├\y_ f╖wpspa╡t [äÉ▌
  3971. l_)KoÆ╛wfâ às_=▄╓x┤}tñb█d▄o└nìx£!╪¼ K    8({3║ûnÖ6;±╜▒[áek:    n:7åí yÄrJ>t┤▀⌐ÖuÉ█cuìé├3╡@╢@]$wvr╘qr╤Öo├stVε╡_.TÆÜ[s?ëevöAhth3aoC╚E%k_─=┘}< 8 0╢2?2n-┬J kA&┤Zí"åÉ|"┘'ⁿ@-┐wrVr,3»#°▀≡ Äà▐    ╖╚x~l√$äàéÅy{"$4>ƒ_dÇf$N@_ε$[┘;M <┘c─B┘#╥H╪
  3972. ¢4>±JB╚_LÿàKamccû= OXJ£Ü▀¥╧╘Zeσ-╦Æ^J╦fp¡a╦₧tM«+p║Ds7i▓ZSk7Ü6╢º╖d╜p┴y¢g≈░æLs'auü╜d'
  3973. ╞ÿ,╡u▐-¼)IsPATH`ü┴ôP2.2;h¡╫ì»╝¡âW─j░╒w√
  3974.  Y┌p█"αΦô;e¬oymMlîìS╠t!eZ0=[╖ 1PⁿmS╫@í{⌡l⌡nÆ╟█ '&e    ë&£ßüÅ
  3975. │²╙ü ┌bu$αé{£╞£
  3976. a-O»u╟∙°@?╦Y╖╟╢.w√XW.E¥¡≡)%)b┴|≤]{uàr\ñ4EUDIR╓Ü√[\PHORIA FI!ô8ë╧,σφR|okC▄üfΓPrδ¼O{░√Åc?xíç┴ë├▐· _Ü2pßαgtg»¥äs[#fApmn>{t╢rÆΩπSyÆ4H▄&ax╓-■h╪ f`oïb<▐$eé/sg╢!S&*,µ.I=C├N#R«mWk┼0u&ë«≡èP'd1R∩ßwΩs¼m╢─å∩/ºs½t-Yr¡╬┤╩▐i«»¬║û=≡▒╗aF ²iIíBπ)c-êôµZû-'■8╡╟¼>MeY<1╢⌐lHtç={+δ╙ªΘ-*/=√&=_ç┌a%iO^%⌡F╒(åÇ┼G░/GiêΦ╜╖▓?╟τ'6ÿ═≈┘N¿A≈¥H'tQpvÿ@ïv┤1╕ΘlµvT¢dyü/jδ2l½#b╬ëa"XaaBσlεP Rô╡%vdù/à-ü+a0t╫░a ¿l-Θm,ü├÷╚g:` ║Z|ÿ»╜Eq¥σ0p┌    v29╢`<æ∞|>o(╡▄ä¿F│╒0XK┴HY+Çïεr,/≈º:X├f1∩└²┼π╨â│Sè╒\k≡ö ƒÅxd'└πtσZ ;ïτf╣/<GΩ ≡p    .╩[p[ú∩kCj ½MYé┴Ω=µ╬┤ç3Mä+2`|!-¬0v█\3▓kìwn/₧ü    ?
  3977. {[Gàd ╤¬e¥≡}CwGby:
  3978.  < >$ù (F⌠ 1&╝ù  ╜╖ò+I,wτf-⌐d4b/!⌐!;d7UÆ¡ ▄╙6«W║B
  3979. Dδ½ï╤╙ù,π>τ╫b╓²5u==  =%εAδSV╗├█0sF1=ô2=Rk╖M`■df-agoY╢¡w ?qQ!│╢╞/<Ç_%lç╢ü╖N10glRñ,▐KÇ│(TVó∩E2Z╧)≡CONEºeKºw≥ò─    
  3980. =B─├⌠╡l·gj░╟½M Y≤:▓ûδ≡ ┤+≤£"|╦▐BOG≈░║┬ L╞V=îÜïD%H ¼╟╖à·_C-╪ä╠╕trªii╜%$ √3ùAls╧wul╓¼d─v▐K╢╧Z≈&@s7º^░ÿ┤äñ°ⁿ¼ÿëX∩║┘╩00<·(skizT%e7lÖ⌐)L-->P3b┬│;An╦ó&±▄¼t╖±6╘▒,,τy░ö({?;<b┴┌
  3981. ¥tΩgDhVσxô\UMüüK`«7W░â╘▓V`
  3982. (CKZ╢öÉ){£╠-[`,'o}î#0╖A┐r╙+∞ò┐ôH╓H(T    <ɼèΩ/Φl«╕l╞ε4üK^OMτ·ºB╫r~º`░#╣gáí¬fƒè╜╓Æ gÆ·áQI7,7ï÷{nkδ¼ⁿ├\ù¿°_╥Jèa╜f≥σ╕│ÑB    /t¡c)X`/%zc#xeáM.f<ó░░_JF[Γ0╧▄kå I²ß╣;¢A-,d-║Zà/êwπpΓ╡>▌ª<jB% °_ª~Åf├¡?#α┴∞f
  3983. »∩Ax┴╫fâNW0.▓enWÆz<=r■8q╪¢t╟├ ßlB╙5≡
  3984. àS+₧úd#¢▒½o┼H3│SÅF╙s1░ªfAg)█i)f!û'ÇWö╧│rÄTT8î'>┐╣"kL<073741ôÆ▒∞823o┐Å╨Å    ╤rÇsNp·⌠?(┌!=⌐JB£vZ√äh╒'dÿ█r.I└f)¼/_0≡Ç¡_(╨÷αy8≤╞YBz╠çlê╨─δ)x┘Fs0lä╬&1)' ╣└J▄'0Üà░    `"#╣&Z╝î%za║ÿ0lY▓çò╣ä5╕/#-╩ l╧π≤U6╩^╦#GäIcjï░å1┌╝ε╜¼çæ±I}∩l9b$ÉB@X╪äü[3h/ÿ╣É7ºbEñ╞vδ5├s╥Θc÷&-!╖)₧{█v«=KìÉbY
  3985. Φ├*%PesúdsOrb»═vǪwa√ur╤8█+bO½cI╤"    Ω    jB_,sGM7at+▀{,}4â3¥ù╕╟Ωóâë╠≤cäB├,üZsYRæ¿p╪╜b╗S│÷
  3986. ≥B╫┴₧(HU∙f@ÜfB└▀K<0╫    gs│7ëh■gDèMBB*=╦->lÉüSús\ff<ΦA│┼|Dn&╩RÖ ^Nmnïéòσ
  3987. ?D6kä5oƒ0JîPÅ┬FB░╨τ{,ä=:_:Ç╔V┘4äüm&Bφ    v█±hI/O¬Éäfµ╟Vé╜4É /îäU┌{'┴G(\X\cµ(!φ¥Z0{yLP¿╘╢C3Ææl'╥═α═¬<Φ<Hα¿±.PJ⌐ª{Ç(     ^ ┤╡`Çg:ìpÄ, ¼÷$@@sÖ╬év╧ád┤░sl⌐Pφ╣₧!├: FY░ñÅw╬bE9╘╣e┼!:τ▓°¢4#! FF,0T╜w=fa|R%:╚ tKhuOtQ2Z╓8⌠╕i┤é¬2┐ \càI┌≈CL─[vê-/8α ûìUK3eèÇⁿß`    
  3988. {─{\{╝`╫µà:╔ÿ╔£ ε┘W"æ╚ûç'G■(f÷ö0@K└ ╓r#H∞K0αoτ 0<P_∞╒¼Cg6▒$8.p.Y┘'╙!┴¼p:OOVS"▓cy≈ê≈)├îrOΓx@téTñ─ca.ûä╦╖≥[g┬╢Yj°òé≡─:╙eAêT[α&I»ér.zσ¢½ôf«≈ΩM¿c'o░z╘╠¿_╖ δ└Φo%;1sÖ╩▀α─ü`─≈├l∞>ƒpoº╟¼%┼e½åµoqrªç;éS┘éÇ⌐I__dè%½XG┼ ╪ÇT│öot╫?/L│∩U 7kúß√╢ ─s╧cv╖│æ╚╒Γsr
  3989. $¢┴░x│ Üß / 4Ω%ñ∩ ?*ÿ¢┐sÑ░Yï3╟_ç¼â}├▐ ╚º4╖4G▓b░suk
  3990. -`≡╕ó²^àl( {_täÆ£_ Y╗▐ÆhX└g34,üƒvr!qê    çεEÆÇαF8╘╩f √Rî$ß3OUT$R╪êC╥¡╨┴W $    ╟[JΓ≡"81╕YÅ┼╜a░#xçô╧^ld╢\+    f [isCbÉô|!br╬Åv╬?╜B+ü½ß@/K─▒!)╞,6δ╟╟╠δ3,ñ╧x└▓Xß±ïÉ#ä C+½æQ╖╖[Yîe# ╩$╝r¿#⌐%]╥╧/═∩ü╬ ≈ 7 FH─Ñ₧     ⌡{$╩5YD
  3991. ëƬ-½Fk¥w╪┬▓<*a£-º╨╩Asë6wü0B"■ùX≡ó▒Yîa3╩╘┘╫¢┴Jj╡«0X┘+┘$R`A[&{7Σ∩_.üäiïjçòöëåÅ╦å╘6├Ö├┤î&p/┬ ╠QGyíRMò]X:s-äkO╢
  3992. üæoQ░ò=s├#┘╩b▒$#;0ù1╒o+ !+M∞+He'$1┐┤▓XîKMëIƒ# ╬αDƒ?■÷▐    ₧*.*╫-*a¿╡ ╣,Jt¬Ri\╨⌠ªô^aü08lx_f┘¼Γí┘ïda╨i░7
  3993. 3c╦hæfdî╙10╫¥▀∩g8Xφ┼&oσJê╒ïédRR7Hä┬&╙4═╬╢K ╜zo7n1└▄ë─:éDL,l╘MÇ╖╩1⌠$┘░êà(á2    ┼#╡4αjÅ╣½ñJrîóúK².dM=┤┌jBïxAæ¿5┴╪F▓a÷E6:qsεF▐
  3994. CÑOKp¿)ê¢ïn=├Çû=┴a2m ┼≡┐τS╓├ïêSpMD'║÷\{MAN C▐÷J$N2√v⌐¼ORL TE▄Çà~INATILⁿTZå┬╘B∩bí▒    √ghÄBSPECN╕┬a¢FNÆ0èlÆ-δ<ΦL╕├5TN─¢æä¢H▄ X╠åº■;├uN/:î0ΓÄyE>a└è╘⌐a╔╒┐φ╘SO╥h█h┤Θ≈₧z▐210A║o{«ai%di▓½≈98y01ß╣R┤0≡3╠¿S-Rosì3Γ-╤cpNÿΩlö+D╤ 5ñA╨9O╬┴adr┴)U%7e/TTz[pÇQRP i£a╦Z½n½kn╗_E~R╨▓ ;─√√ o┬ù╡╘≤0Nm<[÷a█ ÿ╢╒⌠1On 9%╧
  3995. dΣdÆ8 XHÉææ ÿêÇl vwäΦ≡─ αφMfM7-H#÷╠T⌐∩ ╪  ¢■╞∙╞@Θ4╟εNâ╠=@[V6╬╔êçß$K╪▀²╖Bä■Σq┘ëE=É─╝╓BIyƒ²ä╫ùATê├@$@É├▐(uû{c├╤└÷╚▌;{▓╘ö╪ αçΣ√Σ╔ôáΦ⌠Ü°æOÄⁿ╥¥Æ{≥Σ╔(<,4⌡'∞╔φ=<₧wH¢TG>y÷`dlτtí9÷╔æî²ÿ£■╔ô▌;á.ñ¿    êb÷Σ░ ┤·oy≥d≈ô/─╠╘
  3996. 'O₧<▄α¥∞°ƒwå│oⁿδ╙£╙≥∞╔ô≈ô,Ö÷₧<y4°<ƒD£WÄ|÷ΣLúXñ`.l?úä▒Ot±╪'xτw≥I╒╝*╢≈M║*╖4[╫???? ├4M???s!▀S╪ô█╪╗╦fO√ßx ║ü░ o┐╓╦^÷I╔0Tε⌠B¿╚Rê≥üec∩±∞âr╪ ≡╡ ô╦!╦⌠Öⁿ¥ ,_ ╩≥Θ û∩lç/£ Ülç╣C ; (/.,ç,ç0ƒ8á,ç,çDôH,çlçL P<lçlçX¢₧d;¢lçlçl öp/lçlçtí| úsç,çäñî√/»-╤Éüí) Köÿ+ô∞;yΘá°]¿ C#N╛ôτ┤;└'╚¥<_√G" ╨8╪╧≤w≥/α %Φ:F▒ºs!/°RGíôºY╛  ¥|╟₧N│≤/= τ∞;≥k≤(ÅB0yN╛ôK8 L@Mô∩Σ;HSEP c¥=╟₧`$│≤hUâp╧┘s÷ ?_xZ Ç(≥£<'êOîP&╧╔sÉQöIN╛│sbkáâD¿τΣ;∙ºF┤ G╝y╬╛│n/╠;oº▄}ô∩Σ;Σ_~∞#∙N₧⌠ÇⁿS4⌠∩Σ;≥/H⌠ 7 yN╛ô /,2≥lτ;8_ü@éy╢≤pLδâ Xä│τΣ;`/àhå;9{N₧pç|ëê₧│∩∞è öï/£î∞;∙Nñ ì¼#ÿ ╠₧ô∩┤│Ü╝¢;τkc½£/╘ÜÖâ
  3997. b τ ï?    
  3998. ╖Cp4Mw▓╚úXd╪Σ╙4M╙8Dÿñ╕«╣4M─xäÑ , σ╥5╖°ñ DT₧<╛«3═1 WñÑl└║ng3ƒ0îwe═ á╚╠ígµdgí4ÑL5_░|O┐ÿ£╓ Ç `dWUf"x¿▄¥ƒ.═Ñ{ƒ└Σó╠ª< äªi`t¿7«kÜnñ─╘⌠;vhÜ(╘╪╗
  3999. ┘uñ[ñ░░ 2αⁿù    pª#ÿáWa▀{$8∞d U?╖*∞╚N~åƒ:É├^?ö╕Aòeφ∞tât≥≤ °F≤
  4000. Y3û╨ kH    ║┐▌╛│ ß gÇH╥yKSB|hπ÷êWücε9·■B.å@öu$└σ#.░7╬#PFÆ▓OEST╜EDT╪∩u/8WIt£F3╪▒oúpéΘFáφΓδLQªiܪV[_diܪiÜmsx|éêiܪiÄôÖ¥í╡iܪѿ½«▓S≡E'tO!@kô├+E╢-J?d)Æτ
  4001. \ù█CH ─╖┼ï╜Φ┐«▌Çjƒò■ }²5~ƒ╦
  4002. Mεñ═ª@p╧∩≈╣ ºå⌐╨╝,)ÑDá2£Φî    tqΣ┘╘┼?≡CI;?D║∞²■Cpêܪ█±#äY_djiܪiou{üçªiܪú¿╛├▀M╙4ù∩à38R4M╙4Wwïú╖╣4M╙╫▄÷√åªiܪ/G[{ÇܪiÜ܃┐╙δ 4M╙\ç$>Cc╙4M╙wÅú├╚ªi.MΓτêܪiÜGglåï½Jói┐╫╛É@E )*
  4003. HY*ÉQ úúQ╔EXW6╕PR╛C#ê«"áHΦ½ wle GE╡ç▌"╡tAFiè╔╢ô MuxPÇH╢HssmÆo▒£8DeleD_l∩m┐Dimo    Ef┴JDA? ÷f├<",9∞╨└H8ï╡╢    ╗─
  4004. F√éê╘zN»╠■vXGöCPInfo
  4005. ├┌P▒L#█V,o(MFA1W£╪`4DAl`║Id┬╢╟╪EnvKo è* Ss▌∞sⁿCtR╬ Φ∞▒t½sÖáê═y≥å è PhND;╪am╛La≈▄ä├∞ó$ lYäµ╙/É/▀l┬∙ÇA¢u/V+ñds±LckC`ê[7ZZ╦eNrmXß)φVe~ Bä╢Ça[bra8│{]╚Xk    ¢P"bPóéT╠≡▒puÇR9┬dπ{/    læs┐w╢0╔SC5l╢rù@.ä╓S ╛X ≤    ]P;f«$?SDßvepTlæ{▒m╠    FFeⁿπ╔₧Σlu SUnlΓk╖Vstu<@┼╓>WaiyìSÑ{A±ûO▄rªl░e┐AI╛,f6ñPK"/(&¢å1S⌠╓%ñ≈Buff╔╠l%åq( O?Yk0ó└C┌÷Hµ^8RmΣjHa<Vtîà╚b0ñ∞udoÜqQ╨&┴'"`,∞╕√╕▓wóFóPôè5M╪┬╩v½zTa    KpiG╝d┼> ,v]Q√l1Ü⌐w ╣    Qò$,
  4006.   ┐ⁿ      oƒmφ"?- ╞ φ1"' Ä≡\
  4007.  Üφo    O59ROK≡5<╫■█÷        _   <LQ≥ µ7 
  4008.         & kε  ╡÷÷m&
  4009. /[2
  4010. ï█ [╗öX¡&,ç @L «╪o=
  4011. ^°/ N -à/,\(J] dφ¡² )
  4012. 4#--≈ φ▄╢÷m²*" /.4!▌pß/éI¡!6$B≈mí^+ ,5^ ╪m[h▌0A%ü|╓=r░H7@6B▌┌ █'ÑOê█╓h▀W#pZ√φ╜╞, A!(RP/├╓╡mXnLa°┌m√2;>Ä~ >╖à▌72-& á ë╟6n╟╢0ñG'0.▀xk8I    F +██    Γ(:╢█¡5Y(╗ú▒▌I B
  4013.     £
  4014. [k╔ZWJ┌ìO<`?
  4015. oì▀ÄÄ╕ $╜╣╫He! ▒² Åh5bak.'█÷φ¡█ à _r£/o█ªo┐88%D
  4016. ET°÷ (P≡nkLJ3    kê/▒■■B├]┘▀l#╩Ubε∙÷m█┬$8Ö@ I%pc█ÜOp r-⌠±┘FíèID÷_ò─a !N8(p[X■!)T3Zß┐╜ª╗5è|&4-q9'>╝╤■K?g     /ï
  4017. ═ε╖┤▌n=ùδ6u>╠Kào7╢
  4018. Z ▀ò▄
  4019. åε    ┼â¿W╢╢░uM(òε }+lƒ≡&Ä-FL    û┌Ñíu╟░╓5▐ )yK┌8╢}     8Pu╖¡╘(2jX#!φma╗`╔(╓6àσKX-òZ█╥)<8
  4020. ûW╕█╕rrNV¥Q  O█o|kÑ╘G3$ ╥2    +)╢îîl%F*█x╪ì░ :)J≡┐╡~4 8ƒÉ#$E ┐]*..╡OÑ╢±Q1 añ.┬Ñ8╖F[j;- (╜#▓╡[kÿó ß╝%∞█░.┬S█@s6⌡z(αX╖5: £
  4021. 'lφA°@▌ 2"°+Z⌐░-1 %╢[&├╢m▀╒" E▄/Bv*B█▄'GPM╤Hk«l╣τu√6²φ[╗>#=Y$¬≡∙&┌╓p;v╒2#_ UY[X╕╨φ] .N;q»┤┴|e1S╩,Ñ75
  4022. ÆbE, ·{,¢s¿+äS╗╡F|╤╡.Γù:┤ûkFúp╡≡«]Yó~tà_ç2n(K╖Fú╔.Js$╪
  4023. ÷Ñ═mU-y╩1╢▌ε╖P .'(0!*ì╢┤ÿaN*XƒZk4\≥&▒B{┴º_hRvA;ö
  4024. ┤lN|÷φAI∞üXb╢cπφ:─    +═╡;    á}⌐²φ'1F'PR)L╓╣ܽÅâKK ó»ìµ┌░Hªéåτ╪Jf0±⌐/l«└3|< 7&╫(≡"7ÄF┤¡50⌠)Bφ¡÷▀.YM└4)hÄ╬^µ┌Bßi
  4025. $0╢?│Θ÷╘ò┌ ⌐X$^«msª
  4026. ╧ ≥¥hmÄFìoñà╢AúΩô6Iτ╞╛O└ .Fám5ä╛É-*ZG╗╨*[3±2╤*Ééâ┐[+hwå╖╖╤₧@;P"    ,└ç*D≡╤óº╪ ╗■[O?    ≡Z](0((
  4027. ≡Yöá&≡I▐─] ,≡ⁿ0Dy&    c    ▀; 9/╡▌j,#d°,E<├Ñoo{≡Cm≡⌠δ╗ö>²▀ò1" K0 ≡160»αó╨▐";╗_ /}┐Ö)+ Ü&Zö *%╜δ╔╪A█╨≥ª∞#èZÑo∞╔≈
  4028. w
  4029. ]╓*αn┬&$≤╨kå»ß  R╩á²ünbÑ" H.6╨`δQÿ╚"]²ì¬6,≡┌5$>╓7║╜δ┐`≡&≡| .0ù@0╦ε▐æå%|»&/12V0mm
  4030.     n_ ç╖ ÑΘ"&&+048;U.E█6
  4031. Oµ W╪)¢└ ╪Cc% úíºV ¢û    ü,àûí}╚à▒│═Ç╗╜B¡#$Ç╟╞¡╨░u<16¢[· !$<",6F':á    %Φ/    4çíd}0-╖t╨    ≈▓üπ▓s$ ■╢m¡╞v╢╕JO╜âü ~4o]ïm╗Dú]8.n5
  4032. ì┌┬¡_∩qWDl][╗±-.)XñV,°¡o░Φ┼Å:f2?╖ò:k1±ÆZε4
  4033. } /─┌⌠√)H1"8&*<rmbßQï.v0┤]m{Wy¿B8Q▒¿b«└Wh¼     Wï▌ZΘF«ëæ12╜█c▒╡₧&çmπ> H^ÆQ┌L\r+á!Æç5T¿d╔è¼+╢h_j┬≤= !\(4p5╫u0bÑ -S╖-¿@    ózót╔╒
  4034. OfAr╣p╗╢l#îÑ    áekl[í ╧!Ea╫▒╤b!p<ü Ü0≡/ó)  a,╡╪:Åt(    Sφ÷vk┘K5(RF]mP:jà╣╖`!5R¡┴e╛¢+ F&bc5C]+QGß  p8Q}WèX╜*Júä<%lr⌐w-╟&ëπ▀Lè>OO;ⁿì■àO∩Fçd35÷    ;É»÷F w┴wD«δ8¬häDè■╥6_R_π08^ H&╘≈?╠²uàràîvb⌐╘ò-▄╪αÑ╝7E▄ûçë J1öI0tp&&*9╖▌ +▄96/lm█/ -W'²1I9╖à╖┬<τÑ-`.{?p▀á± DBU#66K,!P≡2^¡à■où-JSU$ìI"╓Tß╖[bIª⌡äöû~ïº6A"Dià"╩C8°┐},; =INN$Pâ±VJ┐3à⌐Fí≥wwìc¡╡¬û2(│
  4035. ┤mC`(4)%# ╡║7C+f∙├*°  x YA44+╦<≡@î╒█Z$.2sÑo²▀n═_    '0Wa}≡φ¿ 2└ mtFΦα±$áR╗▌╛c6æ/$┘*E·S.▐Φ~X#&v3╤ó!╘7ê╔╒Di"╔R3 2å⌐o░/()╣√╖~ÑH"5H3
  4036. [▄└à3"¬Tⁿ6«E½Qdxα¡².%à%ü≤⌠▌¡ ╓┼PG;≡≥─W!_ê    ëùj îw≡⌡╟ ╣ ╓|*;#·=ê*≡├&QWe⌐─¿╓iJ╓á▌╢y(ò≡▀nVhK Ñπ#0╝╫▀hk_σ╜╨ f|A*Sß$Z╔╡ëε!b»╥EGà╗Ö, ⌐A δF¡╓±
  4037. ƒ├ ▄⌐Z┤VÑáÆTZà«╘:╓╚úBÑV _=+╣å╞┐Θ)eF√k%≡ûJsÅ"íA⌐m╙ p≡╟Å&╛mpZ≡`╬½à[
  4038. ╔┤î]¡╝╦bvßW╗ P3╜uε░}'▌ß┐ò¡δj$Å.≡°åI 2U■à¡A╗PÇ5S 1╞ N║ %ú)a4*└╖k -,7b^4.n(+#⌐    ëd│Y,E▒°ß£Θ
  4039. d·╡/ìm
  4040.     [}E-ô5≡▀
  4041. #1≡iÇÄM⌐¥╝╤ l÷*╡J╙'°ì.`+W╢ü4Ñtï ⁿ#^P45≡Åπ█ΓK╝3╢Q    ▒Xⁿ<a°÷ìZ▄BB≡;Åa%ΓÑ _╖S>+$┬e2 !ÆéTàû║`╡)kE▄░╡x⌐1ε!&'H╙╖φ═æ|┌z      Ñ ┐cI≡\Z&$!BEE≡¡≡DQXü2÷í
  4042. ";ñ[ci<2╖░Σ┐IàXx$D ≡  B"4    ²ó└¢≡! f∙S▓┬tG╣¬
  4043. 0╩/É  ≡ %P*fΩPE² ½L╧{╥╖╬²αéü ╨.~e=
  4044. Ωu ΓT╗èÿ  ^7╚G~░∞eE±ä 3╢╓l┘₧    »äóΘ-á
  4045. 5p┐ö
  4046. Σ└'╚GTEXT▓┘{▒πÉ╖¥░·f DGROU┤L√¡É░_╘'ó%M7≥.bss.╦0.╬Q┼wÇ'iΩ√╜▓cô
  4047.  Orecôk(*c∩2e'Bsr&Oá√M╔ R@°b@;váÑO╣  `╛+╤Aì╛╒>■ Wâ═ δÉÉÉÉÉÉèFêG█uïâεⁿ█rφ╕█uïâεⁿ█└█s∩u    ïâεⁿ█sΣ1╔âΦr┴αèFâ≡ ttë┼█uïâεⁿ█╔█uïâεⁿ█╔u A█uïâεⁿ█╔█s∩u    ïâεⁿ█sΣâ┴ü²≤  â╤ì/â²ⁿvèBêGIu≈Θc   Éïâ┬ëâ╟âΘw±╧ΘL   ^ë≈╣èG,Φ<w≈Ç?u≥ïè_f┴Φ┴└å─)°ÇδΦ≡ëâ╟ë╪Γ┘ì╛áï    └t8ï_ìä0lΘ≤Pâ╟ û¿ΘòèG└t▄ë∙WH≥«U û¼Θ    └tëâ├δßa├â╟ì^ⁿ1└èG    └t"<∩w├ïå─┴└å─≡ëδΓ$┴αfïâ╟δΓaΘ]à■ ╧{8 Ç`Ç╧{88Ç╧{8P¼≡¿╧{8áÇxÇ╧{8ÉX∙EXW¿á( @a'%c65^GFi4+╕-'âBASA:î}x« zjb¡Éï║ñƒ╩⌐º╝╨╬ß╫╒τσΣεmO    q%º╝╣╨╚┼▄ìïÖ▀▌Ω≡∩÷∩ε⌡±≡÷;Γ[Iƒñ₧»h²n╨á√éjï╓²çzêÅêÅwvwono≡δ{.x╞╗■╧Ö,àxct■áuGc╝$l■r :╙FÇ7B¢* ┘ïàà*))ëêê┬3&uOL 0íE&ÅîïßQ■g╕d&╙}ìS
  4048. qle óÄk.φ╚à≥═ï┼ºr▓ùgqgV▓x╨¡f¥âO╘▒k▄╕súëWπ┐zΦ─ǬæaÅüeöìÇ»à(┤ôH╕ûL╗ÖO╛¥S¡ÄL┬áVïs>┼úZÖ~F╔ª^╠¬baQ/╗£\ìzRUL8aWBÖöëeOôs$ûw(Üz+qZ Üz,¥~/íü3ñä7¿ç:ºê;½ï>xa,«ÄA▓æEük5pcD>9-QL@tV{^YDàhàgëjîmïnÅpÉq Åq A4ôt#ôt$ûw'(  âj%û{2F:PE(DA9utpⁿ╧▀┐Çv╛▒ªó'≥≈ÄÄïèèêJJIÄÄìÉò/ìÄàêú(┬■⌐▄à┴"Æ Z{4Heÿ7a■åîä0 îæï!╨dwcµ)╜$RsQ 1ú37|B /╠E Z(ñg²ô9y_ ╔µ╥dut2Åè÷÷çèè╝┴Sij?nv╦■ö■ n─`ⁿÆöÿ2≥+╧▓^aå èn,-Rxyò##PNNR╪╪▀iijUUV√√ⁿ¥¥₧└└└²²²···°°°≈≈≈⌡⌡⌡≥≥≥±±±∩∩∩∞∞∞δδδΩΩΩτττσσσΓΓΓ▐▐▐┘┘┘╙╙╙╧╧╧╦╦╦╞╞╞├├├┐┐┐╗╗╗╢╢╢▒▒▒¬¬¬ñññÜÜÜùùùöööÉÉÉîîîèèèåååééé}}}fff^^^EEE╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╨╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫21+(#!╦¢╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫<=61+(!ⁿ╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫C=61+#! ═╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫yF=61+#═╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫=2.(!ⁿ╫╫╫╫╫╫╫╫╫╫╫╫╫ñDMªGvDvhGíôA61+#√╫╫╫╫╫╫╫╫╫╫╫qoGGMéDùM¥╫╫úÿA=1+!╫╫╫╫╫╫╫╫╫╫_DoMGùâGGD╫╫╫▒áÿ=2.#╫╫╫╫╫╫╫╫Ct¥G╫╫╫╫▓ºÿF=1+!╫╫╫╫╫╫╫u_tG╫╫╫╫╫╫╫╫╫╫╫┤⌐ÿF=1+!╚╫╫╫╫╫╫GCaq╫╫╫╫╫╫╫╫╫╫╫╫│ºÿF=1+!╫╫╫╫╫ùbbs{╫╫╫╫╫╫╫╫╫╫╫╫╢░úÿA6.#ⁿ╫╫╫╫b¥¥[╫╫╫╫╫╫└│⌐áF=1+!╫╫╫╫bsUKuJuZb¥╫╫╫╫╫╫└╖░úÿ=2+#╫╫╫╫bZùJöKöJP¥╫╫╫╫╫╫║╖░úÿA61#╫╫╫╫bbbbbbJ`bb╫╫╫╫╫╫╜╖░úÿA6.#╫╫╫╫`Q`P╫╫╫╫╫├╜╡⌐áF=2+#╫╫╫╫bQPQ╫╫╫╫╫╫╫╫╫╫╟╜╖░ºÿF61+╫╫╫╫HQTb╫╫╫╫╫╫╫╫╫╟┬╣│ºÿF=2+# ╫╫╫╫╫TJQP╫╫╫╫╫╫╫╫╟┬╣░⌐ÿF=2+#╫╫╫╫╫╫THφT╙┼╜╣░⌐ÿF=6.#╫╫╫╫╫╫╫╫NIIQHIcIHP┬╣╡░úÿF61+)╫╫╫╫╫╫╫╫╫ISQISQTI∞H╖░⌐ÿôA61+╫╫╫╫╫╫╫╫╫╫╫QIIQIIQIIQºÿôA61,╫╫╫╫╫╫╫╫╫╫╫╫╫ôA61/╫╫╫╫╫╫╫╫╫╫╫╫╫╫╨╦┼┬╜╖│░ºáÿF=2/╫╫╫╫╫╫╫╫╫╫╫╫╫╫╔┼┬╜╣╡░⌐úáÿF=;<╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╡│░⌐úáÿFA5╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫áôök<╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫╫P⌐  ¿╝∙¿∙╔∙┤∙╘∙Γ∙≥∙KERNEL32.DLLUSER32.DLLLoadLibraryAGetProcAddresswsprintfA╨ ó>SEARCH.BAT
  4049. 159
  4050. @echo off
  4051. if "%0"=="search" goto nowait
  4052. %EUDIR%\bin\ex.exe %EUDIR%\bin\SEARCH.ex %1
  4053. goto done
  4054. :nowait
  4055. %EUDIR%\bin\ex.exe %EUDIR%\bin\search.ex %1
  4056. :done
  4057. SEARCH.EX
  4058. 10890
  4059. -- This program searches for a string in files of the current directory 
  4060. -- and subdirectories.
  4061. -- usage:  
  4062. --      search [string] 
  4063. --
  4064. -- If you don't supply a string on the command line you will be prompted 
  4065. -- for it. The string may contain * and ? wildcard characters and so may 
  4066. -- the list of file specifications. Lines containing the string are 
  4067. -- displayed on the screen, and also recorded in C:\SEARCH.OUT 
  4068. -- (DOS/Windows), or in $HOME/search.out (Linux).
  4069. -- Some statistics are printed at the end.
  4070. -- Example:
  4071. --
  4072. --   C:\> search
  4073. --   string: p?oc*re
  4074. --   match case? (n)
  4075. --   file-spec (*.*): *.e *.ex
  4076. --   scan subdirectories? (y)
  4077. --
  4078. -- Note: if you just hit Enter instead of supplying a string to search for,
  4079. -- the program will simply print any file names that match your file-spec.
  4080. -- This is a good way to search for a file, when you can't remember which
  4081. -- directory you put it in.
  4082.  
  4083. -------- some user-modifiable parameters: 
  4084.  
  4085. -- when you search "*.*" the following files 
  4086. -- will be skipped (to save time):
  4087. sequence skip_list 
  4088. skip_list = {
  4089.     "*.EXE", "*.ZIP", "*.BMP", "*.GIF", "*.OBJ",
  4090.     "*.DLL", "*.OBJ", "*.SWP", "*.PAR", "*.JPG", 
  4091.     "*.WAV"
  4092. }
  4093.  
  4094. -------- end of user-modifiable parameters 
  4095.  
  4096. without type_check
  4097.  
  4098. include misc.e
  4099. include file.e
  4100. include wildcard.e
  4101. include sort.e
  4102. include graphics.e
  4103.  
  4104. constant KEYB = 0, SCREEN = 1, ERR = 2
  4105.  
  4106. constant TRUE = 1, FALSE = 0
  4107. constant EOF = -1, ESC = 27
  4108.  
  4109. type boolean(integer x)
  4110.     return x = 0 or x = 1
  4111. end type
  4112.  
  4113. integer SLASH
  4114. sequence log_name, log_path, home
  4115. log_name = "search.out"
  4116. if platform() = LINUX then
  4117.     SLASH='/'
  4118.     home = getenv("HOME")
  4119.     if sequence(home) then
  4120.     log_path = home & '/' & log_name -- put in home dir if possible
  4121.     else
  4122.     log_path = log_name  
  4123.     end if
  4124. else
  4125.     SLASH='\\'
  4126.     log_path = "C:\\" & log_name  -- put at top of C drive
  4127. end if
  4128. sequence pos, cmd, string, orig_string, file_spec
  4129.  
  4130. boolean match_case, scan_subdirs, wild_string, abort_now
  4131. abort_now = FALSE
  4132.  
  4133. integer scanned, skipped, no_open, file_hits, line_hits
  4134. scanned = 0
  4135. skipped = 0
  4136. no_open = 0
  4137. file_hits = 0
  4138. line_hits = 0
  4139.  
  4140. atom start_time
  4141. integer log_file
  4142.  
  4143. function alphabetic(object s)
  4144. -- does s contain alphabetic characters?
  4145.     return find(TRUE, (s >= 'A' and s <= 'Z') or
  4146.               (s >= 'a' and s <= 'z')) 
  4147. end function
  4148.  
  4149. constant TO_LOWER = 'a' - 'A' 
  4150.  
  4151. function fast_lower(sequence s)
  4152. -- Faster than the standard lower().
  4153. -- Speed of lower() is very important for "any-case" search.
  4154.     integer c
  4155.     
  4156.     for i = 1 to length(s) do
  4157.     c = s[i]
  4158.     if c <= 'Z' then
  4159.         if c >= 'A' then
  4160.         s[i] = c + TO_LOWER
  4161.         end if
  4162.     end if
  4163.     end for
  4164.     return s
  4165. end function
  4166.  
  4167. constant LINE_WIDTH = 79
  4168.  
  4169. function clean(sequence line)
  4170. -- replace any funny control characters 
  4171. -- and put in \n's to help break up long lines
  4172.     sequence new_line
  4173.     integer c, col
  4174.     
  4175.     new_line = ""
  4176.     col = 1
  4177.     for i = 1 to length(line) do
  4178.     if col > LINE_WIDTH then
  4179.         new_line = append(new_line, '\n')
  4180.         col = 1
  4181.     end if
  4182.     c = line[i]
  4183.     col = col + 1
  4184.     if c < 14 or c = 26 then
  4185.         if c = '\t' or c = '\r' then
  4186.         c = ' '
  4187.         elsif c = '\n' then
  4188.         col = 1
  4189.         else    
  4190.         c = '.'
  4191.         end if
  4192.     end if
  4193.     new_line = append(new_line, c)
  4194.     end for
  4195.     if length(line) > 1.5 * LINE_WIDTH then
  4196.     new_line &= '\n'
  4197.     end if
  4198.     return new_line
  4199. end function
  4200.  
  4201. procedure both_puts(object text)
  4202.     puts(SCREEN, text)
  4203.     puts(log_file, text)
  4204. end procedure
  4205.  
  4206. procedure both_printf(sequence format, object values)
  4207.     printf(SCREEN, format, values)
  4208.     printf(log_file, format, values)
  4209. end procedure
  4210.  
  4211. function plural(integer n)
  4212. -- Yes, this is a bit obsessive...
  4213.     if n = 1 then
  4214.     return ""
  4215.     else
  4216.     return "s"
  4217.     end if
  4218. end function
  4219.  
  4220. procedure list_file_spec()
  4221.     for i = 1 to length(file_spec) do
  4222.     both_puts(file_spec[i])
  4223.     if i != length(file_spec) then
  4224.         both_puts(" ")
  4225.     end if
  4226.     end for
  4227. end procedure
  4228.  
  4229. procedure final_stats(boolean aborted)
  4230. -- show final statistics    
  4231.     sequence cm
  4232.     
  4233.     puts(SCREEN, repeat(' ', 80))
  4234.     if aborted then
  4235.     both_puts("=== SEARCH WAS ABORTED ===\n")
  4236.     end if
  4237.     if length(string) = 0 then
  4238.     both_printf("%d file name" & plural(file_hits) & " matched (", 
  4239.              file_hits)
  4240.     list_file_spec()
  4241.     both_puts(")\n")
  4242.     both_printf("%d names did not match\n", skipped)
  4243.     else
  4244.     both_printf("\n%5d file" & plural(scanned) & " scanned (", scanned)
  4245.     list_file_spec()
  4246.     both_printf(")\n%5d file" & plural(skipped) & " skipped\n", skipped)
  4247.     cm = ""
  4248.     if alphabetic(orig_string) then
  4249.         if match_case then
  4250.         cm = "(case must match)"
  4251.         else
  4252.         cm = "(any case)"
  4253.         end if
  4254.     end if
  4255.     if line_hits then
  4256.         both_printf("%5d line" & plural(line_hits) & 
  4257.             " in %d file", {line_hits, file_hits}) 
  4258.     else
  4259.         both_printf("%5d file", file_hits)
  4260.     end if
  4261.     both_printf(plural(file_hits) & 
  4262.             " contained \"%s\" " & cm & "\n", 
  4263.             {orig_string})
  4264.     both_puts('\n')
  4265.     if no_open then
  4266.         both_printf("couldn't open %d file" & plural(no_open) & '\n', 
  4267.              no_open)
  4268.     end if
  4269.     end if
  4270.     printf(SCREEN, "search time: %.1f seconds\n", time()-start_time)
  4271.     if file_hits then
  4272.     puts(SCREEN, "\nSee " & log_path & '\n')
  4273.     end if
  4274.     close(log_file)
  4275. end procedure
  4276.  
  4277. constant MAX_LINE = 500 
  4278.  
  4279. -- space for largest line
  4280. sequence buff
  4281. buff = repeat(0, MAX_LINE)
  4282.  
  4283. function safe_gets(integer fn)
  4284. -- Return the next line of text.
  4285. -- Lines are split at MAX_LINE to prevent
  4286. -- "out of memory" problems on humongous lines
  4287. -- and to reduce the amount of extraneous output.
  4288.     integer c
  4289.     
  4290.     for b = 1 to MAX_LINE-1 do
  4291.     c = getc(fn)
  4292.     if c <= '\n' then
  4293.         if c = '\n' then
  4294.         buff[b] = c
  4295.         return buff[1..b]
  4296.         elsif c = EOF then
  4297.         if b = 1 then
  4298.             return EOF
  4299.         else
  4300.             exit
  4301.         end if
  4302.         end if
  4303.     end if
  4304.     buff[b] = c
  4305.     end for
  4306.     buff[MAX_LINE] = '\n'
  4307.     return buff[1..MAX_LINE]
  4308. end function
  4309.  
  4310. constant SAFE_FILE_SIZE = 100000
  4311.  
  4312. function scan(sequence file_name, integer file_size, sequence string)
  4313. -- print all lines in current file containing the string
  4314.     object line
  4315.     sequence match_line
  4316.     integer fileNum, found
  4317.     boolean found_in_file
  4318.     
  4319.     wrap(FALSE)
  4320.     puts(SCREEN, file_name & ':' & repeat(' ', 80) & '\r')
  4321.     wrap(TRUE)
  4322.     fileNum = open(file_name, "rb")   
  4323.     if fileNum = -1 then
  4324.     no_open += 1
  4325.     both_puts(file_name & ": Couldn't open. Probably locked.\t\t\t\n")
  4326.     return 0
  4327.     end if
  4328.     found_in_file = FALSE
  4329.     while TRUE do
  4330.     if file_size > SAFE_FILE_SIZE then
  4331.         if get_key() >= ESC then
  4332.         abort_now = TRUE
  4333.         exit
  4334.         end if
  4335.         line = safe_gets(fileNum)
  4336.     else
  4337.         line = gets(fileNum)    
  4338.     end if
  4339.     if atom(line) then
  4340.         exit -- end of file
  4341.     else
  4342.         if match_case then
  4343.         match_line = line
  4344.         else
  4345.         match_line = fast_lower(line)
  4346.         end if
  4347.         if wild_string then
  4348.         found = wildcard_match(string, match_line) 
  4349.         else        
  4350.         found = match(string, match_line) 
  4351.         end if
  4352.         if found then
  4353.         both_puts(clean(file_name & ": " & line))
  4354.         line_hits += 1
  4355.         found_in_file = TRUE
  4356.         end if
  4357.     end if
  4358.     end while
  4359.     
  4360.     scanned += 1
  4361.     close(fileNum)
  4362.     return found_in_file
  4363. end function
  4364.  
  4365. function look_at(sequence path_name, sequence entry)
  4366. -- see if a file name qualifies for searching
  4367.     boolean matched_one
  4368.     sequence file_name
  4369.     
  4370.     if find('d', entry[D_ATTRIBUTES]) then
  4371.     return 0 -- a directory
  4372.     end if
  4373.     file_name = entry[D_NAME]
  4374.     if equal(file_name, log_name) then
  4375.     return 0 -- avoid circularity
  4376.     end if
  4377.     if equal(file_spec[1], "*.*") then
  4378.     -- check skip list
  4379.     for i = 1 to length(skip_list) do
  4380.         if wildcard_file(skip_list[i], file_name) then
  4381.         skipped += 1
  4382.         return get_key() >= ESC
  4383.         end if
  4384.     end for
  4385.     else
  4386.     -- go through list of file specs
  4387.     matched_one = FALSE
  4388.     for i = 1 to length(file_spec) do
  4389.         if wildcard_file(file_spec[i], file_name) then
  4390.         matched_one = TRUE
  4391.         exit
  4392.         end if
  4393.     end for
  4394.     if not matched_one then
  4395.         skipped += 1
  4396.         return get_key() >= ESC
  4397.     end if
  4398.     end if
  4399.     path_name &= SLASH
  4400.     if equal(path_name[1..2], '.' & SLASH) then
  4401.     path_name = path_name[3..length(path_name)]
  4402.     end if
  4403.     path_name &= file_name
  4404.     if length(string) = 0 then
  4405.     -- just looking for file names
  4406.     both_printf("%4d-%02d-%02d %2d:%02d", entry[D_YEAR..D_MINUTE])
  4407.     both_printf(" %7d  %s\n", {entry[D_SIZE], path_name})
  4408.     file_hits += 1
  4409.     else
  4410.     file_hits += scan(path_name, entry[D_SIZE], string)
  4411.     end if
  4412.     return abort_now or get_key() >= ESC
  4413. end function
  4414.  
  4415. function blank_delim(sequence s)
  4416. -- break up a blank-delimited string
  4417.     sequence list, segment
  4418.     integer i
  4419.     list = {}
  4420.     i = 1
  4421.     while i < length(s) do
  4422.     while find(s[i], " \t") do
  4423.         i += 1
  4424.     end while
  4425.     if s[i] = '\n' then
  4426.         exit
  4427.     end if
  4428.     segment = ""
  4429.     while not find(s[i], " \t\n") do
  4430.         segment &= s[i]
  4431.         i += 1
  4432.     end while
  4433.     list = append(list, segment)
  4434.     end while
  4435.     return list
  4436. end function
  4437.  
  4438. procedure get_file_spec()
  4439. -- read in a list of file specifications from user
  4440. -- result is stored in file_spec sequence of strings
  4441.     sequence spec
  4442.     
  4443.     puts(SCREEN, "file-spec (*.*): ")
  4444.     spec = gets(KEYB)
  4445.     puts(SCREEN, '\n')
  4446.     file_spec = blank_delim(spec)
  4447.     if length(file_spec) = 0 then
  4448.     file_spec = {"*.*"}
  4449.     end if
  4450. end procedure
  4451.  
  4452. if platform() != LINUX then
  4453.     log_name = upper(log_name)
  4454. end if
  4455.  
  4456. cmd = command_line()   -- ex search.ex [string]
  4457.  
  4458. if length(cmd) >= 3 then
  4459.     orig_string = cmd[3]
  4460. else
  4461.     puts(SCREEN, "string (* and ? may be used): ")
  4462.     orig_string = gets(KEYB)
  4463.     orig_string = orig_string[1..length(orig_string)-1] -- remove \n
  4464.     puts(SCREEN, '\n')
  4465. end if
  4466.  
  4467. if alphabetic(orig_string) then
  4468.     puts(SCREEN, "match case? (n)")
  4469.     pos = get_position()
  4470.     position(pos[1], pos[2] - 2)
  4471.     match_case = find('y', gets(KEYB))
  4472.     puts(SCREEN, '\n')
  4473. else
  4474.     match_case = TRUE   
  4475. end if
  4476.  
  4477. string = orig_string
  4478. if not match_case then
  4479.     string = fast_lower(string)
  4480. end if
  4481.  
  4482. wild_string = find('?', string) or find('*', string) 
  4483. if wild_string then
  4484.     string = '*' & string & '*' -- to match whole line
  4485. end if
  4486.  
  4487. get_file_spec()
  4488.  
  4489. object d
  4490. d = dir(current_dir())
  4491. if atom(d) then
  4492.     puts(SCREEN, "network drive not available\n")
  4493.     abort(1)
  4494. end if
  4495. -- avoid asking about subdirectories 
  4496. -- when there aren't any...
  4497. scan_subdirs = FALSE
  4498. for i = 1 to length(d) do
  4499.     if find('d', d[i][D_ATTRIBUTES]) then
  4500.     if not find(d[i][D_NAME], {".", ".."}) then
  4501.         puts(SCREEN, "scan subdirectories? (y)")
  4502.         pos = get_position()
  4503.         position(pos[1], pos[2] - 2)
  4504.         scan_subdirs = not match("n", gets(KEYB))
  4505.         exit
  4506.     end if          
  4507.     end if
  4508. end for
  4509.  
  4510. puts(SCREEN, "\npress q to quit\n\n")
  4511.  
  4512. log_file = open(log_path, "w")
  4513. if log_file = -1 then
  4514.     puts(ERR, "Couldn't open " & log_path & '\n')
  4515.     abort(1)
  4516. end if
  4517.  
  4518. sequence top_dir
  4519. start_time = time()
  4520. if sequence(dir(".")) then
  4521.     puts(log_file, "Searching " & current_dir() & "\n\n")
  4522.     top_dir = "."
  4523. else
  4524.     top_dir = current_dir()
  4525. end if
  4526.  
  4527. if walk_dir(top_dir, routine_id("look_at"), scan_subdirs) then
  4528. end if
  4529.  
  4530. final_stats(FALSE)
  4531.  
  4532. -- without warning
  4533.  
  4534.  
  4535. SYNCOLOR.E
  4536. 4297
  4537. --              Syntax Color
  4538. -- Break Euphoria statements into words with multiple colors. 
  4539. -- The editor and pretty printer (eprint.ex) both use this file.
  4540.  
  4541. -- The user must define the following symbols to be colors for the
  4542. -- various syntax classes:
  4543. --       NORMAL_COLOR
  4544. --      COMMENT_COLOR
  4545. --      KEYWORD_COLOR
  4546. --      BUILTIN_COLOR
  4547. --       STRING_COLOR
  4548. --      BRACKET_COLOR  (a sequence of colors)
  4549.  
  4550. include keywords.e
  4551.  
  4552. -- character classes
  4553. constant DIGIT = 1,
  4554.      OTHER = 2,
  4555.      LETTER  = 3,
  4556.      BRACKET = 4,
  4557.      QUOTE   = 5,
  4558.      DASH = 6,
  4559.      WHITE_SPACE = 7,
  4560.      NEW_LINE = 8
  4561.  
  4562. sequence char_class
  4563.  
  4564. global procedure init_class()
  4565. -- set up character classes for easier line scanning
  4566. -- (assume no 0 char)
  4567.     char_class = repeat(OTHER, 255)
  4568.  
  4569.     char_class['a'..'z'] = LETTER
  4570.     char_class['A'..'Z'] = LETTER
  4571.     char_class['_'] = LETTER
  4572.     char_class['0'..'9'] = DIGIT
  4573.     char_class['['] = BRACKET
  4574.     char_class[']'] = BRACKET
  4575.     char_class['('] = BRACKET
  4576.     char_class[')'] = BRACKET
  4577.     char_class['{'] = BRACKET
  4578.     char_class['}'] = BRACKET
  4579.     char_class['\''] = QUOTE
  4580.     char_class['"'] = QUOTE
  4581.     char_class[' '] = WHITE_SPACE
  4582.     char_class['\t'] = WHITE_SPACE
  4583.     char_class['\r'] = WHITE_SPACE
  4584.     char_class['\n'] = NEW_LINE
  4585.     char_class['-'] = DASH
  4586. end procedure
  4587.  
  4588. constant DONT_CARE = -1  -- any color is ok - blanks, tabs
  4589.  
  4590. sequence line  -- the line being processed
  4591. integer seg_start, seg_end -- start and end of current segment of line
  4592. integer current_color
  4593. sequence color_segments -- the value returned
  4594.  
  4595. procedure seg_flush(integer new_color)
  4596. -- if the color must change, 
  4597. -- add the current color segment to the sequence
  4598. -- and start a new segment
  4599.     if new_color != current_color then
  4600.     if current_color != DONT_CARE then
  4601.         color_segments = append(color_segments, 
  4602.                     {current_color, line[seg_start..seg_end]})
  4603.         seg_start = seg_end + 1
  4604.     end if
  4605.     current_color = new_color
  4606.     end if
  4607. end procedure
  4608.  
  4609. global function SyntaxColor(sequence pline)
  4610. -- Break up a '\n'-terminated line into colored text segments identifying the
  4611. -- various parts of the Euphoria language.
  4612. -- Consecutive characters of the same color are all placed in the
  4613. -- same 'segment' - seg_start..seg_end.
  4614. -- A sequence is returned that looks like:
  4615. --     {{color1, "text1"}, {color2, "text2"}, ... }
  4616.     integer class, last, i, c, bracket_level
  4617.     sequence word
  4618.  
  4619.     line = pline
  4620.     current_color = DONT_CARE
  4621.     bracket_level = 0
  4622.     seg_start = 1
  4623.     seg_end = 0
  4624.     color_segments = {}
  4625.     
  4626.     while 1 do
  4627.     c = line[seg_end+1]
  4628.     class = char_class[c]
  4629.  
  4630.     if class = WHITE_SPACE then
  4631.         seg_end += 1  -- continue with current color
  4632.  
  4633.     elsif class = LETTER then
  4634.         last = length(line)-1
  4635.         for j = seg_end + 2 to last do
  4636.         c = line[j]
  4637.         class = char_class[c]
  4638.         if class != LETTER then
  4639.             if class != DIGIT then
  4640.             last = j - 1
  4641.             exit
  4642.             end if
  4643.         end if
  4644.         end for
  4645.         word = line[seg_end+1..last]
  4646.         if find(word, keywords) then
  4647.         seg_flush(KEYWORD_COLOR)
  4648.         elsif find(word, builtins) then
  4649.         seg_flush(BUILTIN_COLOR)
  4650.         else
  4651.         seg_flush(NORMAL_COLOR)
  4652.         end if
  4653.         seg_end = last
  4654.  
  4655.     elsif class <= OTHER then -- DIGIT too
  4656.         seg_flush(NORMAL_COLOR)
  4657.         seg_end += 1
  4658.  
  4659.     elsif class = BRACKET then
  4660.         if find(c, "([{") then
  4661.         bracket_level += 1
  4662.         end if
  4663.         if bracket_level >= 1 and
  4664.            bracket_level <= length(BRACKET_COLOR) then
  4665.         seg_flush(BRACKET_COLOR[bracket_level])
  4666.         else
  4667.         seg_flush(NORMAL_COLOR)
  4668.         end if
  4669.         if find(c, ")]}") then
  4670.         bracket_level -= 1
  4671.         end if
  4672.         seg_end += 1
  4673.  
  4674.     elsif class = NEW_LINE then
  4675.         exit  -- end of line
  4676.     
  4677.     elsif class = DASH then
  4678.         if line[seg_end+2] = '-' then
  4679.         seg_flush(COMMENT_COLOR)
  4680.         seg_end = length(line)-1
  4681.         exit
  4682.         end if
  4683.         seg_flush(NORMAL_COLOR)
  4684.         seg_end += 1
  4685.  
  4686.     else  -- QUOTE
  4687.         i = seg_end + 2
  4688.         while i < length(line) do
  4689.         if line[i] = c then
  4690.             i += 1
  4691.             exit
  4692.         elsif line[i] = '\\' then
  4693.             if i < length(line)-1 then
  4694.             i += 1 -- ignore escaped char
  4695.             end if
  4696.         end if
  4697.         i += 1
  4698.         end while
  4699.         seg_flush(STRING_COLOR)
  4700.         seg_end = i - 1
  4701.     end if
  4702.     end while
  4703.     -- add the final piece:
  4704.     if current_color = DONT_CARE then
  4705.     current_color = NORMAL_COLOR
  4706.     end if
  4707.     return append(color_segments, {current_color, line[seg_start..seg_end]})
  4708. end function
  4709.  
  4710. WHERE.BAT
  4711. 34
  4712. @echo off
  4713. ex.exe where.ex %1 
  4714.  
  4715. WHERE.EX
  4716. 1688
  4717. -- search the PATH for all occurrences of a file
  4718. -- usage:  where filename
  4719. -- (give complete file name including .exe .bat etc.)
  4720.  
  4721. include file.e
  4722.  
  4723. constant TRUE = 1
  4724. constant SCREEN = 1, ERROR = 2
  4725.  
  4726. integer separator, SLASH
  4727. if platform() = LINUX then
  4728.     SLASH='/'
  4729.     separator = ':'
  4730. else
  4731.     SLASH='\\'
  4732.     separator = ';'
  4733. end if
  4734.  
  4735. sequence path
  4736. integer p
  4737.  
  4738. function next_dir()
  4739. -- get the next directory name from the path sequence   
  4740.     sequence dir
  4741.     
  4742.     if p > length(path) then
  4743.     return -1
  4744.     end if
  4745.     dir = ""
  4746.     while p <= length(path) do
  4747.     if path[p] = separator then
  4748.         p += 1
  4749.         exit
  4750.     end if
  4751.     dir &= path[p]
  4752.     p += 1
  4753.     end while
  4754.     if length(dir) = 0 then
  4755.     return -1
  4756.     end if
  4757.     return dir
  4758. end function
  4759.  
  4760.  
  4761. procedure search_path()
  4762. -- main routine
  4763.     sequence file, cmd, full_path
  4764.     object dir_name, dir_info
  4765.     
  4766.     cmd = command_line()
  4767.     if length(cmd) < 3 then
  4768.     puts(ERROR, "usage: ex where file\n")
  4769.     abort(1)
  4770.     end if
  4771.     
  4772.     path = getenv("PATH")
  4773.     if atom(path) then
  4774.     puts(ERROR, "NO PATH?\n")
  4775.     abort(1)
  4776.     end if
  4777.  
  4778.     if platform() != LINUX then
  4779.     path = ".;" & path -- check current directory first
  4780.     end if
  4781.     
  4782.     file = cmd[3]
  4783.     p = 1
  4784.     while TRUE do
  4785.     dir_name = next_dir()
  4786.     if atom(dir_name) then
  4787.         exit
  4788.     end if
  4789.     
  4790.     full_path = dir_name & SLASH & file
  4791.     dir_info = dir(full_path) 
  4792.     if sequence(dir_info) then
  4793.         -- file or directory exists
  4794.         if length(dir_info) = 1 then
  4795.         -- must be a file
  4796.         printf(SCREEN, "%4d-%02d-%02d %2d:%02d",
  4797.               dir_info[1][D_YEAR..D_MINUTE])
  4798.         printf(SCREEN, "  %d  %s\n", 
  4799.            {dir_info[1][D_SIZE], dir_name & SLASH & dir_info[1][D_NAME]})
  4800.         end if
  4801.     end if
  4802.     end while
  4803. end procedure
  4804.  
  4805. search_path()
  4806.  
  4807. ALLSORTS.EX
  4808. 8738
  4809.         ----------------------------------------
  4810.         -- Sorting Algorithms in Euphoria     --
  4811.         ----------------------------------------
  4812. -- Notes:
  4813.  
  4814. -- The slower sorts will be omitted after a while. 
  4815.  
  4816. -- Bucket sort looks really good, but remember that the other sorts are 
  4817. -- generic, and can handle integers, floating-point numbers, strings, etc.
  4818. -- Bucket sort can only sort integers, and the integers need to be 
  4819. -- in a reasonably small, well-defined range, as is the case in this
  4820. -- benchmark. It also uses more memory than some of the other sorts.
  4821.  
  4822. without type_check
  4823.  
  4824. include machine.e
  4825. include misc.e
  4826.  
  4827. tick_rate(100) -- get better clock resolution on DOS32
  4828.  
  4829. constant MAX = 20000
  4830. constant TRUE = 1, FALSE = 0
  4831. constant CHECK_RESULTS = FALSE
  4832.  
  4833. integer hybrid_limit
  4834.  
  4835. type natural(integer x)
  4836.     return x >= 0
  4837. end type
  4838.  
  4839. type file_number(integer x)
  4840.     return x >= -1
  4841. end type
  4842.  
  4843. function simple_sort(sequence x)
  4844. -- put x into ascending order
  4845. -- using a very simple sort
  4846. object temp
  4847.  
  4848.     for i = 1 to length(x) - 1 do
  4849.     for j = i + 1 to length(x) do
  4850.         if compare(x[j],x[i]) < 0 then
  4851.         temp = x[j]
  4852.         x[j] = x[i]
  4853.         x[i] = temp
  4854.         end if
  4855.     end for
  4856.     end for
  4857.     return x
  4858. end function
  4859.  
  4860. function bubble_sort(sequence x)
  4861. -- put x into ascending order
  4862. -- using bubble sort
  4863. object temp
  4864. natural flip, limit
  4865.  
  4866.     flip = length(x)
  4867.     while flip > 0 do
  4868.     limit = flip
  4869.     flip = 0
  4870.     for i = 1 to limit - 1 do
  4871.         if compare(x[i+1], x[i]) < 0 then
  4872.         temp = x[i+1]
  4873.         x[i+1] = x[i]
  4874.         x[i] = temp
  4875.         flip = i
  4876.         end if
  4877.     end for
  4878.     end while
  4879.     return x
  4880. end function
  4881.  
  4882. function insertion_sort(sequence x)
  4883. -- put x into ascending order
  4884. -- using insertion sort
  4885. object temp
  4886. natural final
  4887.  
  4888.     for i = 2 to length(x) do
  4889.     temp = x[i]
  4890.     final = 1
  4891.     for j = i-1 to 1 by -1 do
  4892.         if compare(temp, x[j]) < 0 then
  4893.         x[j+1] = x[j]
  4894.         else
  4895.         final = j + 1
  4896.         exit
  4897.         end if
  4898.     end for
  4899.     x[final] = temp
  4900.     end for
  4901.     return x
  4902. end function
  4903.  
  4904. function shell_sort(sequence x)
  4905. -- Shell sort based on insertion sort
  4906.  
  4907.     integer gap, j, first, last
  4908.     object tempi, tempj
  4909.  
  4910.     last = length(x)
  4911.     gap = floor(last / 3) + 1
  4912.     while TRUE do
  4913.     first = gap + 1
  4914.     for i = first to last do
  4915.         tempi = x[i]
  4916.         j = i - gap
  4917.         while TRUE do
  4918.         tempj = x[j]
  4919.         if compare(tempi, tempj) >= 0 then
  4920.             j += gap
  4921.             exit
  4922.         end if
  4923.         x[j+gap] = tempj
  4924.         if j <= gap then
  4925.             exit
  4926.         end if
  4927.         j -= gap
  4928.         end while
  4929.         x[j] = tempi
  4930.     end for
  4931.     if gap = 1 then
  4932.         return x
  4933.     else
  4934.         gap = floor(gap / 3) + 1
  4935.     end if
  4936.     end while
  4937. end function
  4938.  
  4939.  
  4940. global function quick_sort(sequence x)
  4941. -- put x into ascending order
  4942. -- using recursive quick sort
  4943.     natural n, last, mid
  4944.     object temp, midval
  4945.  
  4946.     n = length(x)
  4947.     if n < 2 then
  4948.     return x -- already sorted (trivial case)
  4949.     end if
  4950.  
  4951.     mid = floor((n + 1) / 2)
  4952.     midval = x[mid]
  4953.     x[mid] = x[1]
  4954.  
  4955.     last = 1
  4956.     for i = 2 to n do
  4957.     if compare(x[i], midval) < 0 then
  4958.         last += 1
  4959.         temp = x[last]  x[last] = x[i]  x[i] = temp
  4960.     end if
  4961.     end for
  4962.  
  4963.     return quick_sort(x[2..last]) & {midval} & quick_sort(x[last+1..n])
  4964. end function
  4965.  
  4966.  
  4967. global function hybrid_sort(sequence x)
  4968. -- put x into ascending order
  4969. -- using recursive quick sort
  4970. -- but call insertion sort for short sequences
  4971.     natural n, last, mid
  4972.     object midval, temp
  4973.  
  4974.     n = length(x)
  4975.     if n < hybrid_limit then
  4976.     return insertion_sort(x)
  4977.     end if
  4978.  
  4979.     mid = floor((n + 1) / 2)
  4980.     midval = x[mid]
  4981.     x[mid] = x[1]
  4982.  
  4983.     last = 1
  4984.     for i = 2 to n do
  4985.     if compare(x[i], midval) < 0 then
  4986.         last += 1
  4987.         temp = x[last]  x[last] = x[i]  x[i] = temp
  4988.     end if
  4989.     end for
  4990.  
  4991.     return hybrid_sort(x[2..last]) & {midval} & hybrid_sort(x[last+1..n])
  4992. end function
  4993.  
  4994. sequence x
  4995.  
  4996. procedure g_insertion_sort()
  4997. -- put global variable x into ascending order
  4998. -- using insertion sort of general objects
  4999. object temp
  5000. natural final
  5001.  
  5002.     for i = 2 to length(x) do
  5003.     temp = x[i]
  5004.     final = 1
  5005.     for j = i-1 to 1 by -1 do
  5006.         if compare(temp, x[j]) < 0 then
  5007.         x[j+1] = x[j]
  5008.         else
  5009.         final = j + 1
  5010.         exit
  5011.         end if
  5012.     end for
  5013.     x[final] = temp
  5014.     end for
  5015. end procedure
  5016.  
  5017. procedure best_sort(natural m, natural n)
  5018. -- put x[m..n] into (roughly) ascending order
  5019. -- using recursive quick sort 
  5020.     natural last, mid
  5021.     object midval, temp
  5022.  
  5023.     if n - m < hybrid_limit then 
  5024.     return
  5025.     end if
  5026.     mid = floor((m + n) / 2)
  5027.     midval = x[mid]
  5028.     x[mid] = x[m]
  5029.  
  5030.     last = m
  5031.     for i = m+1 to n do
  5032.     if compare(x[i], midval) < 0 then
  5033.         last += 1
  5034.         temp = x[last]  x[last] = x[i]  x[i] = temp
  5035.     end if
  5036.     end for
  5037.     x[m] = x[last]
  5038.     x[last] = midval
  5039.     best_sort(m, last-1)
  5040.     best_sort(last+1, n)
  5041. end procedure
  5042.  
  5043. global function great_sort(sequence a)
  5044. -- Avoids dynamic storage allocation - just passes indexes into
  5045. -- a global sequence.
  5046. -- Not much better than hybrid_sort which makes full use of dynamic
  5047. -- storage allocation.
  5048. -- Note that we only partition down to a certain degree, then do an
  5049. -- insertion sort which runs fast because things are roughly in order.
  5050. -- See Knuth for the details.
  5051.     x = a
  5052.     best_sort(1, length(x))
  5053.     g_insertion_sort()
  5054.     return x
  5055. end function
  5056.  
  5057. global function merge_sort(sequence x)
  5058. -- put x into ascending order
  5059. -- using recursive merge sort
  5060.     natural n, mid
  5061.     sequence merged, a, b
  5062.  
  5063.     n = length(x)
  5064.     if n < 2 then
  5065.     return x
  5066.     end if
  5067.  
  5068.     mid = floor(n/2)
  5069.     a = merge_sort(x[1..mid])       -- sort the first half
  5070.     b = merge_sort(x[mid+1..n])     -- sort the second half
  5071.     
  5072.     -- merge the two sorted halves into one
  5073.     merged = {}
  5074.     while length(a) > 0 and length(b) > 0 do
  5075.     if compare(a[1], b[1]) < 0 then
  5076.         merged = append(merged, a[1])
  5077.         a = a[2..length(a)]
  5078.     else
  5079.         merged = append(merged, b[1])
  5080.         b = b[2..length(b)]
  5081.     end if
  5082.     end while
  5083.     return merged & a & b -- merged data plus leftovers
  5084. end function
  5085.  
  5086. integer min_value, max_value -- for bucket sort
  5087.  
  5088. function bucket_sort(sequence s)
  5089. -- Sort s into ascending order. No elements are compared.
  5090. -- The values of s must be integers from min_value to max_value.
  5091.     sequence count, sorted
  5092.     integer value, k, offset, c
  5093.     
  5094.     count = repeat(0, max_value-min_value+1)
  5095.     offset = min_value - 1
  5096.     -- count the number of occurrences of each integer value:
  5097.     for i = 1 to length(s) do
  5098.     value = s[i] - offset
  5099.     count[value] += 1
  5100.     end for
  5101.     sorted = repeat(0, length(s))
  5102.     k = 1
  5103.     -- make the resulting sorted sequence
  5104.     for i = 1 to length(count) do
  5105.     c = count[i]
  5106.     if c then
  5107.         sorted[k..k+c-1] = i + offset
  5108.         k += c
  5109.     end if  
  5110.     end for
  5111.     return sorted 
  5112. end function
  5113.  
  5114. procedure check_results(sequence sdata, sequence data)
  5115. -- compare results with another sort to make sure they are correct
  5116.     if CHECK_RESULTS then
  5117.     if not equal(sdata, shell_sort(data)) then
  5118.         puts(2, "\nabort!\n")
  5119.         print(2, 1/0)
  5120.     end if
  5121.     end if
  5122. end procedure
  5123.  
  5124. integer nsquared_ok
  5125. nsquared_ok = TRUE -- do N-squared sorts
  5126.  
  5127. integer iterations
  5128. sequence data
  5129. file_number printer
  5130.  
  5131. procedure measure(sequence name)
  5132. -- time one sort    
  5133.     integer id
  5134.     atom t0, t
  5135.     sequence sdata
  5136.     
  5137.     id = routine_id(name)
  5138.     t0 = time()
  5139.     for i = 1 to iterations do
  5140.     sdata = call_func(id, {data[i]})
  5141.     check_results(sdata, data[i])
  5142.     end for
  5143.     t = time() - t0
  5144.     if t > 6 then
  5145.     nsquared_ok = FALSE -- time to give up on the slow ones!
  5146.     end if
  5147.     printf(printer, "%15s %9.4f\n", {name, t/iterations})
  5148. end procedure
  5149.  
  5150. procedure all_sorts()
  5151. -- test all sorting routines over a range of numbers of items
  5152.  
  5153.     natural nitems
  5154.     
  5155.     printer = 1  -- open("PRN", "w")
  5156.     hybrid_limit = 20
  5157.     
  5158.     nitems = 5
  5159.     iterations = floor(MAX/nitems)
  5160.     
  5161.     while TRUE do
  5162.     -- get several sets of data of length nitems
  5163.     printf(printer, "\ntime (sec.) to sort %d items (averaged over %d trials)\n",
  5164.             {nitems, iterations})
  5165.  
  5166.     data = rand(repeat(repeat(nitems, nitems), iterations))
  5167.     min_value = 1
  5168.     max_value = nitems
  5169.     
  5170.     if nsquared_ok then
  5171.         -- do the really slow ones
  5172.         measure("bubble_sort")
  5173.         measure("simple_sort")
  5174.         measure("insertion_sort")
  5175.     end if
  5176.  
  5177.     measure("merge_sort")
  5178.     measure("quick_sort")
  5179.     measure("hybrid_sort")  
  5180.     measure("great_sort")
  5181.     measure("shell_sort")
  5182.     measure("bucket_sort")      
  5183.  
  5184.     nitems *= 2
  5185.     iterations = floor(MAX/nitems)
  5186.     if iterations < 1 then
  5187.         exit
  5188.     end if
  5189.     
  5190.     puts(1, "\nPress Enter to continue. Press q to quit: ")
  5191.     if find('q', gets(0)) then
  5192.         abort(0)
  5193.     end if
  5194.     end while
  5195. end procedure
  5196.  
  5197. all_sorts()
  5198.  
  5199. ANIMAL.EX
  5200. 3030
  5201.             ----------------------
  5202.             -- GUESS THE ANIMAL --
  5203.             ----------------------
  5204. -- How it Works:
  5205. -- animal.ex builds up a tree structure that tells it what
  5206. -- question to ask, and which branch to follow in the tree
  5207. -- depending on whether the answer is Yes or No.
  5208.  
  5209. constant 
  5210.     node_type = 1,
  5211.        DESCRIPTION = 1,
  5212.        ANIMAL = 2,
  5213.     question = 2,
  5214.     when_true = 3,
  5215.     when_false = 4
  5216.  
  5217. constant
  5218.     TRUE = 1,
  5219.     FALSE = 0
  5220.  
  5221. constant KEYBOARD = 0, SCREEN = 1
  5222.  
  5223. object database, p, prev_p, prev_answer
  5224.  
  5225. function Yes()  -- returns TRUE if the answer is yes
  5226.     object answer
  5227.  
  5228.     answer = '?'
  5229.     while answer = '?' do
  5230.     answer = gets(KEYBOARD)
  5231.     if length(answer) > 0 then
  5232.         if answer[1] = 'y' or answer[1] = 'Y' then
  5233.         answer = TRUE
  5234.         elsif answer[1] = 'n' or answer[1] = 'N' then
  5235.         answer = FALSE
  5236.         else 
  5237.         answer = '?'
  5238.         end if
  5239.     else
  5240.         answer = '?'   
  5241.     end if
  5242.     if answer = '?' then
  5243.         puts(SCREEN, "\nPlease answer y or n: ")
  5244.     end if
  5245.     end while
  5246.     return answer
  5247. end function
  5248.  
  5249. procedure guess()  -- narrows it down to one animal
  5250.     while TRUE do
  5251.     if database[p][node_type] = ANIMAL then
  5252.         return
  5253.     end if
  5254.     printf(SCREEN, "\n%s? ", {database[p][question]})
  5255.     prev_p = p
  5256.     if Yes() then
  5257.         p = database[p][when_true]
  5258.         prev_answer = when_true
  5259.     else 
  5260.         p = database[p][when_false]
  5261.         prev_answer = when_false 
  5262.     end if
  5263.     end while
  5264. end procedure
  5265.  
  5266. global procedure animal()
  5267. -- updates database of animal information
  5268.  
  5269.     object new, new_question, correct, answer
  5270.  
  5271.     -- initial database:
  5272.     --           record type     text         Y  N
  5273.     database = {{DESCRIPTION, "\tCan it fly", 2, 3},
  5274.         {ANIMAL,      "an eagle"},
  5275.         {ANIMAL,      "a dog"   }}
  5276.     while TRUE do
  5277.     p = 1    
  5278.     printf(SCREEN, "%s\n", 
  5279.       {"\nThink of an animal. Hit <cr> when you are ready, q to quit"})
  5280.     answer = gets(KEYBOARD)
  5281.     if length(answer) > 0 then
  5282.         if answer[1] = 'q' then
  5283.         return
  5284.         end if
  5285.     end if
  5286.     guess()
  5287.     printf(SCREEN, "\n\tIs it %s? ", {database[p][question]})
  5288.     if not Yes() then
  5289.         puts(SCREEN, "\nI give up. What was it? ")
  5290.         correct = gets(KEYBOARD)
  5291.         correct = correct[1..length(correct)-1]
  5292.         database = append(database, {ANIMAL, correct})
  5293.         new = length(database)
  5294.         printf(SCREEN, "\n%s%s%s%s\n", 
  5295.         {"Please give me a question that would distinguish ",
  5296.         database[p][question], " from ", correct})
  5297.         new_question = '\t' & gets(KEYBOARD)
  5298.         new_question = new_question[1..length(new_question)-1]
  5299.         if new_question[length(new_question)] = '?' then
  5300.         new_question = new_question[1..length(new_question)-1]
  5301.         end if
  5302.         printf(SCREEN, "\nFor %s the answer would be: ", {correct})
  5303.         if Yes() then
  5304.         database = append(database, {DESCRIPTION, new_question, new, p})
  5305.         else
  5306.         database = append(database, {DESCRIPTION, new_question, p, new})
  5307.         end if
  5308.         database[prev_p][prev_answer] = length(database)
  5309.     end if
  5310.     end while
  5311. end procedure
  5312.  
  5313. animal()
  5314.  
  5315. BENCH.DOC
  5316. 5619
  5317.         Benchmark Results
  5318.         =================
  5319.  
  5320.  In this directory there are a series of benchmark programs written in
  5321.  Euphoria and Microsoft QBasic.  
  5322.  
  5323.  QBasic should be available if you have MS-DOS 5.0 or later, although it 
  5324.  might not be installed under Windows 95/98 or NT. To run a QBasic program 
  5325.  type: 
  5326.     qbasic /run filename.bas 
  5327.  
  5328.  To run a Euphoria program type:
  5329.     ex filename
  5330.    or
  5331.         exw filename.ex  
  5332.  
  5333.  Each benchmark will run for about 15 seconds before reporting a result.
  5334.  
  5335.  We've also included "filesort.ex" - a tiny Euphoria program that we clocked
  5336.  at 9.6x the speed of the MS-DOS "sort" command on a 2000-line input file. 
  5337.  Furthermore, filesort.ex uses extended memory to sort files that are too big
  5338.  for MS-DOS sort. Type: 
  5339.  
  5340.         ex filesort < input_file > sorted_file
  5341.                vs.
  5342.     sort < input_file > sorted_file
  5343.  
  5344.  Using conventional technology, Euphoria could have been developed to run at 
  5345.  the speed of BASIC. In fact you'd expect it to run *slower* than BASIC, 
  5346.  since data types are not predetermined and fixed; it checks for uninitialized
  5347.  variables; it has dynamic storage allocation, etc. In fact, Euphoria programs
  5348.  run 10 to 20, or even more times faster than equivalent programs in Microsoft
  5349.  QBasic. And QBasic is not particularly slow. Look at some other results: 
  5350.  
  5351.  Language                         Benchmark      Result
  5352.  --------                         ---------      ------
  5353.  Java (JDK 1.0.2 interpreter)     sieve          Euphoria is   8x faster
  5354.  Perl (DOS version)               fibonnacci     Euphoria is  65x faster
  5355.  Perl (Linux version)             sieve          Euphoria is  34x faster
  5356.  Python (WIN32 v1.5)              sieve          Euphoria is  43x faster
  5357.  Python (Linux version)           sieve          Euphoria is  34x faster
  5358.  PC-LISP v3.0                     Queens         Euphoria is  28x faster
  5359.  Small C Interpreter              sieve          Euphoria is 545x faster
  5360.  
  5361.  We have yet to find an interpreter that even comes close to Euphoria in speed.
  5362.  
  5363.  Compare Euphoria against any interpreted or compiled language that you are 
  5364.  interested in. Euphoria is * F A S T * -- but don't take our word for it. 
  5365.  Make your own measurements on your own machine. 
  5366.  
  5367.  About The Benchmarks
  5368.  --------------------
  5369.  sieve is based on the classic Byte magazine benchmark. It generates a list of 
  5370.        prime numbers using the sieve technique. See the execution-count
  5371.        and time profiles for sieve in sieve1.pro and sieve2.pro
  5372.  
  5373.  shell is a sort of 50 integers using the Shell sort technique.
  5374.  
  5375.  database is a series of transactions against a small in-memory data structure
  5376.        that must sometimes grow or shrink as information is added, deleted or
  5377.        updated.
  5378.  
  5379.  sequence shows the *extra* (TURBO!) speed that kicks in when you take 
  5380.        advantage of Euphoria's unique ability to process entire sequences of 
  5381.        data in a single statement. 
  5382.  
  5383.  When benchmarking Euphoria programs you should include the statement
  5384.  "without type_check" at the top of the main file. This gives permission
  5385.  to Euphoria to simplify or remove some runtime type checking.  An 
  5386.  unexplained machine exception will still be impossible, and as always, 
  5387.  subscript checking, uninitialized variable checking, integer overflow 
  5388.  checking, stack overflow checking, and all other checks are still performed.
  5389.  Remove any "with trace" or "with profile" statements for benchmark runs.
  5390.  
  5391.  We gave QBasic the benefit of the doubt by declaring 16-bit integers, 
  5392.  "DEFINT A-Z". Declaring 32-bit integers, "DEFLNG A-Z", slows things down 
  5393.  significantly. Also, in some cases we used QBasic character-string operations
  5394.  to compare with the much more general Euphoria sequence operations.
  5395.  
  5396.  The Euphoria interpreter achieves its high speed while maintaining the 
  5397.  ultimate in language flexibility and runtime safety. 
  5398.  
  5399.  Comparison with Microsoft QBasic
  5400.  -------------------------------- 
  5401.  The measurements below were made on a Pentium II 350 MHz using 
  5402.  Euphoria 2.2 DOS32 platform, running under Windows 98 in a full-screen
  5403.  DOS window. 
  5404.  
  5405.                          QBasic         Euphoria     speed ratio    
  5406.  scalar benchmarks:
  5407.    sieves per second ...........     498.44           6286.7         12.6
  5408.    sorts per second ............     783.81           9654.3         12.3
  5409.    transactions per second .....   23594            408000           17.3
  5410.  
  5411.  sequence benchmarks:
  5412.    initializations per second ..   11085            590299           53.3 
  5413.    sequence-adds per second ....    6026            191893           31.8
  5414.    appends per second ..........   82474           7406976           89.8 
  5415.    slices per second ...........   69167           2195182           31.7
  5416.    look-ups per second .........    5430            331694           61.1
  5417.  
  5418. -------------------------------------------------------------------------------
  5419.  
  5420.             Conclusions
  5421.             -----------
  5422.  Interpreted programming languages are enjoyable and productive to use
  5423.  due to their simplicity, ease-of-use, flexibility, runtime safety, 
  5424.  debuggability etc. The only drawback is speed. Compiled languages like C/C++
  5425.  have dominated, despite the fact that they are harder to learn, harder to use,
  5426.  difficult to debug, cause mysterious crashes, and require you to compile and
  5427.  link after every small change. Programmers have put up with this inconvenient,
  5428.  often frustrating, low-productivity environment for essentially one reason: 
  5429.  speed.
  5430.  
  5431.  With the introduction of Euphoria, programmers can now have the best of 
  5432.  both worlds! 
  5433.   
  5434. DATABASE.BAS
  5435. 3527
  5436. DECLARE SUB purge ()
  5437. '$DYNAMIC
  5438.  
  5439. DEFINT A-Z
  5440.  
  5441. CONST BATCH = 200
  5442. CONST BENCHTIME = 15
  5443.  
  5444. TYPE rd
  5445.   pname AS STRING * 20
  5446.   amount AS DOUBLE
  5447.   code AS INTEGER
  5448. END TYPE
  5449.  
  5450. TYPE dbrec
  5451.   pname AS STRING * 20
  5452.   amount AS DOUBLE
  5453. END TYPE
  5454.  
  5455. DECLARE SUB dump ()
  5456. DECLARE SUB xupdate (datastream() AS rd)
  5457.  
  5458. DIM SHARED database(0) as dbrec
  5459. 'backup array needed because REDIM wipes out your data
  5460. DIM SHARED database2(0) as dbrec
  5461.  
  5462. CONST INPUTSIZE = 30
  5463.  
  5464. REM update commands
  5465. CONST NEW = 1      ' add a new account
  5466. CONST UPDATE = 2   ' add/subtract from their account
  5467. CONST DELETE = 3   ' delete someone's account
  5468.  
  5469. DIM SHARED rawdata(INPUTSIZE) AS rd
  5470. DATA "George Bush", 1000, 1
  5471. DATA "Bill Clinton", 2000, 1
  5472. DATA "Brian Mulroney", 500, 1
  5473. DATA "Ross Perot", 10000, 1
  5474. DATA "Ross Perot", 0, 3
  5475. DATA "George Bush", -30.55, 2
  5476. DATA "Madonna", 2500, 1
  5477. DATA "Boris Yeltsin", 100, 1
  5478. DATA "Michael Jackson", 50, 1
  5479. DATA "Peter Mansbridge", 1200, 1
  5480. DATA "Bill Clinton", +500, 2
  5481. DATA "Rod Stewart", 3000, 1
  5482. DATA "Boris Yeltsin", 0, 3
  5483. DATA "Sharon Stone", 1500, 1
  5484. DATA "Clint Eastwood", 1900, 1
  5485. DATA "Madonna", 0, 3
  5486. DATA "Sally Jessy Raphael", 750, 1
  5487. DATA "Brian Mulroney", -400, 3
  5488. DATA "Richard Gere", 299, 1
  5489. DATA "Rod Stewart", 0, 3
  5490. DATA "Demi Moore", 350, 1
  5491. DATA "Bruce Willis", 480, 1
  5492. DATA "Sharon Stone", +900.50, 2
  5493. DATA "Arsenio Hall", 300, 1
  5494. DATA "David Letterman", 450, 1
  5495. DATA "Whoopi Goldberg", 1050, 1
  5496. DATA "Clint Eastwood", +2500, 2
  5497. DATA "Michael Jackson", -50, 2
  5498. DATA "Clint Eastwood", 0, 3
  5499. DATA "Jack Nicholson", 3000, 1
  5500.  
  5501. DIM SHARED size
  5502. size = 0  'current database size
  5503.  
  5504. FOR i = 0 TO INPUTSIZE - 1
  5505.     READ rawdata(i).pname
  5506.     READ rawdata(i).amount
  5507.     READ rawdata(i).code
  5508. NEXT i
  5509.  
  5510. PRINT "database benchmark ..."
  5511. cycles& = 0
  5512. t# = TIMER
  5513. WHILE TIMER < t# + BENCHTIME
  5514.     FOR b = 1 TO BATCH
  5515.     purge
  5516.     CALL xupdate(rawdata())
  5517.     NEXT b
  5518.     cycles& = cycles& + BATCH * INPUTSIZE
  5519. WEND
  5520. t# = TIMER - t#
  5521. PRINT USING "##### transactions per second"; cycles& / t#
  5522. dump
  5523.  
  5524. SYSTEM
  5525.  
  5526. SUB dump
  5527. REM used to verify that program works correctly
  5528. REM not part of timing loop
  5529.     FOR i = 0 TO size - 1
  5530.     PRINT database(i).pname, database(i).amount
  5531.     NEXT i
  5532. END SUB
  5533.  
  5534. SUB purge
  5535. REM empty the database - free all storage
  5536.     size = 0
  5537.     REDIM database(0)
  5538.     REDIM database2(0)
  5539. END SUB
  5540.  
  5541. SUB xupdate (datastream() AS rd)
  5542.     FOR i = 0 TO INPUTSIZE - 1
  5543.     transactioncode = datastream(i).code
  5544.     
  5545.     IF transactioncode = NEW THEN
  5546.         FOR j = 0 TO size - 1 
  5547.         database2(j) = database(j)
  5548.         NEXT j
  5549.         size = size + 1
  5550.         REDIM database(size)
  5551.         FOR j = 0 TO size - 2
  5552.         database(j) = database2(j)
  5553.         NEXT j
  5554.         database(size - 1).pname = datastream(i).pname
  5555.         database(size - 1).amount = datastream(i).amount
  5556.         REDIM database2(size)
  5557.  
  5558.     ELSE
  5559.         REM look up name
  5560.         pname$ = datastream(i).pname
  5561.         FOR accountno = 0 TO size - 1
  5562.         IF pname$ = database(accountno).pname THEN
  5563.             EXIT FOR
  5564.         END IF
  5565.         NEXT accountno
  5566.  
  5567.         IF transactioncode = UPDATE THEN
  5568.         database(accountno).amount = database(accountno).amount + datastream(i).amount
  5569.  
  5570.         ELSE  'DELETE
  5571.         FOR j = 0 TO size - 1 
  5572.             database2(j) = database(j)
  5573.         NEXT j
  5574.         size = size - 1
  5575.         REDIM database(size)
  5576.         j = 0
  5577.         FOR k = 0 TO accountno - 1
  5578.             database(j) = database2(k)
  5579.             j = j + 1
  5580.         NEXT k
  5581.         FOR k = accountno + 1 TO size
  5582.             database(j) = database2(k)
  5583.             j = j + 1
  5584.         NEXT k
  5585.         REDIM database2(size)
  5586.         END IF
  5587.     END IF
  5588.     NEXT i
  5589. END SUB
  5590.  
  5591. DATABASE.EX
  5592. 2861
  5593.             -------------------------------
  5594.             -- database update benchmark --
  5595.             -------------------------------
  5596. without type_check -- makes no difference
  5597.  
  5598. -- output device
  5599. constant LOG = 1
  5600.  
  5601. constant BATCH = 200
  5602. constant BENCH_TIME = 15
  5603.  
  5604. -- data fields
  5605. constant NAME = 1,
  5606.      AMOUNT = 2,
  5607.      CODE = 3
  5608.  
  5609. -- update codes
  5610. constant NEW = 1,    -- add a new account
  5611.      UPDATE = 2, -- update an account
  5612.      DELETE = 3  -- delete an account
  5613.  
  5614. sequence raw_data 
  5615. raw_data = {
  5616. {"George Bush", 1000, NEW},
  5617. {"Bill Clinton", 2000, NEW},
  5618. {"Jean Chretien", 500, NEW},
  5619. {"Ross Perot", 10000, NEW},
  5620. {"Ross Perot", 0, DELETE},
  5621. {"George Bush", -30.55, UPDATE},
  5622. {"Madonna", 2500, NEW},
  5623. {"Boris Yeltsin", 100, NEW},
  5624. {"Michael Jackson", 50, NEW},
  5625. {"Peter Mansbridge", 1200, NEW},
  5626. {"Bill Clinton", +500, UPDATE},
  5627. {"Rod Stewart", 3000, NEW},
  5628. {"Boris Yeltsin", 0, DELETE},
  5629. {"Sharon Stone", 1500, NEW},
  5630. {"Clint Eastwood", 1900, NEW},
  5631. {"Madonna", 0, DELETE },
  5632. {"Sally Jessy Raphael", 750, NEW},
  5633. {"Jean Chretien", -400, DELETE},
  5634. {"Richard Gere", 299, NEW},
  5635. {"Rod Stewart", 0, DELETE},
  5636. {"Demi Moore", 350, NEW},
  5637. {"Bruce Willis", 480, NEW},
  5638. {"Sharon Stone", +900.50, UPDATE},
  5639. {"Arsenio Hall", 300, NEW},
  5640. {"David Letterman", 450, NEW},
  5641. {"Whoopi Goldberg", 1050, NEW},
  5642. {"Clint Eastwood", +2500, UPDATE},
  5643. {"Michael Jackson", -50, UPDATE},
  5644. {"Clint Eastwood", 0, DELETE},
  5645. {"Jack Nicholson", 3000, NEW}
  5646. }
  5647.  
  5648. sequence database 
  5649. database = {}
  5650.  
  5651. procedure dump()
  5652. -- used to verify that the program has worked correctly
  5653. -- not part of timing loop
  5654.     for i = 1 to length(database) do
  5655.     printf(LOG, "%20s: %8.2f\n", database[i])
  5656.     end for
  5657. end procedure
  5658.  
  5659. procedure purge()
  5660. -- empty the database - free all storage
  5661.     database = {}
  5662. end procedure
  5663.  
  5664. procedure update(sequence data_stream)
  5665. -- process a series of transactions
  5666.     integer account_no, action
  5667.     sequence record, pname
  5668.  
  5669.     for i = 1 to length(data_stream) do
  5670.     record = data_stream[i]
  5671.     action = record[CODE]
  5672.     
  5673.     if action = NEW then
  5674.         database = append(database, record[NAME..AMOUNT])
  5675.  
  5676.     else 
  5677.         -- look up name
  5678.         pname = record[NAME]
  5679.         for j = 1 to length(database) do
  5680.         if equal(pname, database[j][NAME]) then
  5681.             account_no = j
  5682.             exit
  5683.         end if
  5684.         end for
  5685.  
  5686.         if action = UPDATE then
  5687.         database[account_no][AMOUNT] += record[AMOUNT]
  5688.  
  5689.         elsif action = DELETE then
  5690.         database = database[1..account_no-1] & 
  5691.                database[account_no+1..length(database)]
  5692.         end if
  5693.     end if
  5694.     end for        
  5695. end procedure
  5696.  
  5697. atom t, cycles
  5698.  
  5699. puts(1, "database update benchmark ...\n\n")
  5700. cycles = 0
  5701. t = time()
  5702. while time() < t + BENCH_TIME do
  5703.     for i = 1 to BATCH do
  5704.     purge()
  5705.     update(raw_data)
  5706.     end for
  5707.     cycles += BATCH * length(raw_data)
  5708. end while
  5709. t = time() - t
  5710. printf(1, "%d transactions per second\n\n", cycles / t)
  5711. dump()
  5712.  
  5713. FILESORT.EX
  5714. 3401
  5715.     ----------------------------------------------------------
  5716.     -- file sort - a tutorial example of a Euphoria program --
  5717.     ----------------------------------------------------------
  5718.  
  5719. -- Alphabetically sorts the lines in a text file.
  5720. -- usage: ex filesort < source > dest
  5721.  
  5722. include sort.e  -- This pulls in the standard Euphoria generic sort routine. It 
  5723.         -- will sort any type of data. e.g. sort({5, 1, 8, 9, 4}) or
  5724.         -- sort({1.5, 9, 0, -999.9e5}) or sort({"ABC", "FRED", "XX"})
  5725.         -- etc. see include\sort.e
  5726.  
  5727. constant TRUE = 1
  5728.  
  5729. procedure file_sort()  -- this is the main procedure
  5730.     sequence buffer,   -- these variables can be assigned sequence values
  5731.          sorted_buffer  
  5732.     object line        -- this variable can be assigned *any* value, atom or
  5733.                -- sequence
  5734.  
  5735.     buffer = {}        -- initialize buffer to the empty sequence (0 lines)
  5736.  
  5737.     while TRUE do         -- "infinite loop"
  5738.     line = gets(0) -- read a line (sequence of chars) from standard input 
  5739.     if atom(line) then -- gets(0) returns atom -1 on end of file
  5740.         exit       -- quit the while loop
  5741.     end if
  5742.     buffer = append(buffer, line) -- add the line to the buffer of lines
  5743.                       -- buffer is a sequence of sequences
  5744.                       -- where each (sub)sequence represents
  5745.     end while                         -- one line of text
  5746.  
  5747.     sorted_buffer = sort(buffer) -- call the sort routine, it will compare
  5748.                  -- the lines against each other 
  5749.                  -- alphabetically and return a new, sorted
  5750.                  -- sequence of lines as a result
  5751.  
  5752.     for i = 1 to length(sorted_buffer) do
  5753.     puts(1, sorted_buffer[i]) -- write out the lines of text to 
  5754.     end for                       -- the standard output
  5755. end procedure
  5756.  
  5757. file_sort() -- execution starts here
  5758.  
  5759.    -- What are the good points about this program?
  5760.  
  5761. -- 1. The sizes of data structures are not declared.
  5762. --    In most languages, such as C, you would have to declare a somewhat
  5763. --    arbitrary maximum size for line and for buffer, or you would have to set
  5764. --    up a complicated system of allocating storage using malloc and free.
  5765.  
  5766. -- 2. gets() does not require you to specify the maximum length of line 
  5767. --    that can be read in. It will automatically create a sequence of 
  5768. --    characters of the appropriate length to hold each incoming line.
  5769.  
  5770. -- 3. The sort routine is very simple. It takes a sequence as an argument,
  5771. --    and returns a sequence as a result. In C, you might set up a 
  5772. --    complicated call to a quicksort routine, requiring you to pass in
  5773. --    a pointer to a compare function. You'd have to consult a manual to
  5774. --    figure out how to do this.
  5775.  
  5776. -- 4. You did not overspecify the loop counter, i, by declaring it
  5777. --    as a 16 or 32-bit integer. Its job is to count from 1 to the length
  5778. --    of the buffer - who cares how many bits should be allocated for it?
  5779.  
  5780. -- 5. Extended memory will automatically be used to let buffer grow
  5781. --    to a very large size. No 640K limit.
  5782.  
  5783. -- 6. The program executes with full runtime safety checking for bad
  5784. --    subscripts, uninitialized variables etc.
  5785.  
  5786. -- 7. You can edit the program and immediately rerun it, without fussing
  5787. --    with compiler options, linker options, makefiles etc.
  5788.  
  5789. -- 8. This program is FAST! It will easily outperform the MS-DOS sort command
  5790. --    (machine language) and can handle much larger files. [see bench.doc]
  5791.  
  5792.  
  5793. SEQUENCE.BAS
  5794. 3043
  5795. REM QBasic Array (Sequence) Benchmarks
  5796.  
  5797. DEFINT A-Z  ' makes it faster, but integers are only 16-bits
  5798.  
  5799. CONST BENCHTIME = 15
  5800. CONST SIZE = 100
  5801. CONST INITBATCH = 2000
  5802. CONST ADDBATCH = 1000
  5803. CONST LOOKUPBATCH = 2000
  5804. CONST SLICEBATCH = 5
  5805. CONST CONCATBATCH = 5
  5806. CONST CONCATSIZE = 5000
  5807.  
  5808. DIM x(SIZE)
  5809. DIM y(SIZE)
  5810. DIM z(SIZE)
  5811. DIM states$(50)
  5812.  
  5813. PRINT
  5814. PRINT "                QBasic Array Benchmarks"
  5815. PRINT
  5816. PRINT "* Initializing a length -"; SIZE; "array ---> ";
  5817. cycles& = 0
  5818. t# = TIMER
  5819. WHILE TIMER < t# + BENCHTIME
  5820.     FOR j = 1 TO INITBATCH
  5821.     FOR k = 1 TO SIZE 
  5822.         z(k) = 999
  5823.     NEXT k
  5824.     NEXT j
  5825.     cycles& = cycles& + INITBATCH
  5826. WEND
  5827. t# = TIMER - t#
  5828. n = cycles& / t# 
  5829. PRINT n; " initializations per second"
  5830.  
  5831. PRINT
  5832. PRINT "* Adding two length -"; SIZE; "arrays ---> ";
  5833.  
  5834. FOR i = 1 TO SIZE
  5835.     x(i) = RND(1000)
  5836.     y(i) = RND(1000)
  5837. NEXT i
  5838.  
  5839. cycles& = 0
  5840. t# = TIMER
  5841. WHILE TIMER < t# + BENCHTIME
  5842.     FOR j = 1 TO ADDBATCH
  5843.     FOR k = 1 TO SIZE   ' one-at-a-time loop
  5844.         z(k) = x(k) + y(k)
  5845.     NEXT k
  5846.     NEXT j
  5847.     cycles& = cycles& + ADDBATCH
  5848. WEND
  5849. t# = TIMER - t#
  5850. n = cycles& / t# 
  5851. PRINT n; " array-adds per second"
  5852.  
  5853. PRINT
  5854. PRINT "* String concatenation ---> ";
  5855.  
  5856. cycles& = 0
  5857. t# = TIMER
  5858. WHILE TIMER < t# + BENCHTIME
  5859.     FOR i = 1 to CONCATBATCH
  5860.     S$ = ""
  5861.     FOR j = 1 TO CONCATSIZE
  5862.         S$ = S$ + "*"
  5863.     NEXT j
  5864.     NEXT i
  5865.     x& = CONCATBATCH
  5866.     x& = x& * CONCATSIZE
  5867.     cycles& = cycles& + x&
  5868. WEND
  5869. t# = TIMER - t#
  5870. n# = cycles& / t# 
  5871. PRINT n#; " concatenations per second"
  5872.  
  5873. PRINT
  5874. PRINT "* Substring selection ---> ";
  5875.  
  5876. cycles& = 0
  5877. t# = TIMER
  5878. WHILE TIMER < t# + BENCHTIME
  5879.     FOR i = 1 to SLICEBATCH
  5880.     partial$ = s$
  5881.     WHILE LEN(partial$) >= 2
  5882.         partial$ = MID$(partial$, 2, LEN(partial$)-2)
  5883.     WEND
  5884.     NEXT i
  5885.     x& = SLICEBATCH
  5886.     x& = x& * LEN(s$) / 2
  5887.     cycles& = cycles& + x&
  5888. WEND
  5889. t# = TIMER - t#
  5890. n# = cycles& / t# 
  5891. PRINT n#; " substrings per second"
  5892.  
  5893. DATA "Kentucky", "Alabama", "California", "Washington", "Ohio", "Texas"
  5894. DATA "Nevada", "Florida", "Wyoming", "New York", "Maine", "Massachusetts"
  5895. DATA "North Carolina", "South Carolina", "North Dakota", "South Dakota"
  5896. DATA "Mississippi", "Arizona", "Hawaii", "Alaska", "Oregon", "Michigan"
  5897. DATA "Illinois", "Pennsylvania", "Kansas", "Virginia", "New Mexico" 
  5898. DATA "Rhode Island", "New Hampshire", "Delaware", "Tennessee", "Colorado"
  5899. DATA "Wisconsin", "Vermont", "Indiana", "Maryland", "Connecticut", "Louisiana"
  5900. DATA "Missouri", "Minnesota", "Iowa", "Idaho", "Arkansas", "Montana"
  5901. DATA "Nebraska", "Georgia", "West Virginia", "Utah", "New Jersey", "Oklahoma"
  5902.  
  5903. FOR i = 1 TO 50
  5904.     READ states$(i)
  5905. NEXT i
  5906.  
  5907. PRINT
  5908. PRINT "* Name look-up ---> ";
  5909. cycles& = 0
  5910. t# = TIMER
  5911. WHILE TIMER < t# + BENCHTIME  
  5912.     FOR j = 1 TO LOOKUPBATCH
  5913.     FOR k = 1 TO 50
  5914.         IF states$(k) = "Oklahoma" THEN
  5915.         EXIT FOR
  5916.         END IF
  5917.     NEXT k
  5918.     IF k <> 50 THEN
  5919.         PRINT "whoops!"
  5920.     END IF
  5921.     NEXT j
  5922.     cycles& = cycles& + LOOKUPBATCH
  5923. WEND
  5924. t# = TIMER - t#
  5925. n = cycles& / t# 
  5926. PRINT n; " look-ups per second"
  5927.  
  5928. SYSTEM
  5929.  
  5930.  
  5931. SEQUENCE.EX
  5932. 3277
  5933. -- Sequence Operations Benchmarks 
  5934.  
  5935. without type_check
  5936.  
  5937. constant BENCH_TIME = 15   -- run for at least this many seconds
  5938. constant SIZE = 100        -- sequence size for init, add
  5939.  
  5940. -- We check the time after performing each "batch". The overhead of checking
  5941. -- the time should be negligible. However we should check often enough so 
  5942. -- a very slow machine running QBasic does not take too long to perform a 
  5943. -- single batch.
  5944. constant INIT_BATCH = 2000 
  5945. constant ADD_BATCH = 1000 
  5946. constant LOOKUP_BATCH = 2000
  5947. constant SLICE_BATCH = 5
  5948. constant CONCAT_BATCH = 5
  5949.  
  5950. constant CONCAT_SIZE = 5000
  5951. constant SCREEN = 1
  5952.  
  5953. atom t, cycles
  5954.  
  5955. puts(SCREEN, "\n\t\tEuphoria Sequence Benchmarks\n")
  5956.  
  5957. sequence x, y, z
  5958.  
  5959. printf(SCREEN, "\n* Initializing a length-%d sequence ---> ", SIZE)
  5960. cycles = 0
  5961. t = time()
  5962. while time() < t + BENCH_TIME do
  5963.     for j = 1 to INIT_BATCH do
  5964.     z = repeat(999, SIZE)
  5965.     end for
  5966.     cycles += INIT_BATCH
  5967. end while
  5968. t = time() - t
  5969. printf(SCREEN, "%d initializations per second\n", cycles / t)
  5970.  
  5971.  
  5972. printf(SCREEN, "\n* Adding two length-%d sequences ---> ", SIZE)
  5973.  
  5974. x = rand(repeat(999, SIZE))
  5975. y = rand(repeat(999, SIZE))
  5976.  
  5977. cycles = 0
  5978. t = time()
  5979. while time() < t + BENCH_TIME do
  5980.     for j = 1 to ADD_BATCH do
  5981.     z = x + y   -- add two sequences
  5982.     end for
  5983.     cycles += ADD_BATCH
  5984. end while
  5985. t = time() - t
  5986. printf(SCREEN, "%5d sequence-adds per second\n", cycles / t)
  5987.  
  5988. puts(SCREEN, "\n* Appending to a sequence ---> ")
  5989. sequence s
  5990. cycles = 0
  5991. t = time()
  5992. while time() < t + BENCH_TIME do
  5993.     for j = 1 to CONCAT_BATCH do
  5994.     s = ""
  5995.     for k = 1 to CONCAT_SIZE do
  5996.         s = append(s, '*')
  5997.     end for
  5998.     end for
  5999.     cycles += CONCAT_BATCH * CONCAT_SIZE
  6000. end while
  6001. t = time() - t
  6002. printf(SCREEN, "%d appends per second\n", cycles / t)
  6003.  
  6004.  
  6005. puts(SCREEN, "\n* Slicing a sequence ---> ")
  6006. sequence partial
  6007. cycles = 0
  6008. t = time()
  6009. while time() < t + BENCH_TIME do
  6010.     for j = 1 to SLICE_BATCH do
  6011.     partial = s 
  6012.     while length(partial) >= 2 do
  6013.         -- delete an element from each end
  6014.         partial = partial[2..length(partial)-1]
  6015.     end while
  6016.     end for
  6017.     cycles += SLICE_BATCH * length(s) / 2
  6018. end while
  6019. t = time() - t
  6020. printf(SCREEN, "%d slices per second\n", cycles / t)
  6021.  
  6022.  
  6023. puts(SCREEN, "\n* Name look-up ---> ")
  6024.  
  6025. sequence states
  6026. states = {
  6027.   "Kentucky", "Alabama", "California", "Washington", "Ohio", "Texas",
  6028.   "Nevada", "Florida", "Wyoming", "New York", "Maine", "Massachusetts",
  6029.   "North Carolina", "South Carolina", "North Dakota", "South Dakota",
  6030.   "Mississippi", "Arizona", "Hawaii", "Alaska", "Oregon", "Michigan",
  6031.   "Illinois", "Pennsylvania", "Kansas", "Virginia", "New Mexico", 
  6032.   "Rhode Island", "New Hampshire", "Delaware", "Tennessee", "Colorado",
  6033.   "Wisconsin", "Vermont", "Indiana", "Maryland", "Connecticut", "Louisiana",
  6034.   "Missouri", "Minnesota", "Iowa", "Idaho", "Arkansas", "Montana",
  6035.   "Nebraska", "Georgia", "West Virginia", "Utah", "New Jersey",  "Oklahoma"
  6036. }
  6037.  
  6038. cycles = 0
  6039. t = time()
  6040. while time() < t + BENCH_TIME do
  6041.     for i = 1 to LOOKUP_BATCH do
  6042.     if find("Oklahoma", states) != 50 then
  6043.         puts(SCREEN, "whoops!\n")
  6044.     end if
  6045.     end for
  6046.     cycles += LOOKUP_BATCH
  6047. end while
  6048. t = time() - t
  6049. printf(SCREEN, "%d look-ups per second\n", cycles / t)
  6050.  
  6051. without warning
  6052.  
  6053. SHELL.BAS
  6054. 1341
  6055. DECLARE SUB sort ()
  6056.  
  6057. DEFINT A-Z
  6058.  
  6059. CONST BATCH = 100
  6060. CONST BENCHTIME = 15
  6061. CONST NITEMS = 50
  6062. DIM SHARED xlist(NITEMS), slist(NITEMS)
  6063.  
  6064. DATA 9, 34, 14, 18, 33, 46, 11, 13, 7, 26, 22, 10, 36, 40, 2, 28, 32, 1
  6065. DATA 23, 31, 43, 5, 24, 42, 45, 50, 16, 3, 47, 39, 21, 49, 41, 6, 19, 30
  6066. DATA 20, 35, 44, 38, 25, 15, 27, 17, 8, 4, 29, 37, 48, 12
  6067.  
  6068. FOR i = 1 TO NITEMS
  6069.     READ xlist(i)
  6070. NEXT i
  6071.  
  6072. PRINT "shell sort benchmark ..."
  6073.  
  6074. cycles& = 0
  6075. t# = TIMER
  6076. WHILE TIMER < t# + BENCHTIME
  6077.     FOR b = 1 TO BATCH
  6078.         REM must preserve the original array
  6079.         FOR x = 1 TO NITEMS
  6080.         slist(x) = xlist(x)
  6081.         NEXT x
  6082.         sort
  6083.     NEXT b
  6084.     cycles& = cycles& + BATCH
  6085. WEND
  6086. t# = TIMER - t#
  6087. PRINT USING "######.## sorts per second"; cycles& / t#
  6088.  
  6089. FOR i = 1 TO NITEMS
  6090.     PRINT slist(i),
  6091. NEXT i
  6092.  
  6093. SYSTEM
  6094.  
  6095. SUB sort
  6096. REM put slist into ascending order
  6097. REM using a shell sort
  6098.     
  6099.     gap = INT(NITEMS / 4) + 1
  6100.     DO
  6101.     FOR i = gap + 1 TO NITEMS
  6102.         tempi = slist(i)
  6103.         j = i - gap
  6104.         DO
  6105.         tempj = slist(j)
  6106.         IF tempi >= tempj THEN
  6107.             j = j + gap
  6108.             EXIT DO
  6109.         END IF
  6110.         slist(j + gap) = tempj
  6111.         IF j <= gap THEN
  6112.             EXIT DO
  6113.         END IF
  6114.         j = j - gap
  6115.         LOOP
  6116.         slist(j) = tempi
  6117.     NEXT i
  6118.     IF gap = 1 THEN
  6119.         EXIT SUB
  6120.     ELSE
  6121.         gap = INT(gap / 4) + 1
  6122.     END IF
  6123.     LOOP
  6124. END SUB
  6125.  
  6126. SHELL.EX
  6127. 1379
  6128.             --------------------------
  6129.             -- Shell sort Benchmark --
  6130.             --------------------------
  6131. without type_check -- makes no difference
  6132.  
  6133. constant BATCH = 100
  6134. constant BENCH_TIME = 15
  6135. constant TRUE = 1
  6136.  
  6137. sequence list, slist
  6138.  
  6139. list = {9, 34, 14, 18, 33, 46, 11, 13, 7, 26, 22, 10, 36, 40, 2, 28, 32, 1,
  6140.     23, 31, 43, 5, 24, 42, 45, 50, 16, 3, 47, 39, 21, 49, 41, 6, 19, 30,
  6141.     20, 35, 44, 38, 25, 15, 27, 17, 8, 4, 29, 37, 48, 12}
  6142.  
  6143. function shell_sort(sequence x)
  6144. -- Shell sort 
  6145. -- will sort any sequence of integers
  6146.     integer gap, j
  6147.     integer first, last 
  6148.     integer tempi, tempj
  6149.  
  6150.     last = length(x)
  6151.     gap = floor(last / 4) + 1
  6152.     while TRUE do
  6153.     first = gap + 1
  6154.     for i = first to last do
  6155.         tempi = x[i]
  6156.         j = i - gap 
  6157.         while TRUE do
  6158.         tempj = x[j]
  6159.         if tempi >= tempj then
  6160.             j += gap
  6161.             exit
  6162.         end if
  6163.         x[j+gap] = tempj
  6164.         if j <= gap then
  6165.             exit
  6166.         end if
  6167.         j -= gap
  6168.         end while
  6169.         x[j] = tempi
  6170.     end for
  6171.     if gap = 1 then
  6172.         return x
  6173.     else
  6174.         gap = floor(gap / 4) + 1 
  6175.     end if
  6176.     end while
  6177. end function
  6178.  
  6179. atom t, cycles
  6180.  
  6181. puts(1, "shell sort benchmark ...\n")
  6182. cycles = 0
  6183. t = time()
  6184. while time() < t + BENCH_TIME do
  6185.     for i = 1 to BATCH do 
  6186.     slist = shell_sort(list) 
  6187.     end for
  6188.     cycles += BATCH
  6189. end while
  6190. t = time() - t
  6191. printf(1, "%6.1f sorts per second\n", cycles / t)
  6192. ? slist
  6193.  
  6194. SIEVE.BAS
  6195. 1014
  6196. ' PRIME SIEVE BENCHMARK
  6197.  
  6198. DEFINT A-Z  'only 16-bit integers - runs faster than DEFLNG A-Z
  6199.  
  6200. DECLARE FUNCTION sieve()
  6201.  
  6202. 'Constants
  6203. CONST BATCH = 50
  6204. CONST BENCHTIME = 15
  6205.  
  6206. CONST TRUE = -1
  6207. CONST FALSE = NOT TRUE
  6208. CONST SIZE = 500
  6209.  
  6210. 'Global Variables
  6211. DIM SHARED flags(SIZE)
  6212.  
  6213. PRINT "prime sieve benchmark ..."
  6214.  
  6215. cycles& = 0
  6216. t# = TIMER
  6217. WHILE TIMER < t# + BENCHTIME
  6218.     FOR b = 1 TO BATCH
  6219.     IF sieve <> 167 THEN
  6220.         PRINT "whoops"
  6221.     END IF
  6222.     NEXT b
  6223.     cycles& = cycles& + BATCH
  6224. WEND
  6225. t# = TIMER - t#
  6226. PRINT USING "###.## sieves per second"; cycles& / t#
  6227.  
  6228. 'Display results
  6229. PRINT "   2";
  6230. FOR b = 1 TO SIZE
  6231.     IF flags(b) THEN
  6232.     PRINT USING "####"; b*2+1;
  6233.     END IF
  6234. NEXT b
  6235.  
  6236. SYSTEM
  6237.  
  6238. FUNCTION sieve
  6239.     count = 0
  6240.     FOR f = 1 TO SIZE
  6241.     flags(f) = TRUE
  6242.     NEXT f
  6243.     FOR i = 1 TO SIZE
  6244.     IF flags(i) THEN
  6245.         prime = 2 * i + 1
  6246.         FOR k = i + prime TO SIZE STEP prime
  6247.         flags(k) = FALSE
  6248.         NEXT k
  6249.         count = count + 1
  6250.     END IF
  6251.     NEXT i
  6252.     sieve = count
  6253. END FUNCTION
  6254.  
  6255. SIEVE.EX
  6256. 1300
  6257.            ---------------------------
  6258.            -- Prime Sieve Benchmark --
  6259.            ---------------------------
  6260. -- with profile
  6261. -- with profile_time -- (DOS only)
  6262.  
  6263. without type_check -- makes no difference
  6264.  
  6265. constant BATCH = 50
  6266. constant BENCH_TIME = 15
  6267.  
  6268. constant SIZE = 500  -- finds primes up to SIZE*2+1
  6269.              -- (only tests odd numbers)
  6270. constant ON = 1, OFF = 0
  6271. constant SCREEN = 1
  6272.  
  6273. sequence flags 
  6274.  
  6275. atom t, cycles
  6276.  
  6277. function sieve()
  6278.     integer prime, start, count, still_prime
  6279.  
  6280.     count = 0
  6281.     flags = repeat(ON, SIZE)
  6282.     for i = 1 to SIZE do
  6283.     still_prime = flags[i]
  6284.     if still_prime then
  6285.         prime = 2 * i 
  6286.         prime += 1 
  6287.         start = prime + i
  6288.         for k = start to SIZE by prime do
  6289.         flags[k] = OFF
  6290.         end for 
  6291.         count += 1
  6292.     end if
  6293.     end for
  6294.     return count
  6295. end function
  6296.  
  6297. puts(SCREEN, "prime sieve benchmark ...\n")
  6298. cycles = 0
  6299. t = time()
  6300. while time() < t + BENCH_TIME do
  6301.     for iter = 1 to BATCH do
  6302.     if sieve() != 167 then
  6303.         puts(SCREEN, "whoops!\n")
  6304.     end if
  6305.     end for
  6306.     cycles += BATCH
  6307. end while
  6308. t = time() - t
  6309. printf(SCREEN, "%6.1f sieves per second\n", cycles / t)
  6310.  
  6311. -- display results
  6312. puts(SCREEN, "   2") -- 2 is also a prime
  6313. for i = 1 to SIZE do
  6314.     if flags[i] then
  6315.     printf(SCREEN, " %3d", i*2+1)
  6316.     end if
  6317. end for
  6318.  
  6319. SIEVE1.PRO
  6320. 1808
  6321. -- Execution-count profile.
  6322. -- Left margin shows the exact number of times that
  6323. -- the statement(s) on that line were executed.
  6324.  
  6325.        |-- with profile_time (DOS only)
  6326.        |
  6327.        |without type_check -- makes no difference
  6328.        |
  6329.        |constant BATCH = 50
  6330.        |constant BENCH_TIME = 0.00001 -- just do one BATCH --15
  6331.        |
  6332.        |constant SIZE = 500  -- finds primes up to SIZE*2+1
  6333.        |             -- (only tests odd numbers)
  6334.        |constant ON = 1, OFF = 0
  6335.        |constant SCREEN = 1
  6336.        |
  6337.        |sequence flags 
  6338.        |
  6339.        |atom t, cycles
  6340.        |
  6341.        |function sieve()
  6342.        |    integer prime, start, count, still_prime
  6343.        |
  6344.     50 |    count = 0
  6345.     50 |    flags = repeat(ON, SIZE)
  6346.     50 |    for i = 1 to SIZE do
  6347.  25000 |    still_prime = flags[i]
  6348.  25000 |    if still_prime then
  6349.   8350 |        prime = 2 * i 
  6350.   8350 |        prime += 1 
  6351.   8350 |        start = prime + i
  6352.   8350 |        for k = start to SIZE by prime do
  6353.  35200 |        flags[k] = OFF
  6354.  35200 |        end for 
  6355.   8350 |        count += 1
  6356.        |    end if
  6357.  25000 |    end for
  6358.     50 |    return count
  6359.        |end function
  6360.        |
  6361.      1 |puts(SCREEN, "prime sieve benchmark ...\n")
  6362.      1 |cycles = 0
  6363.      1 |t = time()
  6364.      1 |while time() < t + BENCH_TIME do
  6365.      1 |    for iter = 1 to BATCH do
  6366.     50 |    if sieve() != 167 then
  6367.        |        puts(SCREEN, "whoops!\n")
  6368.        |    end if
  6369.     50 |    end for
  6370.      1 |    cycles += BATCH
  6371.      1 |end while
  6372.      1 |t = time() - t
  6373.      1 |printf(SCREEN, "%6.1f sieves per second\n", cycles / t)
  6374.        |
  6375.        |-- display results
  6376.      1 |puts(SCREEN, "   2") -- 2 is also a prime
  6377.      1 |for i = 1 to SIZE do
  6378.    500 |    if flags[i] then
  6379.    167 |    printf(SCREEN, " %3d", i*2+1)
  6380.        |    end if
  6381.    500 |end for
  6382.        |
  6383.  
  6384. SIEVE2.PRO
  6385. 1796
  6386. -- Time profile based on 10003 samples.
  6387. -- Left margin shows the percentage of total execution time
  6388. -- consumed by the statement(s) on that line.
  6389.  
  6390.        |
  6391.        |without type_check -- makes no difference
  6392.        |
  6393.        |constant BATCH = 50
  6394.        |constant BENCH_TIME = 100 -- do a long run for better results --15
  6395.        |
  6396.        |constant SIZE = 500  -- finds primes up to SIZE*2+1
  6397.        |             -- (only tests odd numbers)
  6398.        |constant ON = 1, OFF = 0
  6399.        |constant SCREEN = 1
  6400.        |
  6401.        |sequence flags 
  6402.        |
  6403.        |atom t, cycles
  6404.        |
  6405.        |function sieve()
  6406.        |    integer prime, start, count, still_prime
  6407.        |
  6408.        |    count = 0
  6409.   4.79 |    flags = repeat(ON, SIZE)
  6410.   0.04 |    for i = 1 to SIZE do
  6411.  13.24 |    still_prime = flags[i]
  6412.   8.39 |    if still_prime then
  6413.   2.91 |        prime = 2 * i 
  6414.   4.95 |        prime += 1 
  6415.   8.16 |        start = prime + i
  6416.  11.63 |        for k = start to SIZE by prime do
  6417.  16.61 |        flags[k] = OFF
  6418.  16.44 |        end for 
  6419.   1.10 |        count += 1
  6420.        |    end if
  6421.  11.49 |    end for
  6422.   0.15 |    return count
  6423.        |end function
  6424.        |
  6425.        |puts(SCREEN, "prime sieve benchmark ...\n")
  6426.        |cycles = 0
  6427.        |t = time()
  6428.        |while time() < t + BENCH_TIME do
  6429.        |    for iter = 1 to BATCH do
  6430.   0.09 |    if sieve() != 167 then
  6431.        |        puts(SCREEN, "whoops!\n")
  6432.        |    end if
  6433.   0.01 |    end for
  6434.        |    cycles += BATCH
  6435.        |end while
  6436.        |t = time() - t
  6437.        |printf(SCREEN, "%6.1f sieves per second\n", cycles / t)
  6438.        |
  6439.        |-- display results
  6440.        |puts(SCREEN, "   2") -- 2 is also a prime
  6441.        |for i = 1 to SIZE do
  6442.        |    if flags[i] then
  6443.   0.03 |    printf(SCREEN, " %3d", i*2+1)
  6444.        |    end if
  6445.        |end for
  6446.        |
  6447.  
  6448. BUZZ.EX
  6449. 2370
  6450.     -- Buzzword Generator
  6451.     -- Add your own phrases!
  6452.  
  6453. -- How it Works:
  6454. -- buzz has lists of parts of sentences that it matches up at random.
  6455. -- It will always make a grammatically correct sentence.
  6456.  
  6457. constant leadins = {
  6458. "Unfortunately",
  6459. "In the final analysis,",
  6460. "For all intents and purposes",
  6461. "We may definitely conclude that",
  6462. "Leading industry analysts agree that",
  6463. "Therefore",
  6464. "Without a doubt",
  6465. "According to the National Enquirer,",
  6466. "It is rumoured that"
  6467. }
  6468.  
  6469. constant subjects = {
  6470. "the Asian economic crisis",
  6471. "the Year 2000 Problem",
  6472. "Bill Clinton",
  6473. "shareware",
  6474. "the North American Free Trade Deal",
  6475. "C++",
  6476. "IBM",
  6477. "multimedia PCs",
  6478. "local bus video",
  6479. "fax modems",
  6480. "Euphoria",
  6481. "Rapid Deployment Software",
  6482. "Bill Gates",
  6483. "Microsoft",
  6484. "the Pentium processor",
  6485. "pen-based computing",
  6486. "the promised land of 21st century computing",
  6487. "RISC machines",
  6488. "object-oriented technology",
  6489. "case tools",
  6490. "Windows",
  6491. "lap top computers",
  6492. "notebook computers",
  6493. "the World Wide Web",
  6494. "the Information Super Highway"
  6495. }
  6496.  
  6497. constant verbs = {
  6498. "will no longer support",
  6499. "can save",
  6500. "will nibble away at the installed base of",
  6501. "will be the downfall of",
  6502. "will lead the way to",
  6503. "will be like a cancerous growth in",
  6504. "will destroy",
  6505. "will make a mockery of",
  6506. "will not be compatible with",
  6507. "will be a great embarrassment to"
  6508. }
  6509.  
  6510. function buzz(integer n)
  6511. -- generate a paragraph containing n sentences of pure nonsense
  6512.     sequence paragraph
  6513.  
  6514.     paragraph = ""
  6515.     for i = 1 to n do
  6516.     paragraph &= leadins [rand(length(leadins))]  & " " &
  6517.              subjects[rand(length(subjects))] & " " &
  6518.              verbs   [rand(length(verbs))]    & " " &
  6519.              subjects[rand(length(subjects))] & ". "
  6520.     end for
  6521.     return paragraph
  6522. end function
  6523.  
  6524. procedure display(sequence paragraph)
  6525. -- neatly display a paragraph
  6526.     integer column
  6527.     sequence line
  6528.     
  6529.     column = 1
  6530.     line = ""
  6531.     for i = 1 to length(paragraph) do
  6532.     line &= paragraph[i]  -- faster to print a whole line at a time
  6533.     column += 1
  6534.     if column > 65 and (paragraph[i] = ' ' or paragraph[i] = '-') then
  6535.         puts(1, line & '\n')
  6536.         column = 1
  6537.         line = ""
  6538.     end if
  6539.     end for
  6540.     puts(1, line & '\n')
  6541. end procedure
  6542.  
  6543. puts(1, "\n\t\tComputer Industry Forecast\n")
  6544. puts(1, "\t\t--------------------------\n\n")
  6545. display(buzz(8))
  6546. puts(1, "\n\n")
  6547.  
  6548. CSORT.EX
  6549. 1393
  6550. -- Demo of custom_sort(), routine_id()
  6551. -- The Euphoria custom_sort routine is passed the routine id
  6552. -- of the comparison function to be used when sorting.
  6553.  
  6554. include sort.e  -- contains custom_sort()
  6555.  
  6556. constant NAME = 1, 
  6557.      POPULATION = 2
  6558.  
  6559. constant statistics = {
  6560.     {"Canada", 27.4},
  6561.     {"United States", 255.6},
  6562.     {"Brazil", 150.8},
  6563.     {"Denmark", 5.2},
  6564.     {"Sweden", 8.7},
  6565.     {"France", 56.9},
  6566.     {"Germany", 80.6},
  6567.     {"Netherlands", 15.2},
  6568.     {"Italy", 58.0},
  6569.     {"New Zealand", 3.4}
  6570. }   
  6571.  
  6572. function compare_name(sequence a, sequence b)
  6573. -- Compare two sequences (records) according to NAME.
  6574.     return compare(a[NAME], b[NAME])
  6575. end function
  6576.  
  6577. function compare_pop(sequence a, sequence b)
  6578. -- Compare two sequences (records) according to POPULATION.
  6579. -- Note: comparing b vs. a, rather than a vs. b, makes 
  6580. -- the bigger population come first.
  6581.     return compare(b[POPULATION], a[POPULATION])
  6582. end function
  6583.  
  6584. sequence sorted_by_pop, sorted_by_name
  6585. integer by_pop, by_name 
  6586.  
  6587. by_pop  = routine_id("compare_pop")
  6588. by_name = routine_id("compare_name")
  6589.  
  6590. sorted_by_pop = custom_sort(by_pop, statistics)
  6591. sorted_by_name = custom_sort(by_name, statistics)
  6592.  
  6593. puts(1, "sorted by population\t\t  sorted by name\n\n")
  6594. for i = 1 to length(sorted_by_pop) do
  6595.     printf(1, "%13s %6.1f\t\t%13s %6.1f\n", 
  6596.        sorted_by_pop[i] & sorted_by_name[i])
  6597. end for
  6598.  
  6599. DEMO.DOC
  6600. 3533
  6601.  
  6602.         DEMO Programs Written in Euphoria
  6603.         ---------------------------------
  6604.  
  6605.  This directory contains a number of example programs written in Euphoria.
  6606.  These programs are being contributed to the Public Domain by Rapid Deployment 
  6607.  Software. You are encouraged to modify and redistribute any of these programs. 
  6608.  
  6609.  Programs in the DOS32 subdirectory will only run using ex.exe. Programs
  6610.  in the WIN32 subdirectory will only run using exw.exe. Programs in the 
  6611.  Linux subdirectory will only using exu. All other demo programs
  6612.  can be run with any interpreter. You will have either DOS32 and WIN32
  6613.  subdirectories, or a Linux subdirectory depending on which distribution
  6614.  of Euphoria you have downloaded.
  6615.  
  6616.  Be sure that you have restarted your computer after installing Euphoria.
  6617.  AUTOEXEC.BAT will add EUPHORIA\BIN to your PATH and make ex.exe and exw.exe 
  6618.  usable from any directory on your machine, including this DEMO directory.
  6619.  
  6620.  To run a program type 'ex', 'exw' or 'exu' followed by the file name. e.g.
  6621.      
  6622.       ex buzz
  6623.       
  6624.       exw buzz.ex
  6625.       
  6626.       exu buzz.ex
  6627.       
  6628.  If the file type is .ex, you can try to run it with exw or exu, but you must
  6629.  explicitly type the ".ex" part.
  6630.  
  6631.  If you have associated .ex files with ex.exe, and .exw files with exw.exe 
  6632.  you can simply double-click to run any file. However, many programs expect 
  6633.  to be run from the command line and they will terminate immediately after 
  6634.  displaying something.
  6635.  
  6636.  You can view and modify these programs using any editor, but we recommend 
  6637.  using the Euphoria editor, ed, so you can get color syntax highlighting. 
  6638.  
  6639.  See also the tutorial directory for some very simple programs.
  6640.  
  6641.  NAME      DESCRIPTION
  6642.  ----      -----------
  6643.  
  6644.  allsorts.ex - comparison of different sorting algorithms
  6645.  
  6646.  animal.ex - guess the animal game. It learns as you play.
  6647.        
  6648.  buzz.ex   - "buzzword" generator - Try adding your own phrases.
  6649.  
  6650.  csort.ex    - an example of calling custom_sort() with a routine id
  6651.  
  6652.  hash.ex   - counts the frequency of words in standard input by building a
  6653.              hash table (compare with tree.ex below). 
  6654.              Example:
  6655.                 
  6656.                    ex hash < demo.doc
  6657.              
  6658.              Then view the hash.out file.
  6659.              
  6660.  mydata.ex - a simple database program 
  6661.  
  6662.  queens.ex - solves the N queens problem - how to place N queens on an NxN
  6663.          chess board so they do not attack each other
  6664.  
  6665.  sanity.ex - this program tests hundreds of features of Euphoria, in a quick,
  6666.          self-test. If this program reports "PASSED" then Euphoria is
  6667.          working on your machine. If not, there may be something wrong.
  6668.              You can run "ex sanity" or "exw sanity.ex"
  6669.              
  6670.  tree.ex   - counts the frequency of words in standard input by building a
  6671.              binary tree (compare with hash.ex above). 
  6672.              Example:
  6673.              
  6674.                  ex tree < demo.doc
  6675.  
  6676.  bench directory   - contains benchmark programs for comparing Euphoria
  6677.              against QBasic.
  6678.  
  6679.  langwar directory - contains a real-time star wars type game
  6680.                    - runs with ex
  6681.                    
  6682.  win32 directory   - programs that require exw.exe
  6683.  
  6684.  dos32 directory   - programs that require ex.exe
  6685.  
  6686.  linux directory   - programs that require exu
  6687.  
  6688.   --------------------------------------------------------------
  6689.   -- See the source files themselves for more details.        --
  6690.   -- You can view them with:   ed filename.ex                 --
  6691.   --------------------------------------------------------------
  6692.  
  6693. BITMAP.EX
  6694. 1712
  6695. -- bitmap displayer
  6696. -- usage: ex bitmap file[.bmp]
  6697. --
  6698. -- example:  ex bitmap c:\windows\forest
  6699. --
  6700. -- It tries to use mode 261 for 256-color bitmaps and
  6701. -- mode 18 for 16-color or less. If you can't get into mode 261
  6702. -- try mode 19, or see graphics.e
  6703.  
  6704. without type_check
  6705. include image.e
  6706.  
  6707. constant ERR = 2
  6708.  
  6709. sequence cl
  6710. object bitmap
  6711. integer xlen, ylen
  6712. sequence image, Palette, vc
  6713.  
  6714. cl = command_line()
  6715. if length(cl) < 3 then
  6716.     puts(ERR, "usage: ex bitmap file.bmp\n")
  6717.     abort(1)
  6718. end if
  6719. if not find('.', cl[3]) then
  6720.     cl[3] &= ".bmp"
  6721. end if
  6722.  
  6723. bitmap = read_bitmap(cl[3])
  6724.  
  6725. if atom(bitmap) then
  6726.     -- failure
  6727.     if bitmap = BMP_OPEN_FAILED then
  6728.     puts(ERR, cl[3] & ": " & "couldn't open\n")
  6729.     elsif bitmap = BMP_UNEXPECTED_EOF then
  6730.     puts(ERR, cl[3] & ": " & "unexpected end of file\n")
  6731.     else
  6732.     puts(ERR, cl[3] & ": " & "unsupported format\n")
  6733.     end if
  6734.     abort(1)
  6735. end if
  6736.  
  6737. Palette = bitmap[1]
  6738. image = bitmap[2]
  6739.  
  6740. integer mode, xstart
  6741.  
  6742. if length(Palette) > 16 then
  6743.     mode = 261  -- do you have this mode?
  6744. else
  6745.     mode = 18   -- almost everyone has this one
  6746. end if
  6747. if graphics_mode(mode) then
  6748.     puts(ERR, "bad graphics mode\n")
  6749.     abort(1)
  6750. end if
  6751.  
  6752. all_palette(Palette/4)  -- set the whole palette
  6753.  
  6754. display_image({0,0}, image) -- always display first one
  6755.  
  6756. vc = video_config()
  6757.  
  6758. -- display others if there's room:
  6759. xlen = length(image[1])
  6760. ylen = length(image)
  6761. xstart = xlen+1
  6762. for y = 0 to vc[VC_YPIXELS]-floor(ylen/2) by ylen+1 do
  6763.     for x = xstart to vc[VC_XPIXELS]-floor(xlen/2) by xlen+1 do
  6764.     display_image({x,y}, image)
  6765.     end for
  6766.     xstart = 0
  6767. end for
  6768.  
  6769. while get_key() = -1 do
  6770. end while
  6771. if graphics_mode(-1) then
  6772. end if
  6773.  
  6774. CALLMACH.EX
  6775. 2099
  6776.         -- Example of calling a machine code 
  6777.         -- routine from Euphoria
  6778.  
  6779. include machine.e
  6780. include graphics.e
  6781.  
  6782. sequence vc
  6783. vc = video_config()
  6784.  
  6785. atom screen
  6786. if vc[VC_COLOR] then
  6787.     screen = #B8000 -- color
  6788. else
  6789.     screen = #B0000 -- mono
  6790. end if
  6791.  
  6792. sequence string_copy_code, string
  6793. atom code_space, string_space, screen_location
  6794.  
  6795. clear_screen()
  6796.  
  6797. string = {'E', BRIGHT_BLUE, 'u', BRIGHT_GREEN, 'p', BRIGHT_CYAN, 
  6798.       'h', BRIGHT_RED, 'o', BRIGHT_MAGENTA, 'r', YELLOW,
  6799.       'i', BRIGHT_WHITE, 'a', GREEN, '!', BROWN+128}
  6800.  
  6801. string_space = allocate(length(string)+1)
  6802. screen_location = screen + 11*80*2 + 64 -- 11 lines down
  6803.  
  6804.         -- String Copy machine code:
  6805.         -- (will move at least one char)
  6806. string_copy_code =
  6807.       {#50,                            -- push eax
  6808.        #53,                            -- push ebx
  6809.        #52,                            -- push edx
  6810.        #B8} &                          -- mov eax, 
  6811.        int_to_bytes(string_space) &    -- string address (source)
  6812.       {#BA} &                          -- mov edx, 
  6813.        int_to_bytes(screen_location) & -- screen address (destination)
  6814.       {#8A, #18,                       -- L1: mov bl, [eax]
  6815.        #40,                            -- inc eax
  6816.        #88, #1A,                       -- mov [edx],bl
  6817.        #83, #C2, #01,                  -- add edx, #1
  6818.        #80, #38, #00,                  -- cmp byte ptr [eax], #00
  6819.        #75, #F3,                       -- jne L1
  6820.        #5A,                            -- pop edx       
  6821.        #5B,                            -- pop ebx
  6822.        #58,                            -- pop eax
  6823.        #C3}                            -- ret
  6824.  
  6825. -- poke in the machine code:
  6826. code_space = allocate(length(string_copy_code))
  6827. poke(code_space, string_copy_code)
  6828.  
  6829. -- poke in the string:
  6830. poke(string_space, string & 0)
  6831.  
  6832. puts(1, "\n  calling machine code routine ... ")
  6833.  
  6834. -- call the machine code:
  6835. call(code_space) -- copies string to screen
  6836.  
  6837. -- these would be freed anyway when the program ends:
  6838. free(code_space)
  6839. free(string_space)
  6840.  
  6841. puts(1, "success\n")
  6842.  
  6843.  
  6844. DOS32.DOC
  6845. 2570
  6846.         
  6847.         DEMO Programs for the DOS32 Platform
  6848.         ------------------------------------
  6849.  
  6850.  Run each program using ex.exe.
  6851.  
  6852.  -----------------------------------------------------------------------------
  6853.  Note! If you have trouble running any of the graphics oriented programs, try
  6854.  changing the line that says: 
  6855.     constant GRAPHICS_MODE = 261  -- SVGA
  6856.  to: 
  6857.     constant GRAPHICS_MODE = 18   -- VGA
  6858.  This will provide VGA resolution, and shouldn't cause any problems.
  6859.  See include\graphics.e for other possible graphics modes. You should also
  6860.  run under DOS or in a full-screen DOS window under Windows. (Press Alt-Enter)
  6861.  
  6862.  Users of ATI and some other cards, may have to add the following
  6863.  two statements at the top of the .ex file:
  6864.       include machine.e
  6865.       use_vesa(1)
  6866.  This will force the use of the VESA graphics standard for SVGA modes.
  6867.  -----------------------------------------------------------------------------
  6868.  
  6869.  bitmap.ex - displays bitmap (.BMP) pictures
  6870.     
  6871.  callmach.ex - an example of calling machine code from Euphoria
  6872.  
  6873.  dosint.ex - some examples of calling DOS system interrupt routines
  6874.  
  6875.  hardint.ex - a hardware interrupt handler
  6876.  
  6877.  mouse.ex  - simple demo of get_mouse() built-in function
  6878.        - you need DOS mouse support for this
  6879.  
  6880.  mset.ex   - Mandelbrot Set (fractal) generator
  6881.        - Press Enter to stop the display and change all the colors
  6882.            - Press Enter again to choose a region of the M-set to zoom in on
  6883.        - use the arrow keys to select a box to enlarge, or type 'q'
  6884.          to quit
  6885.        - your picture is saved in a .BMP file (suitable for wallpaper!)
  6886.         - it takes a few minutes as hundreds of floating-point calculations 
  6887.           are performed *per pixel*.
  6888.   
  6889.  plot3d.ex - 3-D surface plotting of functions 
  6890.        - add in your own function of x and y, and see it plotted
  6891.        - Press Enter to move on to the next sample function
  6892.  
  6893.  polygon.ex - displays interesting polygon patterns
  6894.         - hit space bar to see a new pattern
  6895.  
  6896.  sb.ex      - bouncing balls screen blank program 
  6897.  
  6898.  stereo.ex - make a random dot stereo picture:
  6899.         - reads "picture" file by default 
  6900.           
  6901.  ttt.ex  - 3-dimensional tic tac toe
  6902.          - try to get 4 in a row, on any plane or 1 per plane
  6903.          - play against "DEFENDO" or "AGGRESSO" or a human, or
  6904.        watch the AGGRESSO and DEFENDO algorithms slug it out
  6905.      - you need DOS mouse support for a human to play
  6906.  
  6907.  wire.ex - 3-D wire frame demo of the big 'E' in Euphoria
  6908.      - hit space bar to freeze/restart the display
  6909.      - Enter to quit
  6910.  
  6911.  
  6912. DOSINT.EX
  6913. 1539
  6914.     -- DOS Interrupt examples
  6915.  
  6916. include machine.e
  6917.  
  6918. constant SCREEN = 1, ERR = 2
  6919.  
  6920.     -- Example 1: Get DOS version number
  6921.  
  6922. sequence reg_list -- list of register values
  6923.  
  6924. reg_list = repeat(0, 10)
  6925. reg_list[REG_AX] = #3000   -- function: AH = #30 ==> Get MS-DOS Version Number
  6926.  
  6927. reg_list = dos_interrupt(#21, reg_list) -- Call DOS interrupt #21
  6928.  
  6929. if and_bits(reg_list[REG_FLAGS], 1) then
  6930.     puts(ERR, "Problem with Get DOS version interrupt\n")
  6931. end if
  6932. printf(SCREEN, "DOS Version: %d.%d\n", {remainder(reg_list[REG_AX], #100), 
  6933.                        floor(reg_list[REG_AX] / #100)})
  6934.  
  6935.             
  6936.     -- Example 2: Get name of current directory
  6937.     -- Note: Euphoria has a library routine for this. See current_dir().
  6938.  
  6939. integer low_buff, p  -- low memory addresses (integer ok)
  6940. sequence dir_name
  6941.  
  6942. low_buff = allocate_low(100)  -- space in low memory to hold directory name
  6943.  
  6944. reg_list = repeat(0, 10)
  6945. reg_list[REG_AX] = #4700                   -- function: AH = #47
  6946. reg_list[REG_DX] = 0                       -- select current drive
  6947. reg_list[REG_DS] = floor(low_buff / 16)    -- address - paragraph number 
  6948. reg_list[REG_SI] = remainder(low_buff, 16) -- address - offset
  6949.  
  6950. reg_list = dos_interrupt(#21, reg_list)    -- Call DOS interrupt #21
  6951.  
  6952. if and_bits(reg_list[REG_FLAGS], 1) != 0 then
  6953.     puts(2, "Couldn't get name of current directory!\n")
  6954. end if
  6955.  
  6956. dir_name = "\\"
  6957. p = low_buff
  6958. while peek(p) != 0 do
  6959.     dir_name &= peek(p)
  6960.     p += 1
  6961. end while
  6962.  
  6963. free_low(low_buff)
  6964.  
  6965. puts(SCREEN, "Current Directory: " & dir_name & '\n')
  6966.  
  6967. HARDINT.EX
  6968. 3868
  6969.     -- hardware interrupt handler example
  6970.  
  6971. include machine.e
  6972.  
  6973. atom handlerA_address, handlerB_address 
  6974. sequence usual_address
  6975. atom code_segment
  6976.  
  6977. -- record the values of the data segment and code segment
  6978. atom segment, clock_ticks
  6979. segment = allocate(4)
  6980. lock_memory(segment, 4)
  6981.  
  6982. clock_ticks = allocate(4)
  6983. lock_memory(clock_ticks, 4)
  6984.  
  6985. sequence save_segment_code
  6986. save_segment_code = {
  6987.     #53,   -- push ebx
  6988.     #0E,   -- push cs   or #1E push ds -- only a 16-bit value
  6989.     #5B,   -- pop ebx  
  6990.     #89, #1D} & int_to_bytes(segment) & -- mov segment, ebx
  6991.     {#5B,   -- pop ebx
  6992.     #C3    -- ret
  6993. }       
  6994. -- note: there's no "pop cs" instruction
  6995.  
  6996. atom save_segment
  6997. save_segment = allocate(length(save_segment_code))
  6998. poke(save_segment, save_segment_code)
  6999. call(save_segment) -- save code segment
  7000.  
  7001. -- N.B. Only read the low order two bytes! - See data segment below
  7002. code_segment = peek(segment) + 256 * peek(segment+1)
  7003.  
  7004. poke(save_segment+1, #1E) 
  7005. call(save_segment) -- save data segment
  7006.  
  7007. -- Here's one type of interrupt handler:
  7008. -- Handler A just returns from the interrupt
  7009. -- after incrementing clock_ticks.
  7010.  
  7011. sequence handlerA_code
  7012. handlerA_code = {
  7013.     #1E,       -- push ds  
  7014.     #60,       -- pushad
  7015.     
  7016.     -- restore our data segment value:
  7017.     #BB} & 
  7018.     
  7019.     -- N.B. Only read low-order 2 bytes of segment.
  7020.     peek({segment, 2}) & {0,0} & -- mov ebx, data segment value
  7021.    
  7022.    {#53,       -- push ebx
  7023.     #1F        -- pop ds
  7024.     } & {#FF, #05} & int_to_bytes(clock_ticks) &  -- inc clock_ticks
  7025.     {
  7026.     -- acknowledge the interrupt (might not be necessary?)
  7027.     #BA,#20,0,0,0,   -- mov edx, 20 -- port number
  7028.     #B0,#20,         -- mov al, value to send to port
  7029.     #EE,             -- out dx, al
  7030.     
  7031.     #61,       -- popad
  7032.     #1F,       -- pop ds 
  7033.     #CF        -- iretd  -- return from interrupt
  7034. }
  7035.  
  7036. -- Here's another type of interrupt handler:
  7037.  
  7038. -- Handler B jumps to the usual clock tick interrupt handler after
  7039. -- incrementing clock_ticks
  7040.  
  7041. sequence handlerB_code
  7042. handlerB_code = {
  7043.     #1E,        -- push ds  
  7044.     #60,        -- pushad
  7045.  
  7046.     -- restore our data segment value:
  7047.     #BB} & peek({segment, 2}) & {0,0} & -- mov ebx, data segment value
  7048.    {#53,    -- push ebx
  7049.     #1F,    -- pop ds
  7050.     
  7051.     #FF, #05} & int_to_bytes(clock_ticks) &  -- inc clock_ticks
  7052.     
  7053.    {#61,        -- popad  -- make things the same as when we were called
  7054.     #1F,        -- popds
  7055.     
  7056.     #EA,        -- jmp to the usual interrupt handler
  7057.     #00,        -- 6-byte segment and offset to be filled in later
  7058.     #00,
  7059.     #00,
  7060.     #00,
  7061.     #00,
  7062.     #00
  7063. }
  7064.  
  7065. handlerA_address = allocate(length(handlerA_code))
  7066.  
  7067. poke(handlerA_address, handlerA_code)
  7068.  
  7069. usual_address = get_vector(#1C) -- clock tick
  7070.  
  7071. handlerB_address = allocate(length(handlerB_code))
  7072.  
  7073. --plug in far address of usual handler:
  7074. handlerB_code[length(handlerB_code)-5..
  7075.           length(handlerB_code)] = 
  7076.           int_to_bytes(usual_address[2]) &
  7077.           remainder(usual_address[1], 256) & floor(usual_address[1] / 256) 
  7078.  
  7079. poke(handlerB_address, handlerB_code)
  7080.  
  7081. lock_memory(handlerA_address, length(handlerA_code))
  7082. lock_memory(handlerB_address, length(handlerB_code))
  7083.  
  7084. atom t
  7085. constant WAIT = 5
  7086.  
  7087. -- Handler A
  7088. poke4(clock_ticks, 0)
  7089. set_vector(#1C, {code_segment, handlerA_address}) 
  7090. t = time()
  7091. printf(1, "Handler A installed. wait %d seconds ...\n", WAIT)
  7092. while time() < t + WAIT do
  7093. end while
  7094. set_vector(#1C, usual_address)
  7095.  
  7096. printf(1, "Number of clock interrupts: %d\n", peek4u(clock_ticks))
  7097.  
  7098. -- Handler B
  7099. poke4(clock_ticks, 0)
  7100. set_vector(#1C, {code_segment, handlerB_address}) 
  7101. t = time()
  7102. printf(1, "Handler B installed. wait %d seconds ...\n", WAIT)
  7103. while time() < t + WAIT do
  7104. end while
  7105. set_vector(#1C, usual_address)
  7106.  
  7107. printf(1, "Number of clock interrupts: %d\n", peek4u(clock_ticks))
  7108.  
  7109. MOUSE.EX
  7110. 2345
  7111.         ----------------
  7112.         -- mouse test --
  7113.         ----------------
  7114. -- This is a very simple program to demonstrate the get_mouse() built-in
  7115. -- function. No call is made to mouse_events(), so by default all events are
  7116. -- reported by get_mouse(). 
  7117.  
  7118. include mouse.e
  7119. include graphics.e
  7120.  
  7121. sequence vc
  7122. vc = video_config()
  7123. if graphics_mode(17 + vc[VC_COLOR]) then -- 640x480 (16 colors)
  7124.     puts(1, "Can't get good graphics mode\n")
  7125.     abort(1)
  7126. end if 
  7127. vc = video_config()
  7128. constant origin = {vc[VC_XPIXELS]/2, vc[VC_YPIXELS]/2}
  7129. constant MAX_LINE = 5
  7130.  
  7131. procedure beep(integer pitch)
  7132.     atom t
  7133.     sound(pitch)
  7134.     t = time()
  7135.     while time() < t+0.07 do
  7136.     end while
  7137.     sound(0)
  7138. end procedure
  7139.  
  7140. procedure try_mouse()
  7141.     integer color, line, eventNo
  7142.     object event
  7143.     sequence movement, str
  7144.  
  7145.     color = 14
  7146.     eventNo = 0
  7147.     line = 1
  7148.     while 1 do
  7149.     event = get_mouse()
  7150.     if sequence(event) then
  7151.         eventNo += 1
  7152.         movement = "- -- -- --"
  7153.  
  7154.         if and_bits(event[1], MOVE) then
  7155.         movement[1] = 'M'
  7156.         mouse_pointer(0)
  7157.         draw_line(color, {origin, {event[2], event[3]}}) 
  7158.         mouse_pointer(1)
  7159.         end if
  7160.  
  7161.         if and_bits(event[1], LEFT_DOWN) then
  7162.         movement[3] = 'D'
  7163.         beep(500)
  7164.         color += 1
  7165.         if color > 15 then
  7166.             color = 0
  7167.         end if 
  7168.         end if
  7169.  
  7170.         if and_bits(event[1], LEFT_UP) then
  7171.         movement[4] = 'U'
  7172.         beep(500)
  7173.         end if
  7174.                 
  7175.         if and_bits(event[1], MIDDLE_DOWN) then
  7176.         movement[6] = 'D'
  7177.         beep(1000)
  7178.         end if
  7179.         
  7180.         if and_bits(event[1], MIDDLE_UP) then 
  7181.         movement[7] = 'U'
  7182.         beep(1000)
  7183.         end if
  7184.         
  7185.         if and_bits(event[1], RIGHT_DOWN) then 
  7186.         movement[9] = 'D'
  7187.         beep(1000)
  7188.         end if
  7189.         
  7190.         if and_bits(event[1], RIGHT_UP) then 
  7191.         movement[10] = 'U'
  7192.         beep(1000)
  7193.         end if
  7194.         
  7195.         if eventNo > 1 then
  7196.         puts(1, str) 
  7197.         line += 1
  7198.         if line > MAX_LINE then
  7199.             line = 1
  7200.         end if
  7201.         position(line, 1)
  7202.         end if
  7203.         
  7204.         str = sprintf("event# %4d: %s, x:%d, y:%d       \r", 
  7205.            {eventNo, movement, event[2], event[3]})
  7206.  
  7207.         text_color(BRIGHT_MAGENTA)
  7208.         puts(1, str)
  7209.         text_color(WHITE)
  7210.         puts(1, '\n' & repeat(' ', length(str))) 
  7211.         position(line, 1)
  7212.     end if
  7213.     
  7214.     if get_key() != -1 then
  7215.         exit
  7216.     end if
  7217.     end while
  7218. end procedure
  7219.  
  7220. try_mouse()
  7221.  
  7222. if graphics_mode(-1) then
  7223. end if
  7224.  
  7225. MSET.EX
  7226. 6945
  7227.         ---------------------------------
  7228.         -- Plotting the Mandelbrot Set --
  7229.         ---------------------------------
  7230. -- Usage: ex mset
  7231.  
  7232. -- Generates M-Set pictures.
  7233. -- Hit Enter at any time to stop the display. Hit Enter again to save 
  7234. -- the current picture and display a grid. Use the arrow keys to select 
  7235. -- the most interesting box in the grid. Hit Enter to redraw this box at 
  7236. -- the full size of the screen, or hit Esc to quit. The pictures that you 
  7237. -- display are saved in eu_mseta.bmp, eu_msetb.bmp, ...
  7238.  
  7239. -- Move any eu_mset.bmp file of the right screen dimensions to \windows 
  7240. -- and it will be added to your list of choices for "wallpaper". 
  7241. -- Right click on your wallpaper to change it (Win95/98).
  7242.  
  7243. constant GRAPHICS_MODE = 261
  7244.                --  18 is  640x480  16 color  VGA (guaranteed to work)
  7245.                -- 257 is  640x480 256 color SVGA
  7246.                -- 259 is  800x600 256 color SVGA
  7247.                -- 261 is 1024x768 256 color SVGA
  7248.  
  7249. without type_check
  7250.  
  7251. include image.e
  7252. include select.e
  7253. include get.e
  7254.  
  7255. constant ZOOM_FACTOR = 20    -- grid size for zooming in
  7256.  
  7257. constant FALSE = 0, TRUE = 1
  7258. constant REAL = 1, IMAG = 2
  7259.  
  7260. constant ARROW_LEFT  = 331,
  7261.      ARROW_RIGHT = 333,
  7262.      ARROW_UP    = 328,
  7263.      ARROW_DOWN  = 336
  7264.  
  7265.     -- types --
  7266.  
  7267. type natural(integer x)
  7268.     return x >= 0
  7269. end type
  7270.  
  7271. type complex(sequence x)
  7272.     return length(x) = 2 and atom(x[1]) and atom(x[2])
  7273. end type
  7274.  
  7275. procedure beep()
  7276. -- make a beep sound
  7277.     atom t
  7278.  
  7279.     t = time()
  7280.     sound(500)
  7281.     while time() < t + .2 do
  7282.     end while
  7283.     sound(0)
  7284. end procedure
  7285.  
  7286. natural ncolors
  7287. natural max_iter
  7288.  
  7289. sequence vc -- current video configuration
  7290.  
  7291. procedure randomize_palette()
  7292. -- choose random color mixtures    
  7293.     sequence new_pal 
  7294.     
  7295.     new_pal = rand(repeat(repeat(64, 3), ncolors)) - 1
  7296.     if ncolors > 16 then
  7297.     new_pal[17] = {0,0,0}  -- black border
  7298.     end if
  7299.     all_palette(new_pal)
  7300. end procedure
  7301.  
  7302. procedure grid(sequence x, sequence y, natural color)
  7303. -- draw the grid
  7304.     atom dx, dy
  7305.  
  7306.     dx = vc[VC_XPIXELS]/ZOOM_FACTOR
  7307.     dy = vc[VC_YPIXELS]/ZOOM_FACTOR
  7308.  
  7309.     for i = x[1] to x[2] do
  7310.     draw_line(color, {{i*dx, y[1]*dy}, {i*dx, y[2]*dy}})
  7311.     end for
  7312.     for i = y[1] to y[2] do
  7313.     draw_line(color, {{x[1]*dx, i*dy}, {x[2]*dx, i*dy}})
  7314.     end for
  7315. end procedure
  7316.  
  7317. function zoom()
  7318. -- select place to zoom in on next time
  7319.     integer key
  7320.     sequence box
  7321.  
  7322.     grid({0, ZOOM_FACTOR}, {0, ZOOM_FACTOR}, 7)
  7323.     box = {0, ZOOM_FACTOR-1}
  7324.     while TRUE do
  7325.     grid({box[1], box[1]+1}, {box[2], box[2]+1}, rand(15))
  7326.     key = get_key()
  7327.     if key != -1 then
  7328.         grid({box[1], box[1]+1}, {box[2], box[2]+1}, 7)
  7329.         if key = ARROW_UP then
  7330.         if box[2] > 0 then
  7331.             box[2] -= 1
  7332.         end if
  7333.         elsif key = ARROW_DOWN then
  7334.         if box[2] < ZOOM_FACTOR-1 then
  7335.             box[2] += 1
  7336.         end if
  7337.         elsif key = ARROW_RIGHT then
  7338.         if box[1] < ZOOM_FACTOR-1 then
  7339.             box[1] += 1
  7340.         end if
  7341.         elsif key = ARROW_LEFT then
  7342.         if box[1] > 0 then
  7343.             box[1] -= 1
  7344.         end if
  7345.         elsif key >= 27  then
  7346.         return {}  -- quit
  7347.         else
  7348.         return {box[1], ZOOM_FACTOR - 1  - box[2]}
  7349.         end if
  7350.     end if
  7351.     end while
  7352. end function
  7353.  
  7354. procedure mset(complex lower_left,  -- lower left corner
  7355.           complex upper_right) -- upper right corner
  7356. -- Plot the Mandelbrot set over some region.
  7357. -- The Mandelbrot set is defined by the equation: z = z * z + C
  7358. -- where z and C are complex numbers. The starting point for z is 0.
  7359. -- If, for a given value of C, z approaches infinity, C is considered to
  7360. -- *not* be a member of the set. It can be shown that if the absolute value
  7361. -- of z ever becomes greater than 2, then the value of z will increase
  7362. -- towards infinity from then on. After a large number of iterations, if
  7363. -- the absolute value of z is still less than 2 then we assume with high
  7364. -- probability that C is a member of the Mset and this program will show
  7365. -- that point in black.
  7366.     complex c
  7367.     atom zr, zi, zr2, zi2, cr, ci, xsize, ysize
  7368.     natural member, stop, color, width, height
  7369.     sequence color_line
  7370.     
  7371.     clear_screen()
  7372.     height = vc[VC_YPIXELS]
  7373.     width = vc[VC_XPIXELS]
  7374.     color_line = repeat(0, width)
  7375.     xsize = (upper_right[REAL] - lower_left[REAL])/(width - 1)
  7376.     ysize = (upper_right[IMAG] - lower_left[IMAG])/(height - 1)
  7377.     c = {0, 0}
  7378.  
  7379.     for y = 0 to height - 1 do
  7380.     if get_key() != -1 then
  7381.         return 
  7382.     end if
  7383.     c[IMAG] = upper_right[IMAG] - y * ysize
  7384.     for x = 0 to width - 1 do
  7385.         c[REAL] = lower_left[REAL] + x * xsize
  7386.         member = TRUE
  7387.         zr = 0
  7388.         zi = 0
  7389.         zr2 = 0
  7390.         zi2 = 0
  7391.         cr = c[REAL]
  7392.         ci = c[IMAG]
  7393.         for i = 1 to max_iter do
  7394.         zi = 2.0 * zr * zi + ci
  7395.         zr = zr2 - zi2 + cr
  7396.         zr2 = zr * zr
  7397.         zi2 = zi * zi
  7398.         if zr2 + zi2 > 4.0 then
  7399.             member = FALSE
  7400.             stop = i
  7401.             exit
  7402.         end if
  7403.         end for
  7404.         if member = TRUE then
  7405.         color = 0
  7406.         else
  7407.         color = stop + 51 -- gives nice sequence of colors
  7408.         while color >= ncolors do
  7409.             color -= ncolors
  7410.         end while
  7411.         end if
  7412.         color_line[x+1] = color
  7413.     end for
  7414.     pixel(color_line, {0, y}) -- write out a whole line of pixels at once
  7415.     end for
  7416. end procedure
  7417.  
  7418. procedure Mandelbrot()
  7419. -- main procedure
  7420.     sequence delta, new_box
  7421.     complex lower_left, upper_right
  7422.     sequence pic_name
  7423.     integer p, c
  7424.     natural file_no
  7425.     atom t
  7426.     
  7427.     -- initially show the upper half:
  7428.     max_iter = 30 -- increases as we zoom in
  7429.     lower_left = {-1, 0}
  7430.     upper_right = {1, 1}
  7431.     
  7432.     -- set up for desired graphics mode
  7433.     if not select_mode(GRAPHICS_MODE) then
  7434.     puts(2, "couldn't find a good graphics mode\n")
  7435.     return
  7436.     end if
  7437.     vc = video_config()
  7438.     ncolors = vc[VC_NCOLORS]
  7439.  
  7440.     while TRUE do
  7441.     -- Display the M-Set
  7442.     mset(lower_left, upper_right)
  7443.     beep()
  7444.     
  7445.     -- choose a new file to save the picture into
  7446.     file_no = 0
  7447.     for i = 'a' to 'z' do
  7448.         p = open("eu_mset" & i & ".bmp", "rb")
  7449.         if p = -1 then
  7450.         file_no = i
  7451.         exit
  7452.         else
  7453.         -- file exists
  7454.         close(p)
  7455.         end if
  7456.     end for
  7457.     if file_no then
  7458.         pic_name = "eu_mset" & file_no & ".bmp"
  7459.     else
  7460.         puts(1, "Couldn't find a new file name to use\n")
  7461.         return 
  7462.     end if
  7463.  
  7464.     -- choose new colors
  7465.     while 1 do
  7466.         t = time() + 5
  7467.         while time() < t do
  7468.         c = get_key()
  7469.         if c != -1 then
  7470.             exit
  7471.         end if
  7472.         end while
  7473.         if c != -1 then
  7474.         exit
  7475.         end if
  7476.         randomize_palette()
  7477.     end while
  7478.  
  7479.     -- save the picture into a .bmp file
  7480.     if save_screen(0, pic_name) then
  7481.     end if
  7482.     
  7483.     -- clear the keyboard buffer
  7484.     while get_key() != -1 do
  7485.     end while
  7486.     
  7487.     new_box = zoom()
  7488.     if length(new_box) = 0 then
  7489.         exit
  7490.     end if
  7491.     
  7492.     delta = (upper_right - lower_left)
  7493.     lower_left += new_box / ZOOM_FACTOR * delta
  7494.     upper_right = lower_left + delta / ZOOM_FACTOR
  7495.     max_iter *= 2  -- need more iterations as we zoom in
  7496.     end while
  7497. end procedure
  7498.  
  7499. Mandelbrot()
  7500.  
  7501. if graphics_mode(-1) then
  7502. end if
  7503.  
  7504. PICTURE
  7505. 1400
  7506. ....................................................................
  7507. ....................................................................
  7508. ....................................................................
  7509. .......11111111111111111111.........................................
  7510. .......11111111111111111111.........................................
  7511. .......1111............1111.........................................
  7512. .......1111.........................................................
  7513. .......1111.........................................................
  7514. .......1111.........................................................
  7515. .......1111111111...................................................
  7516. .......1111111111..............1111........1111.....................
  7517. .......1111....................1111........1111.....................
  7518. .......1111....................1111........1111.....................
  7519. .......1111....................1111........1111.....................
  7520. .......1111............1111....1111........1111.....................
  7521. .......11111111111111111111....1111111111111111.....................
  7522. .......11111111111111111111.....11111111111111......................
  7523. ....................................................................
  7524. ....................................................................
  7525. ....................................................................
  7526. PLOT3D.EX
  7527. 5939
  7528.         --------------------------------
  7529.         -- Plotting of 3-D Surfaces:  --
  7530.         -- Z as a function of X and Y --
  7531.         --------------------------------
  7532.  
  7533. -- The program does a quick plot of each function to get the scaling right,
  7534. -- then replots so the picture will fit neatly on the screen.
  7535. -- The 4 x-y quadrants are in different colors.
  7536. -- Where z is positive, a brighter shade of color is used.
  7537. -- edit the_function() to insert your function
  7538. -- set GRAPHICS_MODE = a good mode for your machine
  7539. --                     (see euphoria\include\graphics.e for a list of modes)
  7540. -- Press Enter at any time to skip to the next function.
  7541.  
  7542. constant GRAPHICS_MODE = 261  -- SVGA, if this fails try mode 18 
  7543.  
  7544. without type_check
  7545.  
  7546. include graphics.e
  7547. include select.e
  7548.  
  7549. constant NFUNCS = 6
  7550. constant c = sqrt(2.0) / 2
  7551. constant SCREEN = 1
  7552.  
  7553. atom x_min, x_max, x_inc
  7554. atom y_min, y_max, y_inc
  7555. atom z_min, z_max
  7556. atom xc_min, xc_max, yc_min, yc_max
  7557.  
  7558. atom origin_x, origin_y
  7559. origin_x = 400
  7560. origin_y = 150
  7561.  
  7562. integer func_no
  7563. integer grid_width, fine
  7564. integer x_res, y_res
  7565.  
  7566. atom h_magnifier, v_magnifier
  7567.  
  7568. sequence prev_coord
  7569.  
  7570. function abs(atom x)
  7571.     if x < 0 then
  7572.     return -x
  7573.     else
  7574.     return x
  7575.     end if
  7576. end function
  7577.  
  7578. function the_function(atom x, atom y)
  7579. -- compute a function z of two variables x and y
  7580. -- There are actually several different functions below,
  7581. -- selected by the func_no variable
  7582.     sequence pq, pr, ps -- points in the plane
  7583.     atom dq, dr, ds     -- distance from p
  7584.     atom z, w
  7585.  
  7586.     if func_no = 1 then
  7587.     return 100*x*x + 100*y*y - 50
  7588.  
  7589.     elsif func_no = 2 then
  7590.     return 200*x*x*x - 200*y*y*y
  7591.  
  7592.     elsif func_no = 3 then
  7593.     return 50 * cos(8*x*y)
  7594.  
  7595.     elsif func_no = 4 then
  7596.     return 50 * cos(8*(x+y))
  7597.  
  7598.     elsif func_no = 5 then
  7599.     z = 50 * cos(50 * sqrt(x*x+y*y))
  7600.     if z >= -0.01 then
  7601.         if (x < 0 and y < 0) or (x > 0 and y > 0) then
  7602.         return z / 10
  7603.         else
  7604.         return z
  7605.         end if
  7606.     else
  7607.         return -0.01
  7608.     end if
  7609.     elsif func_no = 6 then
  7610.     pq = {.6, -.4}
  7611.     pr = {-.6, 0}
  7612.     ps = {.5, +.5}
  7613.     dq = sqrt((x-pq[1]) * (x-pq[1]) + (y-pq[2]) * (y-pq[2]))
  7614.     dr = sqrt((x-pr[1]) * (x-pr[1]) + (y-pr[2]) * (y-pr[2]))
  7615.     ds = sqrt((x-ps[1]) * (x-ps[1]) + (y-ps[2]) * (y-ps[2]))
  7616.     z = -25 * cos(ds*15)/(0.1 + ds*sqrt(ds)) +
  7617.          75 * cos(dq*3) /(0.1 + dq*sqrt(dq))
  7618.     if x < 0 then
  7619.         w = 60 * cos(9 * dr)
  7620.         if w < 0 then
  7621.         w = 0
  7622.         else
  7623.         w *= 2 * sqrt(-x)
  7624.         end if
  7625.         z += w
  7626.     end if
  7627.     return z
  7628.     end if
  7629. end function
  7630.  
  7631. procedure set_range()
  7632.     -- magnification factors
  7633.     h_magnifier = 1.0
  7634.     v_magnifier = 1.0
  7635.  
  7636.     -- extreme values
  7637.     xc_min = 1e307
  7638.     xc_max = -1e307
  7639.     yc_min = xc_min
  7640.     yc_max = xc_max
  7641.     z_min = xc_min
  7642.     z_max = xc_max
  7643.  
  7644.     -- range of values to plot
  7645.     x_min = -1
  7646.     x_max = +1
  7647.     y_min = -1
  7648.     y_max = +1
  7649.  
  7650.    -- calculate some derived values:
  7651.     x_inc = (x_max - x_min) / x_res
  7652.     y_inc = (y_max - y_min) / y_res
  7653. end procedure
  7654.  
  7655. procedure note_extreme(sequence coord, atom z)
  7656. -- record the extreme values
  7657.     if coord[1] < xc_min then
  7658.     xc_min = coord[1]
  7659.     elsif coord[1] > xc_max then
  7660.     xc_max = coord[1]
  7661.     end if
  7662.     if coord[2] < yc_min then
  7663.     yc_min = coord[2]
  7664.     elsif coord[2] > yc_max then
  7665.     yc_max = coord[2]
  7666.     end if
  7667.     if z > z_max then
  7668.     z_max = z
  7669.     elsif z < z_min then
  7670.     z_min = z
  7671.     end if
  7672. end procedure
  7673.  
  7674. function set_coord(atom x, atom y, atom z)
  7675. -- return the coordinates to plot, given the x, y and z values
  7676.     atom k
  7677.  
  7678.     k = (x - x_min)/x_inc * c
  7679.     return {h_magnifier * (origin_x + (y - y_min)/y_inc - k),
  7680.         v_magnifier * (origin_y - z + k)}
  7681. end function
  7682.  
  7683. procedure plot(atom x, atom y)
  7684. -- plot the point according to 3-D perspective
  7685.     atom z, col
  7686.     sequence coord
  7687.  
  7688.     z = the_function(x, y)
  7689.     coord = set_coord(x, y, z)
  7690.     note_extreme(coord, z)
  7691.     -- select color by quadrant
  7692.     col = (z >= 0) * 8 + (x >= 0) * 2 + (y >= 0) + 1
  7693.     if length(prev_coord) = 0 then
  7694.     pixel(col, coord)
  7695.     else
  7696.     draw_line(col, {prev_coord, coord})
  7697.     end if
  7698.     prev_coord = coord
  7699. end procedure
  7700.  
  7701. function plot_a_function()
  7702. -- generate 3d plotted graph
  7703.  
  7704.     for x = x_min to x_max by grid_width * x_inc do
  7705.     if get_key() != -1 then
  7706.         return 0
  7707.     end if
  7708.     prev_coord = {}
  7709.     for y = y_min to y_max by fine * y_inc do
  7710.         plot(x, y)
  7711.     end for
  7712.     end for
  7713.  
  7714.     for y = y_min to y_max by grid_width * y_inc do
  7715.     if get_key() != -1 then
  7716.         return 0
  7717.     end if
  7718.     prev_coord = {}
  7719.     for x = x_min to x_max by fine * x_inc do
  7720.         plot(x, y)
  7721.     end for
  7722.     end for
  7723.     return 1
  7724. end function
  7725.  
  7726. procedure box()
  7727. -- draw a box around the outside of edge of the screen
  7728.     polygon(5, 0, {{0, 0}, {0, y_res-1}, {x_res-1, y_res-1}, {x_res-1, 0}})
  7729. end procedure
  7730.  
  7731. procedure plot3d()
  7732. -- main program
  7733.     func_no = 1
  7734.     while func_no <= NFUNCS do
  7735.     set_range()
  7736.     -- do a quick trial run to establish range of values
  7737.     grid_width = 20
  7738.     fine = 4
  7739.     if plot_a_function() then
  7740.         clear_screen()
  7741.         box()
  7742.         -- make next one fit screen better
  7743.         v_magnifier = (y_res - 1) / (yc_max - yc_min)
  7744.         h_magnifier = (x_res - 1) / (xc_max - xc_min)
  7745.         origin_x -= xc_min
  7746.         origin_y -= yc_min
  7747.         grid_width = 20
  7748.         fine = 1
  7749.         if plot_a_function() then
  7750.         position(2, 2)
  7751.         printf(SCREEN, "x: %5.1f to %4.1f", {x_min, x_max})
  7752.         position(3, 2)
  7753.         printf(SCREEN, "y: %5.1f to %4.1f", {y_min, y_max})
  7754.         position(4, 2)
  7755.         printf(SCREEN, "z: %5.1f to %4.1f", {z_min, z_max})
  7756.         while get_key() = -1 do
  7757.         end while
  7758.         end if
  7759.     end if
  7760.     func_no += 1
  7761.     clear_screen()
  7762.     end while
  7763. end procedure
  7764.  
  7765. sequence config
  7766.  
  7767. -- execution starts here:
  7768. if select_mode(GRAPHICS_MODE) then
  7769.     config = video_config()
  7770.     x_res = config[VC_XPIXELS]
  7771.     y_res = config[VC_YPIXELS]
  7772.     plot3d()
  7773.     if graphics_mode(-1) then
  7774.     end if
  7775. else
  7776.     puts(1, "couldn't find a good graphics mode\n")
  7777. end if
  7778.  
  7779. POLYGON.EX
  7780. 2362
  7781.         -----------------------------
  7782.         -- Polygon Pattern Program --
  7783.         -----------------------------
  7784.  
  7785. -- press space bar to see a new pattern
  7786. -- press any other key to quit
  7787.  
  7788. constant GRAPHICS_MODE = 261 -- SVGA, if this fails try mode 18 
  7789.                  -- see also euphoria\include\graphics.e
  7790. without type_check
  7791.  
  7792. include graphics.e
  7793. include select.e
  7794.  
  7795. constant TRUE = 1
  7796.  
  7797. constant X = 1,
  7798.      Y = 2
  7799.  
  7800. sequence config
  7801. integer nlines, npoints, spacing, solid
  7802.  
  7803. function poly_pattern()
  7804.     integer color, color_step, ncolors, key
  7805.     sequence points, deltas, history
  7806.  
  7807.     config = video_config()
  7808.     ncolors = config[VC_NCOLORS]
  7809.     color = 1
  7810.     color_step = 1
  7811.     points = rand(repeat(config[VC_XPIXELS..VC_YPIXELS], npoints)) - 1
  7812.     deltas = rand(repeat({2*spacing-1, 2*spacing-1}, npoints)) - spacing
  7813.     history = {}
  7814.     clear_screen()
  7815.     while TRUE do
  7816.     if length(history) >= nlines then
  7817.         -- blank out oldest line
  7818.         polygon(0, solid, history[1])
  7819.         history = history[2..nlines]
  7820.     end if
  7821.     polygon(color, solid, points)
  7822.     history = append(history, points)
  7823.     points += deltas
  7824.     -- make vertices change direction at edge of screen
  7825.     for j = 1 to npoints do
  7826.         if points[j][X] <= 0 or points[j][X] >= config[VC_XPIXELS] then
  7827.         deltas[j][X] = -deltas[j][X]
  7828.         end if
  7829.         if points[j][Y] <= 0 or points[j][Y] >= config[VC_YPIXELS] then
  7830.         deltas[j][Y] = -deltas[j][Y]
  7831.         end if
  7832.     end for
  7833.     -- step through the colors
  7834.     color += color_step
  7835.     if color >= ncolors then
  7836.         color_step = rand(ncolors)
  7837.         color = color_step
  7838.     end if
  7839.     -- change background color once in a while
  7840.     if rand(100) = 1 then
  7841.         bk_color(rand(ncolors)-1)
  7842.     end if
  7843.     -- see if user wants to quit
  7844.     key = get_key()
  7845.     if key = ' ' then
  7846.         return 0
  7847.     elsif key != -1 then
  7848.         return 1
  7849.     end if
  7850.     end while
  7851. end function
  7852.  
  7853. if not select_mode(GRAPHICS_MODE) then
  7854.     puts(1, "couldn't find a good graphics mode\n")
  7855.     abort(1)
  7856. end if
  7857.  
  7858. while TRUE do
  7859.     -- Play with these parameters for neat effects!
  7860.     nlines = 1+rand(140)   -- number of lines on screen at one time
  7861.     npoints = 2+rand(16)   -- number of points in polygons
  7862.     spacing = 1+rand(24)   -- spacing between lines
  7863.     solid = rand(2)-1      -- solid polygons? 1 or 0
  7864.     if poly_pattern() then
  7865.     exit
  7866.     end if
  7867. end while
  7868.  
  7869. if graphics_mode(-1) then
  7870. end if
  7871.  
  7872. SB.EX
  7873. 2119
  7874.         ------------------------------------
  7875.         -- Atomic Reaction Screen Blanker --
  7876.         ------------------------------------
  7877. without type_check
  7878.  
  7879. include graphics.e
  7880. include select.e
  7881.  
  7882. constant GRAPHICS_MODE = 18 -- VGA
  7883.  
  7884. constant MAX_POPULATION = 125          -- maximum number of circles
  7885. constant MAX_SIZE = 5, MIN_SIZE = 1    -- size of circles
  7886.  
  7887. constant TRUE = 1
  7888. constant X = 1, Y = 2
  7889. constant FILL = 1
  7890.  
  7891. sequence size, circles, dirs, colors
  7892. sequence vc
  7893.  
  7894. procedure init()
  7895. -- initialize global variables
  7896.     if not select_mode(GRAPHICS_MODE) then
  7897.     puts(1, "needs VGA graphics\n")
  7898.     abort(1)
  7899.     end if
  7900.     vc = video_config()
  7901.     circles = {}
  7902.     dirs = {}
  7903.     colors = {}
  7904.     size = {}
  7905. end procedure
  7906.  
  7907. procedure bounce()
  7908. -- main routine
  7909.     sequence top_left, prev_circle
  7910.     integer x, y, s
  7911.     atom t
  7912.  
  7913.     init()
  7914.     t = time()
  7915.     while t+1 > time() do
  7916.     -- wait for screen to settle - looks better
  7917.     end while
  7918.     while TRUE do
  7919.     if get_key() != -1 then
  7920.         exit
  7921.     end if
  7922.     
  7923.     if length(circles) < MAX_POPULATION then
  7924.         -- add a new circle
  7925.         x = 0  y = 0 -- start each circle at top left corner of screen
  7926.         s = MIN_SIZE + rand(MAX_SIZE+1-MIN_SIZE) - 1
  7927.         size = append(size, s)
  7928.         circles = append(circles, {{x, y}, {x, y}+s})
  7929.         dirs = append(dirs, floor(s/2)+rand({10*s, 10*s})/10)
  7930.         colors = append(colors, 8+rand(vc[VC_NCOLORS]/2-1))
  7931.     end if
  7932.     
  7933.     -- move all the circles
  7934.     for i = 1 to length(circles) do
  7935.         top_left = circles[i][1]
  7936.         prev_circle = circles[i]
  7937.         if top_left[X] < 0 or top_left[X]+size[i] >= vc[VC_XPIXELS] then 
  7938.         dirs[i][X] = -dirs[i][X] 
  7939.         end if
  7940.         if top_left[Y] < 0 or top_left[Y]+size[i] >= vc[VC_YPIXELS] then 
  7941.         dirs[i][Y] = -dirs[i][Y] 
  7942.         end if
  7943.         top_left += dirs[i]
  7944.         circles[i] = {top_left, top_left+size[i]}
  7945.         -- blank out old position
  7946.         ellipse(BLACK, FILL, prev_circle[1], prev_circle[2])
  7947.         -- draw at new position
  7948.         ellipse(colors[i], FILL, circles[i][1], circles[i][2])
  7949.     end for
  7950.     end while
  7951.     if graphics_mode(-1) then
  7952.     end if
  7953. end procedure
  7954.  
  7955. bounce()
  7956.  
  7957. SELECT.E
  7958. 869
  7959.         -------------------------------------
  7960.         -- search for a good graphics mode --
  7961.         -------------------------------------
  7962.  
  7963. constant nice_color_modes = {261,18,260,259,258,257,256,19,16,14,13,4},
  7964.      nice_mono_modes = {17, 11, 15, 6, 5}
  7965.  
  7966. global function select_mode(integer choice)
  7967. -- Try to select the choice mode, but if it fails try other modes.
  7968. -- This is not guaranteed to work - you may have to set the mode
  7969. -- yourself by editing the code.
  7970.     sequence vc, modes
  7971.     integer fail
  7972.  
  7973.     vc = video_config()
  7974.     if vc[VC_COLOR] then
  7975.     modes = choice & nice_color_modes
  7976.     else
  7977.     modes = choice & nice_mono_modes
  7978.     end if
  7979.     for i = 1 to length(modes) do
  7980.     fail = graphics_mode(modes[i])
  7981.     vc = video_config()
  7982.     if not fail and vc[VC_XPIXELS] > 40 and vc[VC_YPIXELS] > 40 then
  7983.         return 1    
  7984.     end if
  7985.     end for
  7986.     return 0
  7987. end function
  7988.  
  7989. STEREO.EX
  7990. 1968
  7991. -- Random Dot Stereo Pictures
  7992. -- Like the ones you've seen in all the shopping malls!
  7993. -- Relax your eyes so that you are focusing a few inches
  7994. -- behind the screen - maybe on your reflection if you have
  7995. -- a lot of glare. You should see 2 letters of the alphabet,
  7996. -- one upper case, one lower case.
  7997.  
  7998. -- usage:  ex stereo [filename]
  7999. -- (will read PICTURE file by default)
  8000.  
  8001. -- picture can contain digits from 1 to 9 to indicate "depth"
  8002.  
  8003. without type_check
  8004. include graphics.e
  8005.  
  8006. constant DEPTH = 13
  8007. sequence vc
  8008. integer xpixels_per_char, ypixels_per_char, in_file
  8009.  
  8010. procedure gstereo()
  8011.     object input
  8012.     sequence image, row, line
  8013.     integer index, height, w
  8014.     
  8015.     image = {}
  8016.     while 1 do
  8017.     input = gets(in_file)
  8018.     if atom(input) then
  8019.         exit
  8020.     end if
  8021.     image = append(image, repeat(' ', DEPTH) & input)
  8022.     end while
  8023.     w = DEPTH * xpixels_per_char
  8024.     for y = 0 to (length(image)-1)*ypixels_per_char do
  8025.     line = image[floor(y/ypixels_per_char+1)]
  8026.     row = repeat(0, (length(image[1])-1)*xpixels_per_char)
  8027.     row[1..w] = rand(repeat(vc[VC_NCOLORS], w))-1
  8028.     for x = w + 1 to length(row) do
  8029.         height = line[x/xpixels_per_char+1]
  8030.         index = x - w
  8031.         if height >= '0' then
  8032.         if height <= '9' then
  8033.             index += (height - '0') * xpixels_per_char
  8034.         end if
  8035.         end if  
  8036.         row[x] = row[index]
  8037.     end for
  8038.     pixel(row, {0, y})
  8039.     end for
  8040. end procedure
  8041.  
  8042. if graphics_mode(18) then
  8043.     puts(2, "need VGA graphics\n")
  8044.     abort(1)
  8045. end if
  8046.  
  8047. sequence cmd, file_name
  8048.  
  8049. cmd = command_line()
  8050. if length(cmd) >= 3 then
  8051.     file_name = cmd[3]
  8052. else
  8053.     file_name = "picture"
  8054. end if
  8055.  
  8056. in_file = open(file_name, "r")
  8057. if in_file = -1 then
  8058.     printf(1, "Can't open %s\n", {file_name})
  8059.     abort(1)
  8060. end if
  8061.  
  8062. clear_screen()
  8063. vc = video_config()
  8064. xpixels_per_char = floor(vc[VC_XPIXELS]/80)
  8065. ypixels_per_char = floor(vc[VC_YPIXELS]/25)
  8066.  
  8067. gstereo()
  8068.  
  8069. while get_key() = -1 do
  8070. end while
  8071. if graphics_mode(-1) then
  8072. end if
  8073.  
  8074. TTT.EX
  8075. 20126
  8076.         -------------------------------
  8077.         -- 3-Dimensional Tic Tac Toe --
  8078.         -------------------------------
  8079.  
  8080. -- Play 3 dimensional tic-tac-toe against one of two computer algorithms
  8081. -- or against another human -- or let the two computer algorithms play
  8082. -- each other. Which algorithm is better?
  8083.  
  8084. -- How it Works:
  8085. -- * There are two major data structures. positions describes each board 
  8086. --   position. lines describes each possible winning line of 4 positions  
  8087. --   in a row.
  8088. -- * ttt keeps a close eye on the lines data structure, looking first for
  8089. --   lines where it has 3 of the 4 positions, and the 4th is empty. If it
  8090. --   finds one of those, it wins (don't worry - it *will* always find it
  8091. --   if it's there!)
  8092. -- * If it can't win right away, it looks for lines where *you* have 3
  8093. --   positions and the 4th is empty. It will take the empty position to block
  8094. --   you.
  8095. -- * After that, it looks for various forced-win patterns for itself and
  8096. --   for you, e.g. creating two winning lines of 3 with one move.
  8097. -- * If it can't find any winning patterns, it evaluates each remaining
  8098. --   free position and assigns it a score, based on how many possibilities
  8099. --   are created by that position. This is where "DEFENDO" and "AGGRESSO"
  8100. --   differ in their strategies. AGGRESSO is more concerned with its
  8101. --   own possibilities of winning than with blocking your possibilities.
  8102.  
  8103. include graphics.e
  8104. include mouse.e
  8105. include wildcard.e
  8106.  
  8107. constant TRUE = 1, FALSE = 0
  8108. constant ON = 1, OFF = 0
  8109.  
  8110. constant COLORS = {BRIGHT_RED, BRIGHT_GREEN, YELLOW, BRIGHT_MAGENTA}
  8111.  
  8112. sequence pcolors -- colors of circular markers
  8113. pcolors = {BRIGHT_BLUE, BRIGHT_WHITE}
  8114.  
  8115. constant SQUARE_SIZE = 24
  8116.  
  8117. constant TOP_LEFT = {240, 26}
  8118.  
  8119. constant KEYB = 0, SCREEN = 1  -- I/O devices
  8120.  
  8121. constant
  8122.     NPOSITIONS = 64,  -- number of board positions
  8123.     NLINES = 76   -- number of 4-in-a-row lines
  8124.  
  8125. type line(integer x)
  8126.     return x >= 0 and x <= NLINES
  8127. end type
  8128.  
  8129. type Position(integer x)
  8130.     return x >= 0 or x <= NPOSITIONS
  8131. end type
  8132.  
  8133. type all_positions(sequence x)
  8134.     return length(x) = NPOSITIONS
  8135. end type
  8136.  
  8137. type all_lines(sequence x)
  8138.     return length(x) = NLINES
  8139. end type
  8140.  
  8141. type boolean(integer x)
  8142.     return x = TRUE or x = FALSE
  8143. end type
  8144.  
  8145. type players(sequence x)
  8146.     return length(x) = 4
  8147. end type
  8148.  
  8149. type player_number(integer x)
  8150.     return x = 1 or x = 2
  8151. end type
  8152.  
  8153. type positive_int(integer x)
  8154.     return x >= 1
  8155. end type
  8156.  
  8157. type natural(integer x)
  8158.     return x >= 0
  8159. end type
  8160.  
  8161. type human_count(integer x)
  8162.     return x >=0 and x <= 2
  8163. end type
  8164.  
  8165. type move_value(integer x)
  8166.     return integer(x) and x >= -1
  8167. end type
  8168.  
  8169. type time_delay(integer x)
  8170.     return x >= 0 and x < 1000
  8171. end type
  8172.  
  8173. type reason_number(integer x)
  8174.     return x >= 1 and x <= 10
  8175. end type
  8176.  
  8177. type three_digits(sequence x)
  8178.     return length(x) = 3
  8179. end type
  8180.  
  8181. type move_number(integer x)
  8182.     return x >= 111 and x <= 444
  8183. end type
  8184.  
  8185. all_positions positions
  8186.     -- positions is a list of all the board positions
  8187.  
  8188. constant
  8189.     -- positions 2-d sequence columns:
  8190.     LINES_THRU = 1, -- the number of lines passing through this position
  8191.     LINE1 = 2,      -- the first of up to 7 lines passing
  8192.             -- through this position
  8193.     NLIVE = 9,      -- the number of "live" lines passing through this position
  8194.     NEXTP = 10,     -- index of next position (or 0)
  8195.     PREVP = 11,     -- index of previous position (or 0)
  8196.     AVAIL = 12      -- is this position available, 1 = yes, 0 = no
  8197.  
  8198. all_lines lines     -- lines is a list of all the lines of 4 positions in a row
  8199.             -- it is indexed from 1 to NLINES
  8200.  
  8201. constant
  8202.     -- lines 2-d sequence columns:
  8203.     COUNT = 1,   -- number of "live" markers on this line
  8204.     POS1 = 2,    -- first position of 4
  8205.     POS4 = 5,    -- last position
  8206.     NEXTL = 6,   -- index of next line (or 0)
  8207.     PREVL = 7,   -- index of previous line (or 0)
  8208.     STATUS = 8,  -- status of this line
  8209.     -- possible status of a line:
  8210.     EMPTY = 0,
  8211.     COMPUTER = 1,
  8212.     HUMAN = 2,
  8213.     DEAD = 3
  8214.  
  8215. sequence lp       -- L->P format
  8216. all_positions pl  -- P->L format
  8217. sequence dbl      -- used in 3x3 check
  8218. players ptype,    -- player types
  8219.     pname     -- player names
  8220.  
  8221. line fptr,  -- free position list
  8222.      cptr,  -- computer's line list
  8223.      hptr,  -- human's line list
  8224.      eptr   -- empty line list
  8225. player_number player
  8226. natural cmoves, hmoves, l2
  8227. boolean endgame, found
  8228. human_count humans
  8229. move_value bestval
  8230. atom x
  8231.  
  8232. procedure Delay(time_delay t)
  8233. -- waste some time
  8234.     atom t0
  8235.  
  8236.     if humans = 0 and endgame = FALSE then
  8237.     return
  8238.     end if
  8239.     t0 = time()
  8240.     while time() < t0 + t/700 do
  8241.     end while
  8242. end procedure
  8243.  
  8244. procedure Why(reason_number reason)
  8245. -- show the reason why the computer made its move
  8246.     position(22, 11)
  8247.     if reason = 1 then
  8248.     puts(SCREEN, "BLOCK 3 IN A ROW")
  8249.     elsif reason = 2 then
  8250.     puts(SCREEN, "FORCE 3X3       ")
  8251.     elsif reason = 3 then
  8252.     puts(SCREEN, "FORCE 3-2-2-1   ")
  8253.     elsif reason = 4 then
  8254.     puts(SCREEN, "FORCE 3-2-2     ")
  8255.     elsif reason = 5 then
  8256.     puts(SCREEN, "PREVENT 3X3     ")
  8257.     elsif reason = 6 then
  8258.     puts(SCREEN, "PREVENT 3-2-2-1 ")
  8259.     elsif reason = 7 then
  8260.     puts(SCREEN, "PREVENT 3-2-2   ")
  8261.     elsif reason = 8 then
  8262.     printf(SCREEN, "VALUE=%d         ", bestval)
  8263.     else
  8264.     puts(SCREEN, "                ")
  8265.     end if
  8266. end procedure
  8267.  
  8268.  
  8269. function Get4th()
  8270. -- grab the final winning 4th position in a line
  8271. integer pos
  8272.     for z = POS1 to POS4 do
  8273.     pos = lines[x][z]
  8274.     if positions[lp[pos]][AVAIL] = 0 then
  8275.         return pos
  8276.     end if
  8277.     end for
  8278. end function
  8279.  
  8280.  
  8281. function Find2()
  8282. -- Find two lines that intersect where I have 2 markers on each line.
  8283. -- I can take the intersection and create two lines of 3 at once.
  8284. integer pos
  8285.     for z = POS1 to POS4 do
  8286.     pos = lines[x][z]
  8287.     if positions[lp[pos]][AVAIL] = 0 then
  8288.         dbl[l2] = pos
  8289.         l2 += 1
  8290.     end if
  8291.     end for
  8292.     if l2 < 4 then
  8293.     return 0
  8294.     end if
  8295.     for z = l2 - 2 to l2 - 1 do
  8296.     for z1 = 1 to l2 - 3 do
  8297.         if dbl[z] = dbl[z1] then
  8298.         found = TRUE
  8299.         return dbl[z]
  8300.         end if
  8301.     end for
  8302.     end for
  8303.     return 0
  8304. end function
  8305.  
  8306.  
  8307. function FindA()
  8308. -- find forcing pattern "A"
  8309. integer k, z1, line, zz
  8310.     k = 0
  8311.     for z = POS1 to POS4 do
  8312.     z1 = lp[lines[x][z]]
  8313.     for i = LINE1 to positions[z1][LINES_THRU] + 1 do
  8314.         line = positions[z1][i]
  8315.         if lines[line][STATUS] = l2 then
  8316.         if lines[line][COUNT] = 2 then
  8317.             k += 1
  8318.             exit
  8319.         end if
  8320.         end if
  8321.     end for
  8322.     if k = 3 then
  8323.         zz = z
  8324.         exit
  8325.     end if
  8326.     end for
  8327.     if k = 3 then
  8328.     found = TRUE
  8329.     return lines[x][zz]
  8330.     end if
  8331.     return 0
  8332. end function
  8333.  
  8334.  
  8335. function FindB()
  8336. -- find forcing pattern "B"
  8337. integer k, z1, line
  8338.     k = 0
  8339.     for z = POS1 to POS4 do
  8340.     z1 = lp[lines[x][z]]
  8341.     if positions[z1][AVAIL] = 0 then
  8342.         for i = LINE1 to positions[z1][LINES_THRU] + 1 do
  8343.         line = positions[z1][i]
  8344.         if lines[line][STATUS] = l2 then
  8345.             if lines[line][COUNT] = 2 then
  8346.             k += 1
  8347.             exit
  8348.             end if
  8349.         end if
  8350.         end for
  8351.         if k = 2 then
  8352.         found = TRUE
  8353.         return lines[x][z]
  8354.         end if
  8355.     end if
  8356.     end for
  8357.     return 0
  8358. end function
  8359.  
  8360.  
  8361. function FindMax()
  8362. -- find best free position
  8363. integer i, bestm
  8364.     i = fptr
  8365.     bestval = -1
  8366.     while i do
  8367.     if positions[i][NLIVE] > bestval then
  8368.         bestval = positions[i][NLIVE]
  8369.         bestm = i
  8370.     elsif positions[i][NLIVE] = bestval then
  8371.         if rand(7) = 1 then
  8372.         bestm = i
  8373.         end if
  8374.     end if
  8375.     i = positions[i][NEXTP]
  8376.     end while
  8377.     return pl[bestm]
  8378. end function
  8379.  
  8380. function mouse_square(sequence spot)
  8381. -- map x,y mouse coordinate to plane, row, column
  8382.     integer x, y
  8383.     natural m
  8384.  
  8385.     spot -= TOP_LEFT
  8386.     x = spot[1]
  8387.     y = spot[2]
  8388.     -- which plane are we on?
  8389.     m = 111
  8390.     while y > 4 * SQUARE_SIZE do
  8391.     y -= 4.5 * SQUARE_SIZE
  8392.     x -= 2.5 * SQUARE_SIZE
  8393.     m += 100
  8394.     end while
  8395.     -- which row are we on?
  8396.     while y > SQUARE_SIZE do
  8397.     y -= SQUARE_SIZE
  8398.     m += 10
  8399.     end while
  8400.     if x > 4 * SQUARE_SIZE then
  8401.     return 0 
  8402.     end if
  8403.     -- which column are we on?
  8404.     while x > SQUARE_SIZE do
  8405.     x -= SQUARE_SIZE
  8406.     m += 1
  8407.     end while
  8408.     if x < 0 or y < 0 then
  8409.     return 0
  8410.     else
  8411.     return m
  8412.     end if
  8413. end function
  8414.  
  8415.  
  8416. function GetMove()
  8417. -- get human's move via the mouse
  8418.     natural m
  8419.     object event
  8420.  
  8421.     while TRUE do
  8422.     position(20, 1)
  8423.     puts(SCREEN, repeat(' ', 30))
  8424.     position(20, 1)
  8425.     puts(SCREEN, ' ' & pname[player])
  8426.     puts(SCREEN, "'s move? ")
  8427.     event = -1
  8428.     while atom(event) do
  8429.         event = get_mouse()
  8430.         if get_key() != -1 then
  8431.         if graphics_mode(-1) then
  8432.         end if
  8433.         abort(1)
  8434.         end if
  8435.     end while
  8436.     m = mouse_square(event[2..3])
  8437.     if m >= 111 and m <= 444 then
  8438.         if lp[m] then
  8439.         if positions[lp[m]][AVAIL] = 0 then
  8440.             puts(SCREEN, repeat(' ', 30))
  8441.             exit
  8442.         end if
  8443.         end if
  8444.     end if
  8445.     end while
  8446.     return m
  8447. end function
  8448.  
  8449.  
  8450. procedure AdjValues(integer x, integer delta)
  8451. -- adjust the "value" of positions along a line
  8452. integer pos
  8453.     for z = POS1 to POS4 do
  8454.     pos = lp[lines[x][z]]
  8455.     positions[pos][NLIVE] += delta
  8456.     end for
  8457. end procedure
  8458.  
  8459.  
  8460. procedure Relink(integer player, integer x)
  8461. -- adjust some data structures after a move
  8462.     line prev, next
  8463.  
  8464.     next = lines[x][NEXTL]
  8465.     prev = lines[x][PREVL]
  8466.  
  8467.     if player = COMPUTER then
  8468.     AdjValues(x, 1)
  8469.     lines[x][NEXTL] = cptr
  8470.     lines[x][PREVL] = 0
  8471.     if cptr then
  8472.         lines[cptr][PREVL] = x
  8473.     end if
  8474.     cptr = x
  8475.     else
  8476.     lines[x][NEXTL] = hptr
  8477.     lines[x][PREVL] = 0
  8478.     if hptr then
  8479.         lines[hptr][PREVL] = x
  8480.     end if
  8481.     hptr = x
  8482.     end if
  8483.     if prev then
  8484.     lines[prev][NEXTL] = next
  8485.     if next then
  8486.         lines[next][PREVL] = prev
  8487.     end if
  8488.     else
  8489.     eptr = next
  8490.     if eptr then
  8491.         lines[eptr][PREVL] = 0
  8492.     end if
  8493.     end if
  8494. end procedure
  8495.  
  8496. function digits(natural x)
  8497. -- return the 3-digits in number x
  8498.     three_digits d
  8499.  
  8500.     d = {0, 0, 0}
  8501.     while x >= 100 do
  8502.     d[1] += 1
  8503.     x -= 100
  8504.     end while
  8505.  
  8506.     while x >= 10 do
  8507.     d[2] += 1
  8508.     x -= 10
  8509.     end while
  8510.  
  8511.     d[3] = x
  8512.     return d
  8513. end function
  8514.  
  8515.  
  8516. procedure PrintMove(move_number move)
  8517. -- print the move that was just made
  8518.     three_digits d
  8519.     integer px, py
  8520.  
  8521.     d = digits(move)
  8522.     py = (d[1] - 1) * 4.5 * SQUARE_SIZE + (d[2]-1) * SQUARE_SIZE + TOP_LEFT[2]
  8523.     px = (d[1] - 1) * 2.5 * SQUARE_SIZE + (d[3]-1) * SQUARE_SIZE + TOP_LEFT[1]
  8524.     mouse_pointer(OFF)
  8525.     for i = 1 to 3 do
  8526.     ellipse(GRAY, 1, {px+1, py+1}, 
  8527.               {px + SQUARE_SIZE - 2, py + SQUARE_SIZE - 2})
  8528.     Delay(70)
  8529.     ellipse(pcolors[player], 1, {px+1, py+1}, 
  8530.                     {px + SQUARE_SIZE - 2, py + SQUARE_SIZE - 2})
  8531.     Delay(70)
  8532.     end for
  8533.     mouse_pointer(ON)
  8534.     if endgame then
  8535.     return
  8536.     end if
  8537.     if player = COMPUTER then
  8538.     cmoves += 1
  8539.     else
  8540.     hmoves += 1
  8541.     end if
  8542. end procedure
  8543.  
  8544.  
  8545. procedure Another(line x)
  8546. -- add to the number of positions occupied by a player
  8547. -- along a line x
  8548.     integer inarow
  8549.  
  8550.     inarow = lines[x][COUNT] + 1
  8551.     lines[x][COUNT] = inarow
  8552.     if inarow < 4 then
  8553.     return
  8554.     end if
  8555.     position(21,6)
  8556.     text_color(BRIGHT_RED)
  8557.     puts(SCREEN, pname[player])
  8558.     puts(SCREEN, " WINS!          ")
  8559.     text_color(YELLOW)
  8560.     endgame = TRUE
  8561.     mouse_pointer(OFF)
  8562.     for i = 1 to 4 do
  8563.     for j = POS1 to POS4 do
  8564.         PrintMove(lines[x][j])
  8565.     end for
  8566.     Delay(80)
  8567.     end for
  8568.     mouse_pointer(ON)
  8569. end procedure
  8570.  
  8571.  
  8572. procedure Delete_c(line x)
  8573. -- delete from computer list
  8574.     line prev, next
  8575.  
  8576.     prev = lines[x][PREVL]
  8577.     next = lines[x][NEXTL]
  8578.     if prev then
  8579.     lines[prev][NEXTL] = next
  8580.     else
  8581.     cptr = next
  8582.     end if
  8583.     if next then
  8584.     lines[next][PREVL] = prev
  8585.     end if
  8586. end procedure
  8587.  
  8588.  
  8589. procedure Delete_h(line x)
  8590. -- delete from human list
  8591.     line prev, next
  8592.  
  8593.     prev = lines[x][PREVL]
  8594.     next = lines[x][NEXTL]
  8595.     if prev then
  8596.     lines[prev][NEXTL] = next
  8597.     else
  8598.     hptr = next
  8599.     end if
  8600.     if next then
  8601.     lines[next][PREVL] = prev
  8602.     end if
  8603. end procedure
  8604.  
  8605.  
  8606. procedure init()
  8607. -- initialize variables
  8608.     integer temp, u, line, t
  8609.  
  8610.     clear_screen()
  8611.     endgame = FALSE
  8612.     cmoves = 0
  8613.     hmoves = 0
  8614.     for i = 1 to NLINES do
  8615.     lines[i][STATUS] = EMPTY
  8616.     lines[i][COUNT] = 0
  8617.     end for
  8618.     for i = 1 to NPOSITIONS do
  8619.     positions[i][LINES_THRU] = 0
  8620.     positions[i][AVAIL] = 0
  8621.     end for
  8622.     line = 1
  8623.     for i = POS1 to POS4 do
  8624.     lines[line][i] = (i-1) * 111
  8625.     lines[line+1][i] = (i-1) * 109 + 5
  8626.     lines[line+2][i] = (i-1) * 91 + 50
  8627.     lines[line+3][i] = (i-1) * 89 + 55
  8628.     end for
  8629.     line += 4
  8630.     for i = 1 to 4 do
  8631.     for j = POS1 to POS4 do
  8632.         lines[line][j] = i * 100 + (j-1) * 11
  8633.         lines[line+1][j] = i * 100 + (j-1) * 9 + 5
  8634.         lines[line+2][j] = (j-1) * 101 + i * 10
  8635.         lines[line+3][j] = (j-1) * 99 + i * 10 + 5
  8636.         lines[line+4][j] = (j-1) * 110 + i
  8637.         lines[line+5][j] = (j-1) * 90 + 50 + i
  8638.     end for
  8639.     line += 6
  8640.     end for
  8641.     for i = 1 to 4 do
  8642.     for j = 1 to 4 do
  8643.         for k = POS1 to POS4 do
  8644.         t = 100 * i + 10 * j + k - 1
  8645.         u = (i - 1) * 16 + (j - 1) * 4 + k - 1
  8646.         lp[t] = u
  8647.         pl[u] = t
  8648.         lines[line][k] = t
  8649.         lines[line+1][k] = 100 * j + 10 * (k-1) + i
  8650.         lines[line+2][k] = 100 * (k-1) + 10 * i + j
  8651.         end for
  8652.         line += 3
  8653.     end for
  8654.     end for
  8655.     for i = 1 to NPOSITIONS do
  8656.     positions[i][PREVP] = i - 1
  8657.     positions[i][NEXTP] = i + 1
  8658.     end for
  8659.     positions[1][PREVP] = 0
  8660.     positions[NPOSITIONS][NEXTP] = 0
  8661.     fptr = 1
  8662.     for i = 1 to NLINES do
  8663.     lines[i][NEXTL] = i + 1
  8664.     lines[i][PREVL] = i - 1
  8665.     for j = POS1 to POS4 do
  8666.         t = lines[i][j]
  8667.         u = lp[t]
  8668.         temp = positions[u][LINES_THRU] + 1
  8669.         positions[u][LINES_THRU] = temp
  8670.         positions[u][temp+1] = i
  8671.     end for
  8672.     end for
  8673.     cptr = 0
  8674.     hptr = 0
  8675.     eptr = 0
  8676.     lines[NLINES][NEXTL] = 0
  8677.     lines[1][PREVL] = 0
  8678.     for i = 1 to NPOSITIONS do
  8679.     positions[i][NLIVE] = positions[i][LINES_THRU]
  8680.     end for
  8681.     position(15, 2)
  8682.     text_color(COLORS[1])
  8683.     puts(SCREEN, "3-D ")
  8684.     text_color(COLORS[2])
  8685.     puts(SCREEN, "tic ")
  8686.     text_color(COLORS[3])
  8687.     puts(SCREEN, "TAC ")
  8688.     text_color(COLORS[4])
  8689.     puts(SCREEN, "toe ")
  8690. end procedure
  8691.  
  8692.  
  8693. procedure UpdateMove(move_number m)
  8694. -- update data structures after making move m
  8695.     Position x1
  8696.     line x2
  8697.     integer prev, next, val, s
  8698.  
  8699.     x1 = lp[m]
  8700.     positions[x1][AVAIL] = 1
  8701.     prev = positions[x1][PREVP]
  8702.     next = positions[x1][NEXTP]
  8703.     if prev then
  8704.     positions[prev][NEXTP] = next
  8705.     if next then
  8706.         positions[next][PREVP] = prev
  8707.     end if
  8708.     else
  8709.     fptr = next
  8710.     if fptr then
  8711.         positions[fptr][PREVP] = 0
  8712.     end if
  8713.     end if
  8714.     for j = LINE1 to 1+positions[x1][LINES_THRU] do
  8715.     x2 = positions[x1][j]
  8716.     s = lines[x2][STATUS]
  8717.     if s = EMPTY then
  8718.         lines[x2][STATUS] = player
  8719.         lines[x2][COUNT] = 1
  8720.         Relink(player, x2)
  8721.     elsif s = COMPUTER then
  8722.         if player = COMPUTER then
  8723.         Another(x2)
  8724.         else
  8725.         lines[x2][STATUS] = DEAD
  8726.         AdjValues(x2, -2)
  8727.         Delete_c(x2)
  8728.         end if
  8729.     elsif s = HUMAN then
  8730.         if player = HUMAN then
  8731.         Another(x2)
  8732.         if lines[x2][COUNT] = 2 then
  8733.             val = 4
  8734.         else
  8735.             val = 0
  8736.         end if
  8737.         AdjValues(x2, val)
  8738.         else
  8739.         if lines[x2][COUNT] > 1 then
  8740.             val = -5
  8741.         else
  8742.             val = -1
  8743.         end if
  8744.         lines[x2][STATUS] = DEAD
  8745.         AdjValues(x2, val)
  8746.         Delete_h(x2)
  8747.         end if
  8748.     end if
  8749.     end for
  8750. end procedure
  8751.  
  8752.  
  8753. function Think()
  8754. -- pick the best move, return {move, reason for it}
  8755.     integer m, mymoves, myptr, me, him, hisptr, hismoves
  8756.  
  8757.     found = FALSE
  8758.     if player = COMPUTER then
  8759.     mymoves = cmoves
  8760.     hismoves = hmoves
  8761.     myptr = cptr
  8762.     hisptr = hptr
  8763.     me = COMPUTER
  8764.     him = HUMAN
  8765.     else
  8766.     mymoves = hmoves
  8767.     hismoves = cmoves
  8768.     myptr = hptr
  8769.     hisptr = cptr
  8770.     me = HUMAN
  8771.     him = COMPUTER
  8772.     end if
  8773.  
  8774.     -- Have I got 3 in a row?
  8775.     if mymoves >= 3 then
  8776.     x = myptr
  8777.     while x do
  8778.         if lines[x][COUNT] = 3 then
  8779.         return {Get4th(), 9}
  8780.         end if
  8781.         x = lines[x][NEXTL]
  8782.     end while
  8783.     end if
  8784.  
  8785.     -- Does the other guy have 3 in a row?
  8786.     if hismoves >= 3 then
  8787.     x = hisptr
  8788.     while x do
  8789.         if lines[x][COUNT] = 3 then
  8790.         return {Get4th(), 1}
  8791.         end if
  8792.         x = lines[x][NEXTL]
  8793.     end while
  8794.     end if
  8795.  
  8796.     -- Do I have a 2x2 force?
  8797.     if mymoves >= 4 then
  8798.     x = myptr
  8799.     l2 = 1
  8800.     while x do
  8801.         if lines[x][COUNT] = 2 then
  8802.         m = Find2()
  8803.         if found then
  8804.             return {m, 2}
  8805.         end if
  8806.         end if
  8807.         x = lines[x][NEXTL]
  8808.     end while
  8809.  
  8810.     -- Do I have a 3-2-2-1 force ?
  8811.     x = eptr
  8812.     l2 = me
  8813.     while x do
  8814.         m = FindA()
  8815.         if found then
  8816.         return {m, 3}
  8817.         end if
  8818.         x = lines[x][NEXTL]
  8819.     end while
  8820.  
  8821.     -- do I have a 3-2-2 force?
  8822.     if mymoves >= 5 then
  8823.         x = myptr
  8824.         while x do
  8825.         if lines[x][COUNT] = 1 then
  8826.             m = FindB()
  8827.             if found then
  8828.             return {m, 4}
  8829.             end if
  8830.         end if
  8831.         x = lines[x][NEXTL]
  8832.         end while
  8833.     end if
  8834.     end if
  8835.  
  8836.     -- does the other guy have a 2x2 force?
  8837.     if hismoves >= 4 then
  8838.     x = hisptr
  8839.     l2 = 1
  8840.     while x do
  8841.         if lines[x][COUNT] = 2 then
  8842.         m = Find2()
  8843.         if found then
  8844.             return {m, 5}
  8845.         end if
  8846.         end if
  8847.         x = lines[x][NEXTL]
  8848.     end while
  8849.  
  8850.     -- does the other guy have a 3-2-2-1 force?
  8851.     x = eptr
  8852.     l2 = him
  8853.     while x do
  8854.         m = FindA()
  8855.         if found then
  8856.         return {m, 6}
  8857.         end if
  8858.         x = lines[x][NEXTL]
  8859.     end while
  8860.  
  8861.     -- does the other guy have a 3-2-2 force?
  8862.     if hismoves >= 5 then
  8863.         x = hisptr
  8864.         while x do
  8865.         if lines[x][COUNT] = 1 then
  8866.             m = FindB()
  8867.             if found then
  8868.             return {m, 7}
  8869.             end if
  8870.         end if
  8871.         x = lines[x][NEXTL]
  8872.         end while
  8873.     end if
  8874.     end if
  8875.     -- just pick the move with the most possibilities
  8876.     return {FindMax(), 8}
  8877. end function
  8878.  
  8879.  
  8880. procedure Setup()
  8881. -- create major sequences
  8882.     object name
  8883.  
  8884.     positions = repeat(repeat(0, 12), NPOSITIONS)
  8885.     lines = repeat(repeat(0, 8), NLINES)
  8886.     lp = repeat(0, 444)
  8887.     pl = repeat(0, 64)
  8888.     dbl = repeat(0, 52)
  8889.     ptype = repeat(0, 4)
  8890.     pname = ptype
  8891.     ptype[1] = COMPUTER
  8892.     ptype[2] = COMPUTER
  8893.     pname[1] = "DEFENDO"
  8894.     pname[2] = "AGGRESSO"
  8895.     position(15, 1)
  8896.     puts(SCREEN, " Name of player 1? (cr for DEFENDO) ")
  8897.     name = gets(KEYB)
  8898.     name = name[1..length(name)-1]
  8899.     humans = 0
  8900.     if length(name) > 0 then
  8901.     pname[1] = name
  8902.     ptype[1] = HUMAN
  8903.     humans += 1
  8904.     end if
  8905.     puts(SCREEN, "\n Name of player 2? (cr for AGGRESSO) ")
  8906.     name = gets(KEYB)
  8907.     name = name[1..length(name)-1]
  8908.     if (length(name) > 0) then
  8909.     pname[2] = name
  8910.     ptype[2] = HUMAN
  8911.     humans += 1
  8912.     end if
  8913. end procedure
  8914.  
  8915. procedure draw_plane(integer color, integer x, integer y)
  8916. -- draw one plane of the board
  8917.      for i = 0 to 4 do
  8918.     draw_line(color, {{x, y+i*SQUARE_SIZE}, 
  8919.               {x+4*SQUARE_SIZE, y+i*SQUARE_SIZE}})
  8920.      end for
  8921.      for i = 0 to 4 do
  8922.     draw_line(color, {{x+i*SQUARE_SIZE, y},
  8923.               {x+i*SQUARE_SIZE, y+4*SQUARE_SIZE}})
  8924.      end for
  8925. end procedure
  8926.  
  8927. procedure make_board(sequence top_left)
  8928. -- display the board
  8929.     bk_color(8)
  8930.     for i = 0 to 3 do
  8931.     draw_plane(COLORS[i+1], top_left[1]+2.5*SQUARE_SIZE*i, 
  8932.                 top_left[2]+4.5*SQUARE_SIZE*i)
  8933.     end for
  8934. end procedure
  8935.  
  8936. procedure ttt()
  8937. -- this is the main routine
  8938.     sequence m
  8939.  
  8940.     Setup()
  8941.     player = rand(2) -- first game is random 
  8942.              -- loser goes first in subsequent games
  8943.     while TRUE do
  8944.     mouse_pointer(OFF)
  8945.     init()
  8946.     make_board(TOP_LEFT)
  8947.     mouse_pointer(ON)
  8948.     text_color(YELLOW)
  8949.     mouse_events(LEFT_DOWN)
  8950.     while endgame = FALSE do
  8951.         if fptr then
  8952.         if ptype[player] = HUMAN then
  8953.             m = {GetMove()}
  8954.         else
  8955.             m = Think()
  8956.             Why(m[2])
  8957.         end if
  8958.         PrintMove(m[1])
  8959.         UpdateMove(m[1])
  8960.         player = 3 - player
  8961.         else
  8962.         position(18,1)
  8963.         puts(SCREEN, " A DRAW             ")
  8964.         Delay(500)
  8965.         exit
  8966.         end if
  8967.     end while
  8968.     position(19, 1)
  8969.     text_color(BRIGHT_MAGENTA)
  8970.     puts(SCREEN, " Another game? (y or n) ")
  8971.     text_color(YELLOW)
  8972.     if not find('y', lower(gets(KEYB))) then
  8973.         exit
  8974.     end if
  8975.     end while
  8976. end procedure
  8977.  
  8978. if graphics_mode(18) then -- VGA
  8979.     puts(1, "VGA graphics is required\n")
  8980. else
  8981.     ttt()
  8982. end if
  8983.  
  8984. if graphics_mode(-1) then
  8985. end if
  8986.  
  8987. WIRE.EX
  8988. 8163
  8989.         ----------------------------
  8990.         -- 3-D Wire Frame Picture --
  8991.         ----------------------------
  8992. -- Hit space bar to freeze/restart the picture.
  8993. -- Any other key to quit.
  8994.  
  8995. without type_check
  8996.  
  8997. include graphics.e
  8998. include select.e
  8999.  
  9000. constant GRAPHICS_MODE = 261  -- SVGA, N.B. If this fails try mode 18.
  9001.  
  9002. constant X = 1, Y = 2, Z = 3
  9003. constant TRUE = 1
  9004. constant SCREEN = 1
  9005. constant ANY_MODE_WHITE = 255
  9006.  
  9007. type point(sequence x)
  9008.     return length(x) = 3
  9009. end type
  9010.  
  9011. type matrix(sequence x)
  9012.     return length(x) = 4 and sequence(x[1])
  9013. end type
  9014.  
  9015. type vector(sequence x)
  9016.     return length(x) = 4 and atom(x[1])
  9017. end type
  9018.  
  9019. integer axis
  9020. atom sin_angle, cos_angle
  9021.  
  9022. function product(sequence factor)
  9023. -- matrix multiply a number of 4-vectors/4x4 matrices
  9024. -- only the first one could be a vector
  9025.     sequence a, c
  9026.     matrix b
  9027.  
  9028.     a = factor[1]
  9029.     for f = 2 to length(factor) do
  9030.     b = factor[f]
  9031.     if atom(a[1]) then
  9032.         -- a is a vector
  9033.         c = repeat(0, 4)
  9034.         for j = 1 to 4 do
  9035.         c[j] = a[1] * b[1][j] +
  9036.                a[2] * b[2][j] +
  9037.                a[3] * b[3][j] +
  9038.                a[4] * b[4][j]
  9039.         end for
  9040.     else
  9041.         -- a is a matrix
  9042.         c = repeat(repeat(0, 4), 4)
  9043.         for i = 1 to 4 do
  9044.         for j = 1 to 4 do
  9045.             for k = 1 to 4 do
  9046.             c[i][j] += a[i][k] * b[k][j]
  9047.             end for
  9048.         end for
  9049.         end for
  9050.     end if
  9051.     a = c
  9052.     end for
  9053.     return c
  9054. end function
  9055.  
  9056. sequence vc -- video configuration
  9057.  
  9058. procedure display(sequence old_coords, sequence coords)
  9059. -- erase the old lines, draw the new ones
  9060.     for i = 1 to length(old_coords) do
  9061.     draw_line(BLACK, old_coords[i][1..2])
  9062.     end for
  9063.     for i = 1 to length(coords) do
  9064.     if vc[VC_COLOR] then
  9065.         draw_line(coords[i][3], coords[i][1..2])
  9066.     else
  9067.         draw_line(ANY_MODE_WHITE, coords[i][1..2])
  9068.     end if
  9069.     end for
  9070. end procedure
  9071.  
  9072. function view(point view_point)
  9073. -- compute initial view
  9074.     matrix t1, t2, t3, t4, n
  9075.     atom cos_theta, sin_theta, hyp, a_b
  9076.  
  9077.     -- change origin
  9078.     t1 = {{1, 0, 0, 0},
  9079.       {0, 1, 0, 0},
  9080.       {0, 0, 1, 0},
  9081.       -view_point & 1}
  9082.  
  9083.     -- get left-handed coordinate system
  9084.     t2 = {{-1, 0,  0, 0},
  9085.       { 0, 0, -1, 0},
  9086.       { 0, 1,  0, 0},
  9087.       { 0, 0,  0, 1}}
  9088.  
  9089.     -- rotate so Ze points properly
  9090.     hyp = sqrt(view_point[1] * view_point[1] + view_point[2] * view_point[2])
  9091.     sin_theta = view_point[1] / hyp
  9092.     cos_theta = view_point[2] / hyp
  9093.     t3 = {{cos_theta, 0, sin_theta, 0},
  9094.       {        0, 1,         0, 0},
  9095.       {-sin_theta,0, cos_theta, 0},
  9096.       {        0, 0,         0, 1}}
  9097.  
  9098.     -- rotate so Ze points at the origin (0, 0, 0)
  9099.     t4 = {{1, 0, 0, 0},
  9100.       {0, cos_theta, -sin_theta, 0},
  9101.       {0, sin_theta, cos_theta, 0},
  9102.       {0, 0, 0, 1}}
  9103.  
  9104.     a_b = 2
  9105.  
  9106.     n = {{a_b, 0, 0, 0},
  9107.      {0, a_b, 0, 0},
  9108.      {0, 0, 1, 0},
  9109.      {0, 0, 0, 1}}
  9110.  
  9111.     return product({t1, t2, t3, t4, n})
  9112. end function
  9113.  
  9114. function new_coords(sequence overall, sequence shape)
  9115. -- compute the screen coordinates from the 3-D coordinates
  9116.     sequence screen_coords, final
  9117.     point p
  9118.     atom x2, y2
  9119.  
  9120.     x2 = vc[VC_XPIXELS]/2
  9121.     y2 = vc[VC_YPIXELS]/2
  9122.     screen_coords = repeat({0, 0, 0}, length(shape))
  9123.     for i = 1 to length(shape) do
  9124.     for j = 1 to 2  do
  9125.         p = shape[i][j]
  9126.         final = product({p & 1, overall})
  9127.         screen_coords[i][j] = {x2*(final[X]/final[Z]+1),
  9128.                    y2*(final[Y]/final[Z]+1)}
  9129.     end for
  9130.     screen_coords[i][3] = shape[i][3]
  9131.     end for
  9132.     return screen_coords
  9133. end function
  9134.  
  9135. function x_rotate(point p)
  9136. -- compute x rotation of a point
  9137.     return {p[X],
  9138.         p[Y] * cos_angle + p[Z] * sin_angle,
  9139.         p[Z] * cos_angle - p[Y] * sin_angle}
  9140. end function
  9141.  
  9142. function y_rotate(point p)
  9143. -- compute y rotation of a point
  9144.     return {p[X] * cos_angle - p[Z] * sin_angle,
  9145.         p[Y],
  9146.         p[X] * sin_angle + p[Z] * cos_angle}
  9147. end function
  9148.  
  9149. function z_rotate(point p)
  9150. -- compute z rotation matrix
  9151.     return {p[X] * cos_angle + p[Y] * sin_angle,
  9152.         p[Y] * cos_angle - p[X] * sin_angle,
  9153.         p[Z]}
  9154. end function
  9155.  
  9156. function compute_rotate(integer axis, sequence shape)
  9157. -- rotate a shape
  9158.     for i = 1 to length(shape) do
  9159.     for j = 1 to 2 do
  9160.         if axis = X then
  9161.         shape[i][j] = x_rotate(shape[i][j])
  9162.         elsif axis = Y then
  9163.         shape[i][j] = y_rotate(shape[i][j])
  9164.         else
  9165.         shape[i][j] = z_rotate(shape[i][j])
  9166.         end if
  9167.     end for
  9168.     end for
  9169.     return shape
  9170. end function
  9171.  
  9172. -- lines for a block E
  9173. constant E = {
  9174. {{.2, 1.1, 2}, {.2, -.5, 2}, BLUE},
  9175. {{.2, -.5, 2}, {.2, -.5, -2}, YELLOW},
  9176. {{.2, -.5, -2}, {.2, 1.1, -2}, GREEN},
  9177. {{.2, 1.1, -2}, {.2, 1.2, -1.6}, BRIGHT_RED},
  9178. {{.2, 1.2, -1.6}, {.2, 1, -1.8}, BRIGHT_RED},
  9179. {{.2, 1, -1.8}, {.2, 0, -1.8}, MAGENTA},
  9180. {{.2, 0, -1.8}, {.2, 0, -.1}, BRIGHT_CYAN},
  9181. {{.2, 0, -.1}, {.2, .5, -.1}, BLUE},
  9182. {{.2, .5, -.1}, {.2, .6, -.2}, BLUE},
  9183. {{.2, .6, -.2}, {.2, .6, .2}, ANY_MODE_WHITE},
  9184. {{.2, .6, .2}, {.2, .5, .1}, BLUE},
  9185. {{.2, .5, .1}, {.2, 0, .1}, BRIGHT_BLUE},
  9186. {{.2, 0, .1}, {.2, 0, 1.8}, BRIGHT_GREEN},
  9187. {{.2, 0, 1.8}, {.2, 1, 1.8}, BRIGHT_CYAN},
  9188. {{.2, 1, 1.8}, {.2, 1.2, 1.6}, BRIGHT_CYAN},
  9189. {{.2, 1.2, 1.6}, {.2, 1.1, 2}, BRIGHT_RED},
  9190.  
  9191. -- opposite side:
  9192. {{-.2, 1.1, 2}, {-.2, -.5, 2}, BLUE},
  9193. {{-.2, -.5, 2}, {-.2, -.5, -2}, YELLOW},
  9194. {{-.2, -.5, -2}, {-.2, 1.1, -2}, GREEN},
  9195. {{-.2, 1.1, -2}, {-.2, 1.2, -1.6}, BRIGHT_RED},
  9196. {{-.2, 1.2, -1.6}, {-.2, 1, -1.8}, BRIGHT_RED},
  9197. {{-.2, 1, -1.8}, {-.2, 0, -1.8}, MAGENTA},
  9198. {{-.2, 0, -1.8}, {-.2, 0, -.1}, BRIGHT_CYAN},
  9199. {{-.2, 0, -.1}, {-.2, .5, -.1}, BLUE},
  9200. {{-.2, .5, -.1}, {-.2, .6, -.2}, BLUE},
  9201. {{-.2, .6, -.2}, {-.2, .6, .2}, ANY_MODE_WHITE},
  9202. {{-.2, .6, .2}, {-.2, .5, .1}, BLUE},
  9203. {{-.2, .5, .1}, {-.2, 0, .1}, BRIGHT_BLUE},
  9204. {{-.2, 0, .1}, {-.2, 0, 1.8}, BRIGHT_GREEN},
  9205. {{-.2, 0, 1.8}, {-.2, 1, 1.8}, BRIGHT_CYAN},
  9206. {{-.2, 1, 1.8}, {-.2, 1.2, 1.6}, BRIGHT_CYAN},
  9207. {{-.2, 1.2, 1.6}, {-.2, 1.1, 2}, BRIGHT_RED},
  9208.  
  9209. -- cross pieces:
  9210. {{.2, 1.1, 2}, {-.2, 1.1, 2}, BLUE},
  9211. {{.2, -.5, 2}, {-.2, -.5, 2}, BLUE},
  9212. {{.2, -.5, -2}, {-.2, -.5, -2}, GREEN},
  9213. {{.2, 1.1, -2}, {-.2, 1.1, -2}, GREEN},
  9214. {{.2, 1.2, -1.6}, {-.2, 1.2, -1.6}, BRIGHT_GREEN},
  9215. {{.2, .6, -.2}, {-.2, .6, -.2}, ANY_MODE_WHITE},
  9216. {{.2, .6, .2}, {-.2, .6, .2}, ANY_MODE_WHITE},
  9217. {{.2, 1.2, 1.6}, {-.2, 1.2, 1.6}, BRIGHT_GREEN}
  9218. }
  9219.  
  9220. procedure spin(sequence shape)
  9221. -- spin a 3-D shape around on the screen in interesting ways
  9222.     sequence history, coords, overall
  9223.     point view_point
  9224.     integer spread, r, c
  9225.     atom rot_speed
  9226.  
  9227.     view_point = {6, 8, 7.5} / 2.2
  9228.     overall = view(view_point)
  9229.     rot_speed = 0.09
  9230.     sin_angle = sin(rot_speed)
  9231.     cos_angle = cos(rot_speed)
  9232.     axis = Z
  9233.     history = {}
  9234.     spread = 0
  9235.     while TRUE do
  9236.     coords = new_coords(overall, shape)
  9237.     if length(history) > spread then
  9238.         display(history[1], coords)
  9239.         history = history[2..length(history)]
  9240.         if length(history) > spread then
  9241.         display(history[1], {})
  9242.         history = history[2..length(history)]
  9243.         end if
  9244.     else
  9245.         display({}, coords)
  9246.     end if
  9247.     history = append(history, coords)
  9248.     c = get_key()
  9249.     if c != -1 then
  9250.         if c = ' ' then
  9251.         while TRUE do
  9252.             c = get_key()
  9253.             if c != -1 and c != ' ' then
  9254.             return
  9255.             elsif c = ' ' then
  9256.             exit
  9257.             end if
  9258.         end while
  9259.         else
  9260.         return
  9261.         end if
  9262.     end if
  9263.     r = rand(250)
  9264.     if r = 1 then
  9265.         axis = X
  9266.     elsif r = 2 then
  9267.         axis = Y
  9268.     elsif r = 3 then
  9269.         axis = Z
  9270.     elsif r = 4 then
  9271.         spread = 5 * rand(25)  -- leave behind many trailing wire images
  9272.     elsif r = 5 or r = 6 then
  9273.         spread = 0             -- reduce the images back to a sharp picture
  9274.     elsif r = 7 then
  9275.         if rand(2) = 1 then
  9276.         rot_speed = .04
  9277.         spread = 0
  9278.         else
  9279.         rot_speed = .02 * rand(10)
  9280.         end if
  9281.         sin_angle = sin(rot_speed)
  9282.         cos_angle = cos(rot_speed)
  9283.     end if
  9284.     shape = compute_rotate(axis, shape)
  9285.     end while
  9286. end procedure
  9287.  
  9288. -- execution starts here:
  9289. if not select_mode(GRAPHICS_MODE) then
  9290.     puts(SCREEN, "can't find a good graphics mode\n")
  9291. else
  9292.     vc = video_config()
  9293.     bk_color(7)
  9294.     text_color(5)
  9295.     clear_screen()
  9296.     spin(E)
  9297.     bk_color(0)
  9298.     if graphics_mode(-1) then
  9299.     -- we do this just to ignore the result of graphics_mode(-1)
  9300.     end if
  9301. end if
  9302.  
  9303. HASH.EX
  9304. 5170
  9305. -- Hash Table Demo
  9306. -- written by Junko C. Miura, RDS
  9307. -- This reads standard input and builds a hash table containing all of 
  9308. -- the unique words plus a count of how many times each word occurred.
  9309. -- It outputs the words to standard output and writes a bunch of hash table 
  9310. -- statistics to "hash.out".
  9311.  
  9312. -- example: 
  9313. --          ex hash < \euphoria\doc\library.doc
  9314. --
  9315. -- You can direct standard output to a file with '>'
  9316. -- hash.ex (hash table) is faster than tree.ex (binary tree),
  9317. -- but does not produce a sorted list of words.
  9318.  
  9319. -- How it Works:
  9320. -- * hashing is generally much faster than searching a long linear list for a 
  9321. --   word. Instead of searching one big list, we create hundreds of small
  9322. --   lists, and then use a "hash function" to tell us which small list (or
  9323. --   "bucket") to search. For each word, the hash function will return an 
  9324. --   integer. For a given word, the hash function must always return the same 
  9325. --   integer. That integer is used as the index into a sequence of small 
  9326. --   word-lists. We can quickly search the selected small list for the word.
  9327.  
  9328. without type_check
  9329.  
  9330. constant EOF = -1
  9331. constant STANDARD_IN = 0, STANDARD_OUT = 1, SCREEN = 2 
  9332. constant TRUE = 1
  9333. constant STRING = 1, COUNT = 2 -- fields for one hash table entry
  9334.  
  9335. constant HASH_BUCKETS = 1009  -- prime
  9336.     -- With the hash function below, it helps (a little bit) 
  9337.     -- to have a prime number here. Don't use a power of 2.
  9338.     -- You'll get better performance by using a
  9339.     -- bigger size of table, but it wastes space.
  9340.  
  9341. -- Initialize the hash table to a sequence of empty "buckets"
  9342. sequence hash_table
  9343. hash_table = repeat({}, HASH_BUCKETS)
  9344.  
  9345. integer compares
  9346. compares = 0
  9347.  
  9348. function hash_function(sequence string)
  9349. -- This function works well for English words.
  9350. -- It's fast to calculate and it gives a pretty even distribution.
  9351. -- These are the two properties that you want in a hash function.
  9352.     integer len
  9353.     atom val
  9354.     
  9355.     len = length(string)
  9356.     val = string[len]
  9357.     if len > 4 then
  9358.     len = 4
  9359.     end if
  9360.     for i = 1 to len - 1 do
  9361.     val = val * 64 + string[i]  -- shift 6 bits and add
  9362.     end for
  9363.     return remainder(val, HASH_BUCKETS) + 1
  9364. end function
  9365.  
  9366. procedure hash_add(sequence string)
  9367. -- If string is not in the table already, add it, with a count of 1, 
  9368. -- otherwise just increment its count.
  9369.     integer hash_val, found
  9370.     sequence bucket
  9371.     
  9372.     -- which bucket to search?
  9373.     hash_val = hash_function(string) 
  9374.     bucket = hash_table[hash_val]
  9375.     found = 0
  9376.     -- search this bucket for the string
  9377.     for i = 1 to length(bucket) do
  9378.     compares += 1
  9379.     if equal(string, bucket[i][STRING]) then
  9380.         -- found it
  9381.         found = i
  9382.         exit
  9383.     end if
  9384.     end for
  9385.     if found then
  9386.     -- increment count
  9387.     bucket[found][COUNT] += 1
  9388.     else
  9389.     -- add new string with count 1:
  9390.     bucket = append(bucket, {string, 1})
  9391.     end if
  9392.     hash_table[hash_val] = bucket
  9393. end procedure
  9394.  
  9395. function next_word()
  9396. -- Read standard input to get the next "word".
  9397.     integer c
  9398.     sequence word
  9399.  
  9400.     word = ""
  9401.     while TRUE do
  9402.     c = getc(STANDARD_IN)
  9403.     if (c >= 'a' and c <= 'z') then
  9404.         word &= c
  9405.     elsif (c >= 'A' and c <= 'Z') then
  9406.         word &= c
  9407.     elsif length(word) > 0 then
  9408.         return word
  9409.     elsif c = EOF then
  9410.         return 0
  9411.     end if
  9412.     end while
  9413. end function
  9414.  
  9415. procedure build_table()
  9416. -- build a hash table containing all unique words in standard input
  9417.     object word
  9418.  
  9419.     while TRUE do 
  9420.     word = next_word() 
  9421.     if atom(word) then
  9422.         exit
  9423.     else
  9424.         hash_add(word)
  9425.     end if
  9426.     end while
  9427. end procedure
  9428.  
  9429. puts(SCREEN, "terminate typed input with: control-Z Enter\n")
  9430.  
  9431. atom t
  9432. t = time()         -- Time the table-building process only
  9433. build_table() 
  9434. t = time() - t     -- stop timer
  9435.  
  9436.  
  9437. ---------------- Statistics ------------------
  9438. integer numZeroBucket, max, items, len, stats, total_words
  9439.  
  9440. stats = open("hash.out", "w")
  9441. if stats = -1 then
  9442.     puts(SCREEN, "Couldn't open output file\n")
  9443.     abort(1)
  9444. end if
  9445. printf(stats, "time: %.2f\n", t)
  9446. numZeroBucket = 0
  9447. items = 0
  9448. max = 0
  9449. total_words = 0
  9450. for i = 1 to length(hash_table) do
  9451.     len = length(hash_table[i])
  9452.     items += len
  9453.     if len = 0 then
  9454.     numZeroBucket += 1
  9455.     else
  9456.     -- calculate total compares required to lookup all words again
  9457.     for j = 1 to length(hash_table[i]) do
  9458.         total_words +=  hash_table[i][j][COUNT]
  9459.     end for
  9460.     if len > max then
  9461.         max = len
  9462.     end if
  9463.     end if
  9464. end for
  9465.  
  9466. printf(stats, "number of hash table buckets     : %d\n", HASH_BUCKETS)
  9467. printf(stats, "number of words in input stream  : %d\n", total_words)
  9468. printf(stats, "number of items in hash table    : %d\n", items)
  9469. printf(stats, "number of empty buckets          : %d\n", numZeroBucket)
  9470. printf(stats, "largest bucket                   : %d\n", max)
  9471. printf(stats, "compares per lookup              : %.2f\n", 
  9472.            compares/total_words)
  9473.  
  9474. for i = 1 to length(hash_table) do
  9475.     printf(stats, "\nbucket#%d: ", i)
  9476.     for j = 1 to length(hash_table[i]) do
  9477.     printf(stats, "%s:%d ", hash_table[i][j])
  9478.     printf(STANDARD_OUT, "%s:%d\n", hash_table[i][j])
  9479.     if remainder(j,5) = 0 then
  9480.         puts(stats, '\n')
  9481.     end if
  9482.     end for
  9483.     if remainder(length(hash_table[i]), 5) then
  9484.     puts(stats, '\n')
  9485.     end if
  9486. end for
  9487.  
  9488. printf(SCREEN, "\n%.2f seconds\n", t)
  9489.  
  9490.  
  9491. COMMANDS.E
  9492. 8432
  9493. -- commands.e
  9494. -- process user commands
  9495.  
  9496. constant ESC = 27
  9497.  
  9498. type keycode(integer x)  
  9499. -- a keyboard code
  9500.     return x >= -1 and x < 512
  9501. end type
  9502.  
  9503. natural nchars
  9504. nchars = 0
  9505.  
  9506. natural pen
  9507.  
  9508. keycode curcom
  9509.  
  9510. direction wdir -- weapons direction
  9511.  
  9512. integer dir_adjust
  9513.  
  9514. type digit_char(integer x)
  9515.     return (x >= '0' and x <= '9')
  9516. end type
  9517.  
  9518. global procedure quit()
  9519. -- end the game and tidy up the screen
  9520.     sound(0)
  9521.     if graphics_mode(-1) then
  9522.     end if
  9523.     abort(0)
  9524. end procedure
  9525.  
  9526. procedure echo(char com)
  9527. -- echo first char of new command
  9528.     set_bk_color(WHITE)
  9529.     set_color(BLUE)
  9530.     position(CMD_LINE, CMD_POS)
  9531.     console_puts(com)
  9532.     console_puts("         ")
  9533.     position(CMD_LINE, CMD_POS + 2)
  9534. end procedure
  9535.  
  9536. procedure dircom(digit_char d)
  9537. -- process direction change commands
  9538.     nchars = 0
  9539.     if reptime[GUIDANCE] then
  9540.     errbeep()
  9541.     msg("GUIDANCE SYSTEM DAMAGED")
  9542.     return
  9543.     end if
  9544.  
  9545.     if d = '9' then
  9546.     d = '1'
  9547.     elsif d = '0' then
  9548.     d = '8'
  9549.     end if  
  9550.  
  9551.     echo(d)
  9552.     curdir = d - '0'
  9553.     dir_box()
  9554.  
  9555.     if d = '1' then
  9556.     exi = 1
  9557.     eyi = 0
  9558.     esym = esymr
  9559.     elsif d = '2' then
  9560.     exi = 1
  9561.     eyi = -1
  9562.     esym = esymr
  9563.     elsif d = '3' then
  9564.     exi = 0
  9565.     eyi = -1
  9566.     elsif d = '4' then
  9567.     exi = -1
  9568.     eyi = -1
  9569.     esym = esyml
  9570.     elsif d = '5' then
  9571.     exi = -1
  9572.     eyi = 0
  9573.     esym = esyml
  9574.     elsif d = '6' then
  9575.     exi = -1
  9576.     eyi = 1
  9577.     esym = esyml
  9578.     elsif d = '7' then
  9579.     exi = 0
  9580.     eyi = 1
  9581.     elsif d = '8' then
  9582.     exi = 1
  9583.     eyi = 1
  9584.     esym = esymr
  9585.     end if
  9586. end procedure
  9587.  
  9588. function docom(keycode com, keycode chr)
  9589. -- process commands
  9590.     natural t
  9591.     positive_atom t_stop
  9592.  
  9593.     set_bk_color(WHITE)
  9594.     set_color(BLUE)
  9595.     if com = 'p' then      -- phasor
  9596.     if nchars = 0 then
  9597.         dir_adjust = ' '
  9598.         echo(chr)
  9599.         set_color(BLUE)
  9600.         console_puts('_')
  9601.         set_color(BLUE)
  9602.         console_puts("00 _._ ")
  9603.         nchars = 1
  9604.     elsif nchars = 1 then
  9605.         position(CMD_LINE, CMD_POS+2)
  9606.         pen = 100 * (chr - '0')
  9607.         console_puts(chr)
  9608.         position(CMD_LINE, CMD_POS+6)
  9609.         set_color(BLUE)
  9610.         console_puts('_')
  9611.         nchars = 2
  9612.     elsif nchars = 2 then
  9613.         if chr = '<' or chr = '>' then
  9614.         dir_adjust = chr
  9615.         position(CMD_LINE, CMD_POS+5)
  9616.         console_puts(chr)
  9617.         else
  9618.         position(CMD_LINE, CMD_POS+6)
  9619.         if chr = '0' then
  9620.             chr = '8'
  9621.         elsif chr = '9' then
  9622.             chr = '1'
  9623.         end if
  9624.         console_puts(chr)
  9625.         position(CMD_LINE, CMD_POS+8)
  9626.         set_color(BLUE)
  9627.         console_puts('_')
  9628.         wdir = chr - '0'
  9629.         nchars = 3
  9630.         end if
  9631.     else
  9632.         -- nchars is 3 or 4
  9633.         if (chr = '<' or chr = '>') then
  9634.         if nchars = 3 then
  9635.             dir_adjust = chr
  9636.             position(CMD_LINE, CMD_POS+8)
  9637.             console_puts(chr)
  9638.             nchars += 1
  9639.         end if
  9640.         else
  9641.         position(CMD_LINE, CMD_POS+5+nchars)
  9642.         console_puts(chr)
  9643.         if reptime[PHASORS] then
  9644.             errbeep()
  9645.             msg("PHASORS DAMAGED")
  9646.         elsif quadrant[EUPHORIA][Q_EN] <= pen then
  9647.             errbeep()
  9648.             msg("NOT ENOUGH ENERGY")
  9649.         else
  9650.             wdir += (chr - '0')/10
  9651.             p_energy(-pen)
  9652.             esetpt(wdir, dir_adjust)
  9653.             phasor(EUPHORIA, pen)
  9654.         end if
  9655.         nchars = 0
  9656.         end if
  9657.     end if
  9658.  
  9659.     elsif com = 'w' then    -- warp change
  9660.     if nchars = 0 then
  9661.         echo(chr)
  9662.         nchars = 1
  9663.         set_color(BLUE)
  9664.         console_puts('_')
  9665.     else
  9666.         if chr < '6' then
  9667.         position(CMD_LINE, CMD_POS+2)
  9668.         console_puts(chr)
  9669.         nchars = 0
  9670.         if wlimit then
  9671.             setwarp(chr - '0')
  9672.         else
  9673.             errbeep()
  9674.             msg("ALL ENGINES DAMAGED")
  9675.         end if
  9676.         end if
  9677.     end if
  9678.  
  9679.     elsif com = 't' then    -- torpedo
  9680.     if nchars = 0 then
  9681.         dir_adjust = ' '
  9682.         echo(chr)
  9683.         nchars = 1
  9684.         set_color(BLUE)
  9685.         console_puts('_')
  9686.         set_color(BLUE)
  9687.         console_puts("._")
  9688.     elsif nchars = 1 then
  9689.         if chr = '<' or chr = '>' then
  9690.         dir_adjust = chr
  9691.         position(CMD_LINE, CMD_POS+1)
  9692.         console_puts(chr)
  9693.         else
  9694.         position(CMD_LINE, CMD_POS+2)
  9695.         if chr = '0' then
  9696.             chr = '8'
  9697.         elsif chr = '9' then
  9698.             chr = '1'
  9699.         end if
  9700.         console_puts(chr)
  9701.         position(CMD_LINE, CMD_POS+4)
  9702.         set_color(BLUE)
  9703.         console_puts('_')
  9704.         wdir = chr - '0'
  9705.         nchars = 2
  9706.         end if
  9707.     else
  9708.         -- nchars is 2 or 3
  9709.         if (chr = '<' or chr = '>') then
  9710.         if nchars = 2 then
  9711.             dir_adjust = chr
  9712.             position(CMD_LINE, CMD_POS+4)
  9713.             console_puts(chr)
  9714.             nchars += 1
  9715.         end if
  9716.         else
  9717.         position(CMD_LINE, CMD_POS+2+nchars)
  9718.         console_puts(chr)
  9719.         wdir += (chr - '0')/10
  9720.         if reptime[TORPEDOS] then
  9721.             errbeep()
  9722.             msg("TORPEDO LAUNCHER DAMAGED")
  9723.         else
  9724.             t = quadrant[EUPHORIA][Q_TORP]
  9725.             if t then
  9726.             t -= 1
  9727.             quadrant[EUPHORIA][Q_TORP] = t
  9728.             ts = ts[2..length(ts)]
  9729.             wtext()
  9730.             esetpt(wdir, dir_adjust)
  9731.             torpedo(EUPHORIA)
  9732.             else
  9733.             errbeep()
  9734.             msg("OUT OF TORPEDOS")
  9735.             end if
  9736.         end if
  9737.         nchars = 0
  9738.         end if
  9739.     end if
  9740.  
  9741.     elsif com = 'g' then    -- galaxy scan
  9742.     echo(chr)
  9743.     if scanon then
  9744.         end_scan()
  9745.     else
  9746.         if reptime[GALAXY_SENSORS] then
  9747.         errbeep()
  9748.         msg("SENSORS DAMAGED")
  9749.         else
  9750.         BlueScreen()
  9751.         scanon = TRUE
  9752.         refresh_scan()
  9753.         gtext()
  9754.         gsbox(qrow, qcol)
  9755.         schedule(t_gquad, 0.4, 0.4, 0.06, {})
  9756.         end if
  9757.     end if
  9758.     nchars = 0
  9759.  
  9760.     elsif com = 13 then
  9761.     EnterPressed = TRUE
  9762.     
  9763.     elsif com = 'a' then   -- antimatter pod
  9764.     if nchars = 0 then
  9765.         dir_adjust = ' '
  9766.         echo(chr)
  9767.         nchars = 1
  9768.         set_color(BLUE)
  9769.         console_puts('_')
  9770.         set_color(BLUE)
  9771.         console_puts("._")
  9772.     elsif nchars = 1 then
  9773.         if chr = '<' or chr = '>' then
  9774.         dir_adjust = chr
  9775.         position(CMD_LINE, CMD_POS+1)
  9776.         console_puts(chr)
  9777.         else
  9778.         position(CMD_LINE, CMD_POS+2)
  9779.         if chr = '0' then
  9780.             chr = '8'
  9781.         elsif chr = '9' then
  9782.             chr = '1'
  9783.         end if
  9784.         console_puts(chr)
  9785.         position(CMD_LINE, CMD_POS+4)
  9786.         set_color(BLUE)
  9787.         console_puts('_')
  9788.         wdir = chr - '0'
  9789.         nchars = 2
  9790.         end if
  9791.     else
  9792.         -- nchars is 2 or 3
  9793.         if (chr = '<' or chr = '>') then
  9794.         if nchars = 2 then
  9795.             dir_adjust = chr
  9796.             position(CMD_LINE, CMD_POS+4)
  9797.             console_puts(chr)
  9798.             nchars += 1
  9799.         end if
  9800.         else
  9801.         position(CMD_LINE, CMD_POS+2+nchars)
  9802.         console_puts(chr)
  9803.         if length(ps) > 0 then
  9804.             wdir += (chr - '0')/10
  9805.             ps = ps[2..length(ps)]
  9806.             wtext()
  9807.             esetpt(wdir, dir_adjust)
  9808.             EnterPressed = FALSE
  9809.             pod()
  9810.         else
  9811.             errbeep()
  9812.             msg("OUT OF PODS")
  9813.         end if
  9814.         nchars = 0
  9815.         end if
  9816.     end if
  9817.  
  9818.     elsif com = 's' then   -- shuttlecraft
  9819.     echo(chr)
  9820.     if not shuttle then
  9821.         if equal(esym[1], esymr[1]) then
  9822.         esym = SHUTTLE_R
  9823.         else
  9824.         esym = SHUTTLE_L
  9825.         end if
  9826.         esyml = SHUTTLE_L
  9827.         esymr = SHUTTLE_R
  9828.         otype[G_EU] = "SHUTTLE"
  9829.         oshape[G_EU] = {SHUTTLE_L, SHUTTLE_R}
  9830.         write_screen(quadrant[EUPHORIA][Q_X], 
  9831.              quadrant[EUPHORIA][Q_Y], quadrant[EUPHORIA][Q_UNDER])
  9832.         quadrant[EUPHORIA][Q_UNDER] = read_screen(quadrant[EUPHORIA][Q_X],
  9833.                               quadrant[EUPHORIA][Q_Y],
  9834.                               esym)
  9835.         write_screen(quadrant[EUPHORIA][Q_X], 
  9836.              quadrant[EUPHORIA][Q_Y], esym)
  9837.         for r = 1 to NSYS do
  9838.         if reptime[r] then
  9839.             reptime[r] = 0
  9840.             repair(r)
  9841.         end if
  9842.         end for
  9843.         quadrant[EUPHORIA][Q_DEFL] = 1
  9844.         ds = "d"
  9845.         quadrant[EUPHORIA][Q_TORP] = 0
  9846.         quadrant[EUPHORIA][Q_EN] = 5000
  9847.         ts = ""
  9848.         ps = ""
  9849.         wtext()
  9850.         shuttle = TRUE
  9851.         p_energy(0)
  9852.     end if
  9853.  
  9854.     elsif com = 'c' or com = BS then   -- cancel
  9855.     chr = ' '
  9856.     echo(chr)
  9857.     nchars = 0
  9858.  
  9859.     elsif com = 'f' then   -- freeze the game (pause until cancelled)
  9860.     echo(chr)
  9861.     t_stop = time()
  9862.     while not find(get_key() , {'c', BS, ESC}) do
  9863.     end while
  9864.     shift_task_times(time() - t_stop)
  9865.     echo(' ')
  9866.     nchars = 0
  9867.  
  9868.     elsif com = ESC then
  9869.     quit()
  9870.     
  9871.     else
  9872.     return FALSE
  9873.  
  9874.     end if
  9875.  
  9876.     return TRUE
  9877. end function
  9878.  
  9879. global function task_keyb()
  9880. -- independent task: check the keyboard for command input
  9881.     boolean x
  9882.     natural tempchars
  9883.     keycode chr
  9884.  
  9885.     while TRUE do
  9886.     chr = get_key()
  9887.     if not char(chr) then
  9888.         exit
  9889.     end if
  9890.     if (chr >= '0' and chr <= '9') or chr = '<' or chr = '>' then
  9891.         if nchars then
  9892.         x = docom(curcom, chr)
  9893.         else
  9894.         if chr >= '0' and chr <= '9' then
  9895.             dircom(chr)
  9896.         end if
  9897.         end if
  9898.     else
  9899.         tempchars = nchars
  9900.         nchars = 0
  9901.         if docom(chr, chr) then
  9902.         curcom = chr
  9903.         else
  9904.         nchars = tempchars
  9905.         end if
  9906.     end if
  9907.     end while
  9908.     return {}
  9909. end function
  9910.  
  9911. DAMAGE.E
  9912. 11803
  9913. -- damage.e
  9914. -- compute effects of damage
  9915.  
  9916. global function Java_target(valid_quadrant_row r)
  9917. -- select target for Java ship at row r
  9918.     sequence flive
  9919.  
  9920.     flive = {}
  9921.     for i = 1 to length(quadrant) do
  9922.     if i != r and quadrant[i][Q_TYPE] != DEAD then
  9923.         flive &= i
  9924.     end if
  9925.     end for
  9926.     return flive[rand(length(flive))]
  9927. end function
  9928.  
  9929. procedure setrmt(valid_quadrant_row newtarg)
  9930. -- set BASIC group target
  9931.  
  9932.     basic_targ = newtarg
  9933.     if bstat = TRUCE then
  9934.     if basic_targ = EUPHORIA or quadrant[basic_targ][Q_TYPE] = G_BS then
  9935.         truce_broken = TRUE
  9936.         schedule(t_bstat, 2.5, 2.5, 0.1, {})
  9937.     end if
  9938.     end if
  9939.     for row = 2 to length(quadrant) do
  9940.     if quadrant[row][Q_TYPE] = G_BAS then
  9941.         quadrant[row][Q_TARG] = basic_targ
  9942.     end if
  9943.     end for
  9944. end procedure
  9945.  
  9946. procedure setnt(quadrant_row victim)
  9947. -- target is dead 
  9948. -- set new target for everyone that was shooting at him
  9949.     natural t -- type or 0
  9950.     valid_quadrant_row targ
  9951.  
  9952.     for row = 2 to length(quadrant) do
  9953.     if quadrant[row][Q_TARG] = victim then
  9954.         t = quadrant[row][Q_TYPE]
  9955.         if t = G_BS then
  9956.         quadrant[row][Q_FRATE] = 0
  9957.         else
  9958.         if t = G_JAV then
  9959.             targ = Java_target(row)
  9960.         else
  9961.             targ = EUPHORIA
  9962.         end if
  9963.         quadrant[row][Q_TARG] = targ
  9964.         end if
  9965.     end if
  9966.     end for
  9967.     if victim = basic_targ then
  9968.     basic_targ = EUPHORIA
  9969.     end if
  9970. end procedure
  9971.  
  9972. global procedure repair(subsystem sys)
  9973. -- repair a subsystem
  9974.     if sys = ENGINES then
  9975.     wlimit = 5
  9976.     set_bk_color(WHITE)
  9977.     set_color(BLACK)
  9978.     position(WARP_LINE, WARP_POS+5)
  9979.     console_printf("%d   ", curwarp)
  9980.     end if
  9981.     ndmg -= 1
  9982. end procedure
  9983.  
  9984. procedure edmg(positive_atom blast)
  9985. -- Euphoria damage
  9986.     subsystem sys
  9987.  
  9988.     if blast > rand(256) * 80 then
  9989.     sys = rand(NSYS)
  9990.     if reptime[sys] = 0 then
  9991.         reptime[sys] = rand(81) + 9
  9992.         if sys = GALAXY_SENSORS then
  9993.         end_scan()
  9994.         end if
  9995.         if sys = ENGINES then
  9996.         wlimit = rand(4) - 1
  9997.         if wlimit = 0 then
  9998.             msg("ALL ENGINES DAMAGED")
  9999.         else
  10000.             msg("ENGINES DAMAGED")
  10001.         end if
  10002.         if curwarp > wlimit then
  10003.             setwarp(wlimit)
  10004.         end if
  10005.         else
  10006.         fmsg("%s DAMAGED", {dtype[sys]})
  10007.         end if
  10008.         ndmg += 1
  10009.         schedule(t_damage_report, 1.5, 1.5, 0.1, {})
  10010.     end if
  10011.     end if
  10012. end procedure
  10013.  
  10014. boolean drep_on
  10015. drep_on = FALSE
  10016.  
  10017. procedure drep_blank()
  10018. -- clear the damage report area
  10019.     position(WARP_LINE, DREP_POS)
  10020.     console_puts(repeat(' ', 13))
  10021.     position(WARP_LINE+1, DREP_POS)
  10022.     console_puts(repeat(' ', 13))
  10023. end procedure
  10024.  
  10025. global procedure drep()
  10026. -- damage report update
  10027.     set_bk_color(RED)
  10028.     set_color(BLACK)
  10029.     if not drep_on then
  10030.     drep_blank()
  10031.     drep_on = TRUE
  10032.     end if
  10033.     position(WARP_LINE, DREP_POS+1)
  10034.     console_printf("P%-2d T%-2d S%-2d", {reptime[PHASORS],
  10035.                 reptime[TORPEDOS],
  10036.                 reptime[GALAXY_SENSORS]})
  10037.     position(CMD_LINE, DREP_POS+1)
  10038.     console_printf("G%-2d E%d", {reptime[GUIDANCE], reptime[ENGINES]})
  10039.     if reptime[ENGINES] > 0 then
  10040.     console_printf(":%d ", wlimit)
  10041.     else
  10042.     console_puts("   ")
  10043.     end if
  10044. end procedure
  10045.  
  10046. global function task_damage_report()
  10047. -- independent task: damage countdown
  10048.  
  10049.     if ndmg = 0 then
  10050.     schedule(t_damage_report, INACTIVE, INACTIVE, 0, {})
  10051.     set_bk_color(WHITE)
  10052.     drep_blank()
  10053.     drep_on = FALSE
  10054.     else
  10055.     for i = 1 to NSYS do
  10056.         if reptime[i] then
  10057.         reptime[i] -= 1
  10058.         if reptime[i] = 0 then
  10059.             repair(i)
  10060.             fmsg("%s REPAIRED", {dtype[i]})
  10061.         end if
  10062.         end if
  10063.     end for
  10064.     drep()
  10065.     end if
  10066.     return {}
  10067. end function
  10068.  
  10069. global function who_is_it(h_coord x1, v_coord y1, sequence shape)
  10070. -- map a rectangular region of the screen to the quadrant sequence rows
  10071. -- of the object(s) that occupy it (or return {} if it's just a POD)
  10072.  
  10073.     extended_h_coord x2, ix1, ix2
  10074.     extended_v_coord y2, iy1, iy2
  10075.     natural t, bestover, iover
  10076.     sequence who
  10077.     
  10078.     x2 = x1 + length(shape[1]) - 1
  10079.     y2 = y1 + length(shape) - 1
  10080.     bestover = 0
  10081.     who = {}
  10082.     
  10083.     for i = EUPHORIA to length(quadrant) do
  10084.     t = quadrant[i][Q_TYPE]
  10085.     
  10086.     if t then
  10087.         ix1 = quadrant[i][Q_X]
  10088.         ix2 = ix1 + length(oshape[t][1][1]) - 1
  10089.     
  10090.         iy1 = quadrant[i][Q_Y]
  10091.         iy2 = iy1 + length(oshape[t][1]) - 1
  10092.         
  10093.         -- compute amount of overlap
  10094.         iover = 0
  10095.         if (ix2 >= x1 and ix1 <= x2) and
  10096.            (iy2 >= y1 and iy1 <= y2) then
  10097.         -- there is some overlap
  10098.         who = append(who, i)
  10099.         end if          
  10100.     end if
  10101.     end for
  10102.     if length(who) = 0 then
  10103.     -- check for POD
  10104.     if is_pod(read_screen(x1, y1, shape)) then
  10105.         return {}
  10106.     else
  10107.         -- something is wrong: we must always know who's there
  10108.         return 1/0  
  10109.     end if
  10110.     else
  10111.     return who
  10112.     end if
  10113. end function
  10114.  
  10115. global function task_dead()
  10116. -- independent task: clean dead bodies off the screen
  10117.     integer c
  10118.     image r
  10119.     sequence ri
  10120.     boolean all_zero
  10121.     
  10122.     c = 1
  10123.     while c <= length(wipeout) do
  10124.     r = read_screen(wipeout[c][1], wipeout[c][2], wipeout[c][3])
  10125.     if all_clear(r) then
  10126.         all_zero = TRUE
  10127.         for i = 1 to length(r) do
  10128.         ri = r[i]
  10129.         for j = 1 to length(ri) do
  10130.             if and_bits(ri[j], #F) != 0 then
  10131.             if rand(2) = 1 then
  10132.                 ri[j] = 0
  10133.             else
  10134.                 all_zero = FALSE
  10135.             end if
  10136.             end if
  10137.         end for
  10138.         r[i] = ri
  10139.         end for
  10140.         write_screen(wipeout[c][1], wipeout[c][2], r)
  10141.         if all_zero then
  10142.         -- finished, delete this one
  10143.         wipeout = wipeout[1..c-1] & wipeout[c+1..length(wipeout)]
  10144.         else
  10145.         -- more clearing to do later
  10146.         c += 1
  10147.         end if
  10148.     else
  10149.         -- another object is in the way, skip it
  10150.         c += 1
  10151.     end if
  10152.     end while
  10153.     if c > 1 then
  10154.     -- we skipped something - finish later
  10155.     schedule(t_dead, 1.0, 1.0, 0.2, {})
  10156.     else
  10157.     schedule(t_dead, INACTIVE, INACTIVE, 0, {})
  10158.     end if
  10159.     return {}
  10160. end function
  10161.  
  10162. global function task_explosion(sequence dots)
  10163. -- Plays out an explosion on the screen.
  10164. -- Accesses screen variable directly for maximum speed.
  10165.     integer p, c, x, y
  10166.     boolean draw
  10167.     
  10168.     draw = FALSE
  10169.     for i = 1 to length(dots) do
  10170.     if sequence(dots[i]) then
  10171.         x = floor(dots[i][2])
  10172.         y = floor(dots[i][3])
  10173.         p = screen[y][x]
  10174.         if p >= 33 and p <= 64 then
  10175.         screen[y][x] = 48 -- blank out old position
  10176.         if not scanon then
  10177.             pixel(48, {x-1, y-1})
  10178.         end if
  10179.         end if
  10180.         dots[i][2] += dots[i][4]
  10181.         dots[i][3] += dots[i][5]
  10182.         x = floor(dots[i][2])
  10183.         y = floor(dots[i][3])
  10184.         -- draw at new position
  10185.         if rand(15) = 1 or 
  10186.         x < 1 or x > HSIZE or
  10187.         y < 1 or y > VSIZE then
  10188.         -- delete this dot
  10189.         dots[i] = 0
  10190.         else
  10191.         -- draw it at new position
  10192.         draw = TRUE
  10193.         c = dots[i][1]
  10194.         p = screen[y][x]
  10195.         if p != c and (p = 0 or (p >= 33 and p <= 64)) then
  10196.             screen[y][x] = c
  10197.             if not scanon then
  10198.             pixel(c, {x-1, y-1})
  10199.             end if
  10200.         end if
  10201.         end if
  10202.     end if
  10203.     end for
  10204.     
  10205.     if not draw then
  10206.     schedule(t_dead, 0, INACTIVE, 0.4, {})
  10207.     delete_task(current_task)
  10208.     return {}
  10209.     else
  10210.     return {dots}
  10211.     end if
  10212. end function
  10213.  
  10214. procedure explosion(h_coord x, v_coord y, natural xsize, natural ysize, 
  10215.             natural ndots, 
  10216.             natural color)
  10217. -- initiate an explosion on the screen centered at x, y
  10218. -- xsize and ysize must be at least 3
  10219.     sequence dots
  10220.     task t
  10221.     natural tempx, tempy
  10222.     
  10223.     -- create initial set of colored dots
  10224.     dots = repeat(0, ndots)
  10225.     tempx = floor(xsize/2)-1
  10226.     tempy = floor(ysize/2)-1
  10227.     color += 32
  10228.     for i = 1 to ndots do
  10229.     dots[i] = {color,
  10230.            x+rand(tempx)+rand(tempx), 
  10231.            y+rand(tempy)+rand(tempy),
  10232.            rand(400)/100 * (rand(2)*2-3), 
  10233.            rand(400)/100 * (rand(2)*2-3)}
  10234.     end for
  10235.     t = create_task(routine_id("task_explosion"))   
  10236.     schedule(t, 0.3, .07+.00002*ndots, .03, {dots})
  10237. end procedure
  10238.  
  10239. global procedure sched_move_fire()
  10240. -- schedule enemy move and fire tasks according to number of
  10241. -- ships in the quadrant
  10242.     atom move_time, fire_time
  10243.     integer enemy
  10244.     
  10245.     enemy = 0
  10246.     for i = 2 to length(quadrant) do
  10247.     if quadrant[i][Q_TYPE] != DEAD then
  10248.         enemy += 1
  10249.     end if
  10250.     end for
  10251.     
  10252.     move_time = .01 + .20 / (1+enemy)
  10253.     fire_time = .50 + 3 / (4+enemy)
  10254.     if level = 'n' then
  10255.     move_time *= 3
  10256.     fire_time *= 3
  10257.     end if
  10258.     schedule(t_move, move_time, move_time, .02, {})
  10259.     schedule(t_fire, rand(1+floor(fire_time)), fire_time, .10, {})
  10260. end procedure
  10261.  
  10262. -- bright version of object color for better-looking explosion
  10263. sequence ocolor
  10264. ocolor = {YELLOW,
  10265.       BRIGHT_RED,
  10266.       BRIGHT_RED,
  10267.       BRIGHT_MAGENTA,
  10268.       BRIGHT_BLUE,
  10269.       BRIGHT_GREEN,
  10270.       YELLOW,
  10271.       YELLOW}
  10272.  
  10273. procedure dead(valid_quadrant_row row)
  10274. -- process a dead object
  10275.  
  10276.     object_type t
  10277.     pb_row pbx
  10278.     h_coord x
  10279.     v_coord y
  10280.     natural lenx, leny
  10281.     image dead_body
  10282.     
  10283.     if row = EUPHORIA then
  10284.     -- Euphoria destroyed !
  10285.     quadrant[EUPHORIA][Q_EN] = 0
  10286.     p_energy(-1)
  10287.     end if
  10288.     t = quadrant[row][Q_TYPE]
  10289.     nobj[t] -= 1
  10290.     x = quadrant[row][Q_X]
  10291.     y = quadrant[row][Q_Y]
  10292.     dead_body = (read_screen(x, y, oshape[t][1]) != 32) * (ocolor[t]+32)
  10293.     lenx = length(oshape[t][1][1])
  10294.     leny = length(oshape[t][1])
  10295.     write_screen(x, y, dead_body)
  10296.     wipeout = append(wipeout, {x, y, dead_body})
  10297.     explosion(floor(quadrant[row][Q_X]),
  10298.           floor(quadrant[row][Q_Y]),
  10299.           lenx,
  10300.           leny,
  10301.           floor(lenx*leny+5),
  10302.           ocolor[t])
  10303.     explosion_sound(lenx)
  10304.     if t >= G_PL then
  10305.     pbx = quadrant[row][Q_PBX]
  10306.     pb[pbx][P_TYPE] = DEAD
  10307.     else
  10308.     if c_remaining() = 0 then
  10309.         gameover = TRUE
  10310.     end if
  10311.     end if
  10312.     quadrant[row][Q_TYPE] = DEAD
  10313.     quadrant[row][Q_X] = HSIZE + 1
  10314.     quadrant[row][Q_Y] = VSIZE + 1
  10315.     if not gameover then
  10316.     setnt(row)
  10317.     galaxy[qrow][qcol][t] -= 1
  10318.     end if
  10319.     fmsg("%s DESTROYED!", {otype[t]})
  10320.     sched_move_fire()
  10321.     if scanon then
  10322.     upg(qrow, qcol)
  10323.     gtext()
  10324.     end if
  10325. end procedure
  10326.  
  10327. global procedure dodmg(positive_atom blast, boolean wtorp,
  10328.                valid_quadrant_row shooter, valid_quadrant_row victim)
  10329. -- damage a struck object
  10330.     object_type t
  10331.     natural d
  10332.     positive_atom ven
  10333.  
  10334.     t = quadrant[victim][Q_TYPE]
  10335.     if quadrant[shooter][Q_TYPE] = G_POD then
  10336.     if t = G_BAS then
  10337.         setrmt(EUPHORIA)
  10338.     elsif t != G_BS then
  10339.         quadrant[victim][Q_TARG] = EUPHORIA
  10340.     end if
  10341.     else
  10342.     -- note: shooter may have launched weapon just before he died
  10343.     if quadrant[shooter][Q_TYPE] != DEAD then
  10344.         if t = G_BAS then
  10345.         setrmt(shooter)
  10346.         elsif t = G_BS and shooter = EUPHORIA then
  10347.         -- do nothing if EUPHORIA hits base
  10348.         else
  10349.         quadrant[victim][Q_TARG] = shooter
  10350.         end if
  10351.     end if
  10352.     end if
  10353.     if wtorp then
  10354.     -- torpedo
  10355.     d = quadrant[victim][Q_DEFL]
  10356.     if d then
  10357.         deflected_sound()
  10358.         msg("DEFLECTED")
  10359.         quadrant[victim][Q_DEFL] = d-1
  10360.         ds = repeat(DEFL_SYM, quadrant[EUPHORIA][Q_DEFL])
  10361.         wtext()
  10362.         blast = 0
  10363.     else
  10364.         torpedo_hit()
  10365.     end if
  10366.     end if
  10367.     if blast then
  10368.     fmsg("%d UNIT HIT ON %s", {blast, otype[t]})
  10369.     ven = quadrant[victim][Q_EN]
  10370.     if blast >= ven then
  10371.         dead(victim)
  10372.     else
  10373.         ven -= blast
  10374.         quadrant[victim][Q_EN] = ven
  10375.         if t <= G_JAV then
  10376.         if victim = EUPHORIA then
  10377.             p_energy(0)
  10378.             edmg(blast)
  10379.         else
  10380.             fmsg("%d UNITS REMAIN", ven)
  10381.         end if
  10382.         end if
  10383.     end if
  10384.     end if
  10385. end procedure
  10386.  
  10387. -- global constant ASPECT_RATIO = 1.0 -- vertical vs. horizontal pixel size
  10388.  
  10389. global function bcalc(positive_atom energy, valid_quadrant_row shooter, 
  10390.               valid_quadrant_row victim)
  10391. -- calculate amount of phasor blast
  10392.     atom xdiff, ydiff
  10393.  
  10394.     xdiff = quadrant[victim][Q_X] - quadrant[shooter][Q_X]
  10395.     ydiff = (quadrant[victim][Q_Y] - quadrant[shooter][Q_Y]) --* ASPECT_RATIO
  10396.     return 1500 * energy / (50 + sqrt(xdiff * xdiff + ydiff * ydiff))
  10397. end function
  10398.  
  10399. DISPLAY.E
  10400. 14859
  10401. -- display.e
  10402. -- graphics, sound and text display on screen
  10403.  
  10404. global sequence oshape -- images for all objects
  10405.  
  10406. global sequence ds -- Euphoria deflectors
  10407. global sequence ts -- Euphoria torpedos
  10408. global sequence ps -- Euphoria anti-matter pods 
  10409.  
  10410. global function c_remaining()
  10411. -- number of C ships (of all types) left
  10412.     return nobj[G_KRC] + nobj[G_ANC] + nobj[G_CPP]
  10413. end function
  10414.  
  10415. type negative_atom(atom x)
  10416.     return x <= 0
  10417. end type
  10418.  
  10419. global procedure p_energy(negative_atom delta)
  10420. -- print Euphoria energy
  10421.     atom energy
  10422.  
  10423.     energy = quadrant[EUPHORIA][Q_EN] + delta
  10424.     quadrant[EUPHORIA][Q_EN] = energy
  10425.     if energy < 0 then
  10426.     energy = 0
  10427.     gameover = TRUE
  10428.     end if
  10429.     position(WARP_LINE, ENERGY_POS+7)
  10430.     set_bk_color(WHITE)
  10431.     if energy < 5000 then
  10432.     set_color(RED)
  10433.     else
  10434.     set_color(BLACK)
  10435.     end if
  10436.     console_printf("%d    ", floor(energy))
  10437. end procedure
  10438.  
  10439. global function task_life()
  10440. -- independent task: update energy on console, including "life support" energy
  10441.     if shuttle then
  10442.     p_energy(-3)
  10443.     else
  10444.     p_energy(-13)
  10445.     end if
  10446.     return {}
  10447. end function
  10448.  
  10449. ------------------------- message handler -----------------------------
  10450. -- All messages come here. A task ensures that messages will be displayed
  10451. -- on the screen for at least a second or so, before being overwritten by
  10452. -- the next message. If there is no queue, a message will be printed 
  10453. -- immediately, otherwise it is added to the queue. 
  10454.  
  10455. constant MESSAGE_GAP = 1.2  -- seconds between messages for readability
  10456.  
  10457. sequence message_queue
  10458. message_queue = {}
  10459.  
  10460. constant MAX_MSG_LEN = 55
  10461.  
  10462. global procedure display_msg(sequence text)
  10463. -- print a message immediately
  10464.     set_bk_color(WHITE)
  10465.     set_color(RED)
  10466.     position(MSG_LINE, MSG_POS)
  10467.     if length(text) > MAX_MSG_LEN then
  10468.     text = text[1..MAX_MSG_LEN]
  10469.     end if
  10470.     console_puts(text)
  10471.     console_puts(BLANK_LINE[1..MAX_MSG_LEN-length(text)])
  10472. end procedure
  10473.  
  10474. global procedure msg(sequence text)
  10475. -- print a plain text message on the message line
  10476.     if length(message_queue) = 0 then
  10477.     -- print it right away
  10478.     display_msg(text)
  10479.     schedule(t_message, MESSAGE_GAP, MESSAGE_GAP, 0.2, {})
  10480.     end if
  10481.     message_queue = append(message_queue, text)
  10482. end procedure
  10483.  
  10484. global procedure fmsg(sequence format, object values)
  10485. -- print a formatted message on the message line
  10486.     msg(sprintf(format, values))
  10487. end procedure
  10488.  
  10489. global function task_message()
  10490. -- task to display next message in message queue
  10491.  
  10492.     -- first message is already on the screen - delete it
  10493.     message_queue = message_queue[2..length(message_queue)]
  10494.     if length(message_queue) = 0 then
  10495.     schedule(t_message, INACTIVE, INACTIVE, 0, {}) -- no more messages
  10496.     else
  10497.     display_msg(message_queue[1])
  10498.     -- speed up a bit when there's a queue
  10499.     schedule(t_message, MESSAGE_GAP-0.4, MESSAGE_GAP-0.4, 0.2, {})
  10500.     end if
  10501.     return {}
  10502. end function
  10503.  
  10504. ----------------------------------------------------------------------------
  10505.  
  10506. global procedure show_warp()
  10507. -- show current speed (with warning)
  10508.     set_bk_color(WHITE)
  10509.     set_color(BLACK)
  10510.     position(WARP_LINE, WARP_POS)
  10511.     console_puts("WARP:")
  10512.     if curwarp > wlimit then
  10513.     set_color(RED)
  10514.     end if
  10515.     console_printf("%d", curwarp)
  10516. end procedure
  10517.  
  10518. -- how long it takes Euphoria to move at warp 0 thru 5:
  10519. global constant warp_time = {INACTIVE, 20, .60, .15, .04, .02}
  10520.  
  10521. global procedure setwarp(warp new)
  10522. -- establish a new warp speed for the Euphoria
  10523.  
  10524.     if new != curwarp then
  10525.     schedule(t_emove, warp_time[new+1], warp_time[new+1], (5-new)/100, {})
  10526.     curwarp = new
  10527.     show_warp()
  10528.     end if
  10529. end procedure
  10530.  
  10531. global procedure gtext()
  10532. -- print text portion of galaxy scan
  10533.     set_bk_color(BLUE)
  10534.     position(22, 37)
  10535.     set_color(BRIGHT_RED)
  10536.     console_printf("C: %d ", c_remaining())
  10537.     position(23, 24)
  10538.     set_color(BROWN)
  10539.     console_printf("Planets: %d", nobj[G_PL])
  10540.     set_color(BRIGHT_CYAN)
  10541.     console_printf("   BASIC: %d", nobj[G_BAS])
  10542.     if bstat = TRUCE then
  10543.     console_puts(" TRUCE   ")
  10544.     elsif bstat = HOSTILE then
  10545.     console_puts(" HOSTILE ")
  10546.     else
  10547.     console_puts(" CLOAKING")
  10548.     end if
  10549.     position(24, 24)
  10550.     set_color(YELLOW)
  10551.     console_printf("Bases: %d", nobj[G_BS])
  10552.     set_color(BRIGHT_GREEN)
  10553.     console_printf("     Java: %d ", nobj[G_JAV])
  10554.     position(25, 67)
  10555.     set_color(BLUE)
  10556.     set_bk_color(WHITE)
  10557.     if level = 'n' then
  10558.     console_puts("novice level")
  10559.     else
  10560.     console_puts("expert level")
  10561.     end if
  10562. end procedure
  10563.  
  10564. constant XSCALE = QXSIZE/HSIZE,
  10565.      YSCALE = (QYSIZE-1)/VSIZE  -- -1 or CPP might protrude below quad
  10566.  
  10567. constant KNOWN_QUAD = repeat(repeat(GRAY, QXSIZE), QYSIZE),
  10568.        CURRENT_QUAD = repeat(repeat(WHITE, QXSIZE), QYSIZE)
  10569.  
  10570. constant C_ICON = repeat(repeat(BRIGHT_RED, 3), 2),
  10571.        CPP_ICON = repeat(repeat(BRIGHT_MAGENTA, 3), 3),
  10572.      BASIC_ICON = repeat(repeat(BRIGHT_BLUE, 2), 2),
  10573.       JAVA_ICON = repeat(repeat(BRIGHT_GREEN, 2), 2),
  10574.   EUPHORIA_ICON = repeat(repeat(YELLOW, 2), 2),
  10575.       BASE_ICON = repeat(repeat(YELLOW, 4), 4),
  10576.     PLANET_ICON = repeat(repeat(BROWN, 6), 6)
  10577.  
  10578. function display_rand(image quad, image icon, natural count)
  10579. -- display ships in random positions for non-current quadrant
  10580.     natural xpos, ypos, xlen, ylen, xrange, yrange, back, y
  10581.     boolean collide
  10582.     sequence qy
  10583.     
  10584.     back = KNOWN_QUAD[1][1]
  10585.     xlen = length(icon[1])
  10586.     ylen = length(icon)
  10587.     xrange = QXSIZE-xlen-1 -- avoid the edges
  10588.     yrange = QYSIZE-ylen-1
  10589.     for i = 1 to count do
  10590.     for j = 1 to 10 do -- avoid infinite loop
  10591.         xpos = 1+rand(xrange)
  10592.         ypos = 1+rand(yrange)
  10593.         collide = FALSE
  10594.         y = ypos
  10595.         while y < ypos+ylen and not collide do
  10596.         qy = quad[y]
  10597.         for x = xpos to xpos+xlen-1 do
  10598.             if qy[x] != back then
  10599.             collide = TRUE
  10600.             exit
  10601.             end if
  10602.         end for
  10603.         y += 1
  10604.         end while   
  10605.         if not collide then
  10606.         quad = update_image(quad, xpos, ypos, icon)
  10607.         exit
  10608.         end if
  10609.     end for
  10610.     end for
  10611.     return quad
  10612. end function
  10613.  
  10614. global procedure gquad(g_index r, g_index c)
  10615. -- print one galaxy scan quadrant
  10616.  
  10617.     natural qx, qy, qt, back
  10618.     sequence quad_info
  10619.     h_coord x
  10620.     v_coord y
  10621.     object icon
  10622.     image this_quad
  10623.  
  10624.     quad_info = galaxy[r][c]
  10625.     if quad_info[1] = 0 then
  10626.     return -- unknown quadrant (screen is already black)
  10627.     end if
  10628.     x = c * QXSIZE + 31
  10629.     y = r * QYSIZE - 8
  10630.     if r = qrow and c = qcol then
  10631.     -- the current quadrant
  10632.     this_quad = CURRENT_QUAD
  10633.     for i = length(quadrant) to 1 by -1 do
  10634.         qt = quadrant[i][Q_TYPE]
  10635.         if qt = EUPHORIA then
  10636.         icon = EUPHORIA_ICON
  10637.         elsif qt = G_KRC or qt = G_ANC then
  10638.         icon = C_ICON
  10639.         elsif qt = G_CPP then
  10640.         icon = CPP_ICON
  10641.         elsif qt = G_BAS and bstat != CLOAKING then
  10642.         icon = BASIC_ICON
  10643.         elsif qt = G_JAV then
  10644.         icon = JAVA_ICON
  10645.         elsif qt = G_PL then
  10646.         -- round the edges (assumes size 6)
  10647.         back = CURRENT_QUAD[1][1]
  10648.         icon = PLANET_ICON  
  10649.         icon[1][1] = back
  10650.         icon[1][6] = back
  10651.         icon[6][1] = back
  10652.         icon[6][6] = back
  10653.         if pb[quadrant[i][Q_PBX]][P_EN] <= 0 then
  10654.             -- make it white if it's out of energy
  10655.             icon += (icon != back) * (BRIGHT_WHITE-icon)
  10656.         end if
  10657.         elsif qt = G_BS then
  10658.         icon = BASE_ICON
  10659.         if pb[quadrant[i][Q_PBX]][P_EN] <= 0 then
  10660.             -- make it white if out of energy
  10661.             icon += (BRIGHT_WHITE-icon)
  10662.         end if
  10663.         else
  10664.         icon = DEAD
  10665.         end if
  10666.         
  10667.         if sequence(icon) then
  10668.         -- scaling assumes icons have reasonable proportions 
  10669.         -- compared to real objects
  10670.         qx = 1+floor(quadrant[i][Q_X]*XSCALE) 
  10671.         qy = 1+floor(quadrant[i][Q_Y]*YSCALE)
  10672.         -- avoids flicker
  10673.         this_quad = update_image(this_quad, qx, qy, icon)
  10674.         end if
  10675.     end for
  10676.     else
  10677.     -- other known quadrants
  10678.     this_quad = KNOWN_QUAD
  10679.     if quad_info[G_BS] or quad_info[G_PL] then
  10680.         back = KNOWN_QUAD[1][1]
  10681.         for i = 1 to length(pb) do
  10682.         if pb[i][P_TYPE] != DEAD and pb[i][P_QR] = r and
  10683.                          pb[i][P_QC] = c then
  10684.             if pb[i][P_TYPE] = G_PL then
  10685.             -- round the edges
  10686.             icon = PLANET_ICON
  10687.             icon[1][1] = back
  10688.             icon[1][6] = back
  10689.             icon[6][1] = back
  10690.             icon[6][6] = back
  10691.             else    
  10692.             icon = BASE_ICON
  10693.             end if
  10694.             if pb[i][P_EN] <= 0 then
  10695.             -- make it white if it's out of energy
  10696.             icon += (icon != back) * (BRIGHT_WHITE-icon)
  10697.             end if
  10698.             qx = 1+floor(pb[i][P_X]*XSCALE) 
  10699.             qy = 1+floor(pb[i][P_Y]*YSCALE)
  10700.             this_quad = update_image(this_quad, qx, qy, icon)
  10701.         end if
  10702.         end for
  10703.     end if
  10704.         
  10705.     if bstat != CLOAKING then
  10706.         this_quad = display_rand(this_quad, BASIC_ICON, quad_info[G_BAS])
  10707.     end if
  10708.     this_quad = display_rand(this_quad, JAVA_ICON, quad_info[G_JAV])
  10709.     this_quad = display_rand(this_quad, C_ICON, quad_info[G_KRC] + 
  10710.                             quad_info[G_ANC])
  10711.     this_quad = display_rand(this_quad, CPP_ICON, quad_info[G_CPP])
  10712.     end if
  10713.     -- display final picture of this quadrant
  10714.     display_image({x,y}, this_quad)
  10715. end procedure
  10716.  
  10717. global function task_gquad()
  10718. -- update the current quadrant display on the galaxy scan
  10719.     gquad(qrow, qcol)
  10720.     return {}
  10721. end function
  10722.  
  10723. global procedure upg(g_index qrow, g_index qcol)
  10724. -- update galaxy scan quadrant
  10725.     if scanon then
  10726.     gquad(qrow, qcol)
  10727.     end if
  10728. end procedure
  10729.  
  10730. sequence prev_box
  10731. prev_box = {}
  10732.  
  10733. global procedure gsbox(g_index qrow, g_index qcol)
  10734. -- indicate current quadrant on galaxy scan
  10735.     if scanon then
  10736.     if length(prev_box) = 2 then
  10737.         -- clear the previous "box" (could be gone already)
  10738.         gquad(prev_box[1], prev_box[2])
  10739.     end if
  10740.     gquad(qrow, qcol)
  10741.     prev_box = {qrow, qcol}
  10742.     end if
  10743. end procedure
  10744.  
  10745. constant dir_places = {{1, 6},{0, 6},{0, 3},{0, 0},{1, 0},{2, 0},{2, 3},{2, 6}}
  10746.  
  10747. global procedure dir_box()
  10748.     -- direction box
  10749.     sequence place
  10750.  
  10751.     set_bk_color(BLUE)
  10752.     set_color(BRIGHT_WHITE)
  10753.     position(WARP_LINE, DIRECTIONS_POS)
  10754.     console_puts("4  3  2")
  10755.     position(CMD_LINE, DIRECTIONS_POS)
  10756.     console_puts("5  @  1")  -- @ redefined as big '+'
  10757.     position(MSG_LINE, DIRECTIONS_POS)
  10758.     console_puts("6  7  8")
  10759.     place = dir_places[curdir]
  10760.     position(place[1]+WARP_LINE,place[2]+DIRECTIONS_POS) 
  10761.     set_bk_color(GREEN)
  10762.     console_printf("%d", curdir)
  10763.     set_bk_color(WHITE)
  10764. end procedure
  10765.  
  10766. global procedure wtext()
  10767. -- print torpedos, pods, deflectors in text window
  10768.     sequence s
  10769.     set_bk_color(WHITE)
  10770.     set_color(BLACK)
  10771.     position(WARP_LINE, WEAPONS_POS)
  10772.     s = sprintf("%s %s %s", {ts, ds, ps})
  10773.     console_puts(s) 
  10774.     -- max 10 torps, blank, 3 def, blank, 4 pods
  10775.     console_puts(repeat(' ', 20-length(s)))
  10776. end procedure
  10777.  
  10778. global procedure stext()
  10779. -- print text window info
  10780.     position(QUAD_LINE, 1)
  10781.     set_bk_color(GREEN)
  10782.     set_color(BRIGHT_WHITE)
  10783.     console_puts("  1-8  w")
  10784.     set_color(BLACK)
  10785.     console_puts("arp  ")
  10786.     set_color(BRIGHT_WHITE)
  10787.     console_puts("p")
  10788.     set_color(BLACK)
  10789.     console_puts("hasor  ")
  10790.     set_color(BRIGHT_WHITE)
  10791.     console_puts("t")
  10792.     set_color(BLACK)
  10793.     console_puts("orpedo  ")
  10794.     set_color(BRIGHT_WHITE)
  10795.     console_puts("a")
  10796.     set_color(BLACK)
  10797.     console_puts("ntimatter  ")
  10798.     set_color(BRIGHT_WHITE)
  10799.     console_puts("g")
  10800.     set_color(BLACK)
  10801.     console_puts("alaxy  ")
  10802.     set_color(BRIGHT_WHITE)
  10803.     console_puts("s")
  10804.     set_color(BLACK)
  10805.     console_puts("huttle  ")
  10806.     set_color(BRIGHT_WHITE)
  10807.     console_puts("f")
  10808.     set_color(BLACK)
  10809.     console_puts("reeze  ")
  10810.     set_color(BRIGHT_WHITE)
  10811.     console_puts("c")
  10812.     set_color(BLACK)
  10813.     console_puts("ancel  ")
  10814.     set_color(BRIGHT_WHITE)
  10815.     console_puts("Esc  ")
  10816.     set_bk_color(WHITE)
  10817.     set_color(BLACK)
  10818.     show_warp()
  10819.     wtext()
  10820.     position(WARP_LINE, ENERGY_POS)
  10821.     console_printf("ENERGY:%d    ", floor(quadrant[EUPHORIA][Q_EN]))
  10822.     position(CMD_LINE, CMD_POS-9)
  10823.     console_puts("COMMAND: ")
  10824.     dir_box()
  10825. end procedure
  10826.  
  10827. procedure p_source(valid_quadrant_row row)
  10828. -- print a base or planet
  10829.     h_coord x
  10830.     v_coord y
  10831.  
  10832.     x = quadrant[row][Q_X]
  10833.     y = quadrant[row][Q_Y]
  10834.     if quadrant[row][Q_TYPE] = G_PL then
  10835.     write_screen(x, y, PLANET)
  10836.     else
  10837.     write_screen(x, y, BASE)
  10838.     end if
  10839. end procedure
  10840.  
  10841. procedure p_ship(valid_quadrant_row row)
  10842. -- reprint a ship to get color
  10843.     h_coord x
  10844.     v_coord y
  10845.     object_type t
  10846.     sequence shape
  10847.  
  10848.     x = quadrant[row][Q_X]
  10849.     y = quadrant[row][Q_Y]
  10850.     t = quadrant[row][Q_TYPE]
  10851.     shape = read_screen(x, y, oshape[t][1])
  10852.     write_screen(x, y, shape)
  10853. end procedure
  10854.  
  10855. global procedure end_scan()
  10856. -- end display of galaxy scan
  10857.     if scanon then
  10858.     scanon = FALSE
  10859.     ShowScreen()
  10860.     schedule(t_gquad, INACTIVE, INACTIVE, 0, {})
  10861.     end if
  10862. end procedure
  10863.  
  10864. global procedure refresh_scan()
  10865.     for r = 1 to G_SIZE do
  10866.     for c = 1 to G_SIZE do
  10867.         gquad(r, c)
  10868.     end for
  10869.     end for
  10870. end procedure
  10871.  
  10872. global procedure pobj()
  10873. -- print objects in a new quadrant
  10874.     h_coord x
  10875.     v_coord y
  10876.     sequence c
  10877.     natural len, height
  10878.     object_type t
  10879.     sequence taken
  10880.  
  10881.     -- print dull stars
  10882.     for i = 1 to 40 do
  10883.     x = rand(HSIZE)
  10884.     y = rand(VSIZE)
  10885.     screen[y][x] = STAR2
  10886.     if not scanon then
  10887.         pixel(STAR2, {x-1, y-1})
  10888.     end if
  10889.     end for
  10890.     
  10891.     -- print brighter stars
  10892.     for i = 1 to 15 do
  10893.     x = rand(HSIZE)
  10894.     y = rand(VSIZE)
  10895.     screen[y][x] = STAR1
  10896.     if not scanon then
  10897.         pixel(STAR1, {x-1, y-1})
  10898.     end if
  10899.     end for
  10900.     
  10901.     -- print planets and bases
  10902.     taken = {}
  10903.     for row = 2 to length(quadrant) do
  10904.     if find(quadrant[row][Q_TYPE], {G_PL, G_BS}) then
  10905.         -- look it up in pb sequence
  10906.         for pbi = 1 to length(pb) do
  10907.         if pb[pbi][P_TYPE] = quadrant[row][Q_TYPE] then
  10908.             if pb[pbi][P_QR] = qrow and pb[pbi][P_QC] = qcol then
  10909.             if not find(pbi, taken) then
  10910.                 quadrant[row][Q_X] = pb[pbi][P_X]
  10911.                 quadrant[row][Q_Y] = pb[pbi][P_Y]
  10912.                 quadrant[row][Q_PBX] = pbi
  10913.                 taken &= pbi
  10914.                 exit
  10915.             end if
  10916.             end if
  10917.         end if
  10918.         end for
  10919.         p_source(row)
  10920.     end if
  10921.     end for
  10922.  
  10923.     -- print ships
  10924.     for row = 2 to length(quadrant) do
  10925.     if not find(quadrant[row][Q_TYPE], {G_PL, G_BS})  then
  10926.         height = length(oshape[quadrant[row][Q_TYPE]][1])
  10927.         len =    length(oshape[quadrant[row][Q_TYPE]][1][1])
  10928.         -- look for an empty place to put the ship. 
  10929.         -- Euphoria is already in the quadrant.
  10930.         while TRUE do
  10931.         x = rand(HSIZE - len + 1) 
  10932.         y = rand(VSIZE - height + 1)
  10933.         c = read_screen(x, y, oshape[quadrant[row][Q_TYPE]][1])
  10934.         if all_clear(c) then
  10935.             exit -- found a good place
  10936.         end if
  10937.         end while
  10938.         quadrant[row][Q_UNDER] = c
  10939.         quadrant[row][Q_X] = x
  10940.         quadrant[row][Q_Y] = y
  10941.         t = quadrant[row][Q_TYPE]
  10942.         if x < quadrant[EUPHORIA][Q_X] then
  10943.         c = oshape[t][2]
  10944.         else
  10945.         c = oshape[t][1]
  10946.         end if
  10947.         write_screen(x, y, c)
  10948.     end if
  10949.     end for
  10950. end procedure
  10951. EMOVE.E
  10952. 8252
  10953. -- emove.e
  10954. -- move the Euphoria
  10955.  
  10956. -- Energy consumed per ship movement at warp 0 thru 5.
  10957. -- WARP 4 is the most efficient after you take life support
  10958. -- energy into account. WARP 5 is good if you can use it to avoid
  10959. -- getting blasted.
  10960.  
  10961. constant fuel = {0, 0.5, 1, 2, 4, 9}
  10962.  
  10963. global function gmod(natural x)
  10964. -- quadrant wraparound
  10965.     if x = 0 then
  10966.     return G_SIZE
  10967.     elsif x > G_SIZE then
  10968.     return 1
  10969.     else
  10970.     return x
  10971.     end if
  10972. end function
  10973.  
  10974. constant ZERO_FILL = repeat(0, QCOLS-7)
  10975.  
  10976. -- standard row in quadrant sequence for a type
  10977. global constant stdtype =
  10978. -- TYPE    EN    TORP    DEFL  FRATE  MRATE   TARG
  10979. {{}, -- dummy (Euphoria)
  10980.  {G_KRC,  4000,  2,       0,   100,   160,  EUPHORIA} & ZERO_FILL, -- K&R C
  10981.  {G_ANC,  8000,  4,       0,   100,   200,  EUPHORIA} & ZERO_FILL, -- ANSI C
  10982.  {G_CPP, 25000, 10,       0,   200,   250,  EUPHORIA} & ZERO_FILL, -- C++
  10983.  {G_BAS,  2000,  2,       0,    70,   150,  EUPHORIA} & ZERO_FILL, -- BASIC
  10984.  {G_JAV,  3000,  0,       0,    40,    90,   -1}      & ZERO_FILL, -- Java
  10985.  {G_PL,   7000,  0,       0,     0,     0,   -1}      & ZERO_FILL, -- planet
  10986.  {G_BS,   6000,  5,       1,   120,     0,   -1}      & ZERO_FILL  -- base
  10987. }
  10988.  
  10989. procedure setup_quadrant()
  10990. -- set up quadrant sequence for a new quadrant
  10991.  
  10992.     sequence g_info
  10993.  
  10994.     g_info = galaxy[qrow][qcol]
  10995.     quadrant = quadrant[EUPHORIA..EUPHORIA]
  10996.  
  10997.     for i = 1 to g_info[G_ANC] do
  10998.     quadrant = append(quadrant, stdtype[G_ANC])
  10999.     quadrant[length(quadrant)][Q_UNDER] = oshape[G_ANC] * 0
  11000.     end for
  11001.  
  11002.     for i = 1 to g_info[G_KRC] do
  11003.     quadrant = append(quadrant, stdtype[G_KRC])
  11004.     quadrant[length(quadrant)][Q_UNDER] = oshape[G_KRC] * 0
  11005.     end for
  11006.     
  11007.     for i = 1 to g_info[G_CPP] do
  11008.     quadrant = append(quadrant, stdtype[G_CPP])
  11009.     quadrant[length(quadrant)][Q_UNDER] = oshape[G_CPP] * 0
  11010.     end for
  11011.  
  11012.     for i = 1 to g_info[G_BS] do
  11013.     quadrant = append(quadrant, stdtype[G_BS])
  11014.     end for
  11015.  
  11016.     for i = 1 to g_info[G_PL] do
  11017.     quadrant = append(quadrant, stdtype[G_PL])
  11018.     end for
  11019.  
  11020.     basic_targ = -1
  11021.     for i = 1 to g_info[G_BAS] do
  11022.     quadrant = append(quadrant, stdtype[G_BAS])
  11023.     quadrant[length(quadrant)][Q_UNDER] = oshape[G_BAS] * 0
  11024.     basic_targ = EUPHORIA
  11025.     end for
  11026.  
  11027.     for i = 1 to g_info[G_JAV] do
  11028.     quadrant = append(quadrant, stdtype[G_JAV])
  11029.     quadrant[length(quadrant)][Q_UNDER] = oshape[G_JAV] * 0
  11030.     end for
  11031.  
  11032. end procedure
  11033.  
  11034. boolean contacted, allowed_to_dock
  11035. contacted = FALSE
  11036. allowed_to_dock = TRUE
  11037.  
  11038. function dock(h_coord x, v_coord y)
  11039. -- Euphoria docks with a base or planet at (x,y)
  11040.  
  11041.     object_type t
  11042.     valid_quadrant_row r
  11043.     sequence who
  11044.     pb_row pbr
  11045.     natural maxen, torp, availtorp, xdiff, ydiff
  11046.     positive_atom energy, availen
  11047.     extended_h_coord newx 
  11048.     extended_v_coord newy
  11049.     
  11050.     who = who_is_it(x, y, esym)
  11051.     r = EUPHORIA
  11052.     for i = 1 to length(who) do
  11053.     -- if any base or planet, then we are bumping it (docking)
  11054.     if find(quadrant[who[i]][Q_TYPE], {G_BS, G_PL}) then
  11055.         r = who[i]
  11056.     end if
  11057.     end for
  11058.     t = quadrant[r][Q_TYPE]
  11059.     if t = G_PL or t = G_BS then
  11060.     if curwarp != 1 then
  11061.         if not contacted then
  11062.         contacted = TRUE
  11063.         if t = G_PL then
  11064.             fmsg("PLANET TO %s: PLEASE DOCK AT WARP 1", {otype[G_EU]})
  11065.         else
  11066.             fmsg("BASE TO %s: PLEASE DOCK AT WARP 1", {otype[G_EU]})
  11067.         end if
  11068.         end if
  11069.         return FALSE
  11070.     end if
  11071.     if not allowed_to_dock then
  11072.         return FALSE
  11073.     end if
  11074.     -- perform the docking
  11075.     pbr = quadrant[r][Q_PBX]
  11076.     if pb[pbr][P_POD] > 0 then
  11077.         pb[pbr][P_POD] -= 1
  11078.         ps &= POD_SYM
  11079.     end if
  11080.     torp = 10 - quadrant[EUPHORIA][Q_TORP]
  11081.     availtorp = pb[pbr][P_TORP]
  11082.     if torp > availtorp then
  11083.         torp = availtorp
  11084.     end if
  11085.     pb[pbr][P_TORP] = availtorp - torp
  11086.     torp += quadrant[EUPHORIA][Q_TORP]
  11087.     quadrant[EUPHORIA][Q_TORP] = torp
  11088.     ts = repeat(TORP_SYM, torp)
  11089.     if t = G_BS then
  11090.         -- extra stuff you get at a base
  11091.         for i = 1 to NSYS do
  11092.         -- fix each subsystem
  11093.         if reptime[i] then
  11094.             reptime[i] = 0
  11095.             repair(i)
  11096.         end if
  11097.         end for
  11098.         if shuttle then
  11099.         -- if there's room, restore larger EUPHORIA ship
  11100.         newx = quadrant[EUPHORIA][Q_X]
  11101.         newy = quadrant[EUPHORIA][Q_Y]
  11102.         if quadrant[r][Q_X] > quadrant[EUPHORIA][Q_X] then
  11103.             xdiff = length(EUPHORIA_L[1]) - length(SHUTTLE_L[1])
  11104.             newx -= xdiff
  11105.         end if
  11106.         if quadrant[r][Q_Y] > quadrant[EUPHORIA][Q_Y] then
  11107.             ydiff = length(EUPHORIA_L) - length(SHUTTLE_L)
  11108.             newy -= ydiff
  11109.         end if
  11110.         if h_coord(newx) and 
  11111.            v_coord(newy) and 
  11112.            -- short circuit avoids error:
  11113.             all_clear(read_screen(newx, newy, EUPHORIA_L)) then 
  11114.             -- restore larger ship
  11115.             quadrant[EUPHORIA][Q_X] = newx
  11116.             quadrant[EUPHORIA][Q_Y] = newy
  11117.             esyml = EUPHORIA_L
  11118.             esymr = EUPHORIA_R
  11119.             if equal(esym[1], SHUTTLE_L[1]) then
  11120.             esym = EUPHORIA_L
  11121.             else
  11122.             esym = EUPHORIA_R
  11123.             end if
  11124.             otype[G_EU] = "EUPHORIA"
  11125.             oshape[G_EU] = {EUPHORIA_L, EUPHORIA_R}
  11126.             shuttle = FALSE
  11127.         end if
  11128.         end if
  11129.         quadrant[EUPHORIA][Q_DEFL] = 3
  11130.         ds = repeat(DEFL_SYM, 3)
  11131.     end if
  11132.     if shuttle then
  11133.         maxen = 5000
  11134.     else
  11135.         maxen = 50000
  11136.     end if
  11137.     energy = maxen - quadrant[EUPHORIA][Q_EN]
  11138.     availen = pb[pbr][P_EN]
  11139.     if energy > availen then
  11140.         energy = availen
  11141.     end if
  11142.     pb[pbr][P_EN] = availen - energy
  11143.     quadrant[EUPHORIA][Q_EN] += energy
  11144.     p_energy(0)
  11145.     wtext()
  11146.     docking_sound()
  11147.     upg(qrow, qcol)
  11148.     msg("DOCKING COMPLETED")
  11149.     allowed_to_dock = FALSE -- until it moves free again
  11150.     return TRUE
  11151.     end if
  11152.     return FALSE
  11153. end function
  11154.  
  11155. type increment(integer x)
  11156.     return x = -1 or x = 0 or x = +1
  11157. end type
  11158.  
  11159. global function task_emove()
  11160. -- independent task: move the Euphoria
  11161.     h_coord x, exold
  11162.     v_coord y, eyold
  11163.     increment eqx, eqy
  11164.     sequence c
  11165.     
  11166.     if curwarp > wlimit then
  11167.     if curwarp - wlimit > rand(12) then
  11168.         msg("ALL ENGINES DAMAGED")
  11169.         wlimit = 0
  11170.         reptime[ENGINES] += rand(11)
  11171.         setwarp(0)
  11172.         return {}
  11173.     end if
  11174.     end if
  11175.     eqx = 0
  11176.     eqy = 0
  11177.     exold = quadrant[EUPHORIA][Q_X]
  11178.     eyold = quadrant[EUPHORIA][Q_Y]
  11179.     quadrant[EUPHORIA][Q_X] += exi
  11180.     quadrant[EUPHORIA][Q_Y] += eyi
  11181.  
  11182.     -- check for switching quadrants:
  11183.  
  11184.     if quadrant[EUPHORIA][Q_X] > HSIZE - length(esym[1]) + 1 then
  11185.     quadrant[EUPHORIA][Q_X] = 1
  11186.     eqx = 1
  11187.     elsif quadrant[EUPHORIA][Q_X] < 1 then
  11188.     quadrant[EUPHORIA][Q_X] = HSIZE - length(esym[1]) + 1
  11189.     eqx = -1
  11190.     end if
  11191.  
  11192.     if quadrant[EUPHORIA][Q_Y] > VSIZE - length(esym) + 1 then
  11193.     quadrant[EUPHORIA][Q_Y] = 1
  11194.     eqy = 1
  11195.     elsif quadrant[EUPHORIA][Q_Y] < 1 then
  11196.     quadrant[EUPHORIA][Q_Y] = VSIZE - length(esym) + 1
  11197.     eqy = -1
  11198.     end if
  11199.  
  11200.     if shuttle then
  11201.     quadrant[EUPHORIA][Q_EN] -= fuel[curwarp+1]/6
  11202.     else
  11203.     quadrant[EUPHORIA][Q_EN] -= fuel[curwarp+1]
  11204.     end if
  11205.     if quadrant[EUPHORIA][Q_EN] <= 0 then
  11206.     p_energy(0)
  11207.     end if
  11208.     c = quadrant[EUPHORIA][Q_UNDER]
  11209.     delayed_write_screen(exold, eyold, c) -- avoid flicker
  11210.     if eqx != 0 or eqy != 0 then
  11211.     -- new quadrant
  11212.     flush_screen()
  11213.     stop_weapons()
  11214.     wipeout = {}
  11215.     purge_tasks(routine_id("task_explosion"))
  11216.     qcol = gmod(qcol + eqx)
  11217.     qrow = gmod(qrow + eqy)
  11218.     BlackScreen()
  11219.     setup_quadrant()
  11220.     for i = 2 to length(quadrant) do
  11221.         if quadrant[i][Q_TYPE] = G_JAV then
  11222.         quadrant[i][Q_TARG] = Java_target(i)
  11223.         end if
  11224.     end for
  11225.     sched_move_fire()
  11226.     galaxy[qrow][qcol][1] = TRUE
  11227.     msg("")
  11228.     end if
  11229.     x = quadrant[EUPHORIA][Q_X]
  11230.     y = quadrant[EUPHORIA][Q_Y]
  11231.     c = read_screen(x, y, esym)
  11232.     if all_clear(c) then
  11233.     contacted = FALSE -- no longer bumping a base/planet
  11234.     allowed_to_dock = TRUE
  11235.     else    
  11236.     -- there's something in our way
  11237.     quadrant[EUPHORIA][Q_X] = exold
  11238.     quadrant[EUPHORIA][Q_Y] = eyold
  11239.     if not dock(x, y) then -- docking could change esym
  11240.         end_scan()
  11241.     end if
  11242.     x = quadrant[EUPHORIA][Q_X]
  11243.     y = quadrant[EUPHORIA][Q_Y]
  11244.     c = read_screen(x, y, esym)
  11245.     end if
  11246.     delayed_write_screen(x, y, esym)
  11247.     flush_screen()
  11248.     if eqx != 0 or eqy != 0 then
  11249.     -- print other guys after EUPHORIA is in new quadrant
  11250.     pobj()
  11251.     gsbox(qrow, qcol)
  11252.     end if
  11253.     c *= (c > 64) -- keep stars, discard phasor/torpedo dust
  11254.     quadrant[EUPHORIA][Q_UNDER] = c
  11255.     return {}
  11256. end function
  11257.  
  11258. ENEMY.E
  11259. 10794
  11260. -- enemy.e
  11261. -- operate the enemy ships
  11262.  
  11263. procedure set_basic_color()
  11264. -- set new color and "shape" for BASIC ships after truce/hostile change
  11265.     sequence shape, new_shape
  11266.  
  11267.     for i = 2 to length(quadrant) do
  11268.     if quadrant[i][Q_TYPE] = G_BAS then
  11269.         shape = read_screen(quadrant[i][Q_X], quadrant[i][Q_Y], BASIC_L)
  11270.         -- reprint with new shape & color
  11271.         if equal(shape, BASIC_L) then
  11272.         new_shape = oshape[G_BAS][1]
  11273.         else
  11274.         new_shape = oshape[G_BAS][2]
  11275.         end if
  11276.         write_screen(quadrant[i][Q_X], quadrant[i][Q_Y], new_shape)
  11277.     end if
  11278.     end for
  11279. end procedure
  11280.  
  11281. global function task_bstat()
  11282. -- independent task: BASIC status change
  11283.  
  11284.     positive_atom w
  11285.     natural prevstat
  11286.     
  11287.     prevstat = bstat
  11288.     w = rand(200) + rand(200) + 20
  11289.     if bstat = TRUCE then
  11290.     if truce_broken then
  11291.         truce_broken = FALSE
  11292.         msg("TRUCE BROKEN!")
  11293.     else
  11294.         msg("BASIC STATUS: HOSTILE")
  11295.     end if
  11296.     if rand(20) < 16 then
  11297.         -- switch to hostile
  11298.         w *= 1.2
  11299.         oshape[G_BAS] = {BASIC_L, BASIC_R}
  11300.         oshape[G_BAS] = BLUE * (and_bits(oshape[G_BAS], #F) != 0)
  11301.                 + 32 * (oshape[G_BAS] = 32)
  11302.         bstat = HOSTILE
  11303.     else
  11304.         -- switch to cloaking
  11305.         w *= .6
  11306.         oshape[G_BAS] = INVISIBLE_CHAR * (oshape[G_BAS] = oshape[G_BAS])
  11307.         bstat = CLOAKING
  11308.     end if
  11309.     else
  11310.     -- hostile/cloaking
  11311.     if rand(20) < 10 then
  11312.         -- switch to truce
  11313.         bstat = TRUCE
  11314.         msg("BASIC STATUS: TRUCE")
  11315.         w *= .83
  11316.         oshape[G_BAS] = {BASIC_L, BASIC_R}
  11317.     else
  11318.         if bstat = HOSTILE then
  11319.         -- hostile --> cloaking
  11320.         w *= .6
  11321.         bstat = CLOAKING
  11322.         oshape[G_BAS] = INVISIBLE_CHAR * (oshape[G_BAS] = oshape[G_BAS])
  11323.         else
  11324.         -- cloaking --> hostile
  11325.         w *= 1.2
  11326.         bstat = HOSTILE
  11327.         oshape[G_BAS] = {BASIC_L, BASIC_R}
  11328.         oshape[G_BAS] = BLUE * (and_bits(oshape[G_BAS], #F) != 0)
  11329.                 + 32 * (oshape[G_BAS] = 32)
  11330.         end if
  11331.     end if
  11332.     end if
  11333.     set_basic_color()
  11334.     if scanon then
  11335.     gtext()
  11336.     if bstat = CLOAKING or prevstat = CLOAKING then
  11337.         refresh_scan()
  11338.     end if
  11339.     end if
  11340.     schedule(t_bstat, w, w, 0.2, {})
  11341.     return {}
  11342. end function
  11343.  
  11344. procedure orient(valid_quadrant_row row)
  11345. -- point the ship toward its target
  11346.  
  11347.     quadrant_row targ
  11348.     h_coord targx, rowx
  11349.     v_coord rowy
  11350.     object_type t
  11351.  
  11352.     targ = quadrant[row][Q_TARG]
  11353.     if targ = -1 then
  11354.     -- no target
  11355.     return
  11356.     end if
  11357.     targx = quadrant[targ][Q_X]
  11358.     rowx = quadrant[row][Q_X]
  11359.     rowy = quadrant[row][Q_Y]
  11360.     t = quadrant[row][Q_TYPE]
  11361.     if rowx < targx-4 then
  11362.     write_screen(rowx, rowy, oshape[t][2])
  11363.     elsif rowx > targx+4 then
  11364.     write_screen(rowx, rowy, oshape[t][1])
  11365.     end if
  11366. end procedure
  11367.  
  11368. procedure shoot(valid_quadrant_row shooter)
  11369. -- select torpedo or phasor for enemy shot
  11370.  
  11371.     natural torp
  11372.     positive_atom pen
  11373.     boolean w
  11374.     
  11375.     torp = quadrant[shooter][Q_TORP]
  11376.     w = torp > 0 and rand(4) = 1
  11377.     setpt(shooter, w)
  11378.     if w then
  11379.     quadrant[shooter][Q_TORP] = torp - 1
  11380.     torpedo(shooter)
  11381.     else
  11382.     pen = quadrant[shooter][Q_EN] / 8
  11383.     if quadrant[shooter][Q_TYPE] = G_JAV then
  11384.         Java_phasor(shooter, pen)
  11385.     else
  11386.         phasor(shooter, pen)
  11387.     end if
  11388.     quadrant[shooter][Q_EN] -= pen
  11389.     end if
  11390. end procedure
  11391.  
  11392.  
  11393. global function task_fire()
  11394. -- independent task: select an enemy ship for firing
  11395.  
  11396.     quadrant_row row
  11397.     natural rate
  11398.     quadrant_row targ
  11399.  
  11400.     if length(quadrant) = 1 then
  11401.     return {}  -- nobody in the quadrant except Euphoria
  11402.     end if
  11403.  
  11404.     row = rand(length(quadrant)-1) + EUPHORIA  -- choose a random ship
  11405.     if quadrant[row][Q_TYPE] = DEAD then
  11406.     row = rand(length(quadrant)-1) + EUPHORIA  -- try once more
  11407.     if quadrant[row][Q_TYPE] = DEAD then
  11408.         return {}
  11409.     end if
  11410.     end if
  11411.     rate = quadrant[row][Q_FRATE]
  11412.     if rate > rand(256) then
  11413.     -- shoot
  11414.     if quadrant[row][Q_TYPE] = G_BAS then
  11415.         if bstat != TRUCE then
  11416.         shoot(row)
  11417.         else
  11418.         if basic_targ != EUPHORIA then
  11419.             if quadrant[basic_targ][Q_TYPE] != G_BS then
  11420.             shoot(row)
  11421.             end if
  11422.         end if
  11423.         end if
  11424.  
  11425.     elsif quadrant[row][Q_TYPE] = G_BS then
  11426.         targ = quadrant[row][Q_TARG]
  11427.         if targ != -1 then
  11428.         if bstat != TRUCE then
  11429.             shoot(row)
  11430.         elsif quadrant[targ][Q_TYPE] != G_BAS then
  11431.             shoot(row)
  11432.         end if
  11433.         end if
  11434.  
  11435.     else
  11436.         shoot(row)
  11437.     end if
  11438.     end if
  11439.     return {}
  11440. end function
  11441.  
  11442. global function task_move()
  11443. -- independent task: select an enemy ship for moving
  11444.  
  11445.     quadrant_row row
  11446.     natural mrate
  11447.     h_coord fx
  11448.     v_coord fy
  11449.     extended_h_coord xtry
  11450.     extended_v_coord ytry
  11451.     image fchar, schar
  11452.     natural t
  11453.     object direction
  11454.     
  11455.     if length(quadrant) = 1 then
  11456.     return {}  -- nobody in the quadrant
  11457.     end if
  11458.  
  11459.     row = rand(length(quadrant)-1) + EUPHORIA  -- choose a random ship
  11460.     t = quadrant[row][Q_TYPE]
  11461.     if t = DEAD then
  11462.     return {}
  11463.     end if
  11464.     mrate = quadrant[row][Q_MRATE]
  11465.     if mrate > rand(256) then
  11466.     -- try to move
  11467.     fx = quadrant[row][Q_X]
  11468.     fy = quadrant[row][Q_Y]
  11469.     direction = quadrant[row][Q_DIRECTION]
  11470.     if atom(direction) or rand(25) = 1 then
  11471.         -- pick a new direction
  11472.         xtry = fx + rand(7) - 4
  11473.         ytry = fy + rand(7) - 4
  11474.     else
  11475.         xtry = fx + direction[1]
  11476.         ytry = fy + direction[2]
  11477.     end if
  11478.     if xtry >= 2 and xtry <= HSIZE - length(oshape[t][1][1]) and
  11479.        ytry >= 1 and ytry <= VSIZE - length(oshape[t][1]) then
  11480.         fchar = read_screen(fx, fy, oshape[t][1])
  11481.         write_screen(fx, fy, quadrant[row][Q_UNDER])
  11482.         schar = read_screen(xtry, ytry, oshape[t][1])
  11483.         if all_clear(schar) then
  11484.         -- keep stars, lose phasor/torpedo dust
  11485.         schar *= (schar > 64)
  11486.         quadrant[row][Q_UNDER] = schar
  11487.         write_screen(xtry , ytry, fchar)
  11488.         quadrant[row][Q_X] = xtry
  11489.         quadrant[row][Q_Y] = ytry
  11490.         quadrant[row][Q_DIRECTION] = {xtry-fx, ytry-fy}
  11491.         else
  11492.         write_screen(fx, fy, fchar) -- put it back
  11493.         end if
  11494.     else
  11495.         -- direction is bad
  11496.         quadrant[row][Q_DIRECTION] = 0 
  11497.     end if
  11498.     orient(row)
  11499.     end if
  11500.     return {}
  11501. end function
  11502.  
  11503. function add2quadrant(object_type t, h_coord x, v_coord y)
  11504. -- add a ship to the quadrant sequence 
  11505.  
  11506.     quadrant_row targ
  11507.     valid_quadrant_row row
  11508.     image c
  11509.  
  11510.     -- try to reuse a place in quadrant sequence
  11511.     row = 1
  11512.     for i = 2 to length(quadrant) do
  11513.     if quadrant[i][Q_TYPE] = DEAD then
  11514.        row = i
  11515.        exit
  11516.     end if
  11517.     end for
  11518.     if row = 1 then
  11519.     -- all slots in use - add a new row
  11520.     quadrant = append(quadrant, repeat(0, length(quadrant[1])))
  11521.     row = length(quadrant)
  11522.     end if
  11523.  
  11524.     -- choose his target
  11525.     if t < G_BAS then
  11526.     if galaxy[qrow][qcol][G_BS] then
  11527.         for r = 2 to length(quadrant) do
  11528.         if quadrant[r][Q_TYPE] = G_BS then
  11529.             targ = r
  11530.             exit
  11531.         end if
  11532.         end for
  11533.     else
  11534.         targ = EUPHORIA
  11535.     end if
  11536.     elsif t = G_BAS then
  11537.     if basic_targ = -1 then
  11538.         if galaxy[qrow][qcol][G_BS] then
  11539.         for r = 2 to length(quadrant) do
  11540.             if quadrant[r][Q_TYPE] = G_BS then
  11541.             basic_targ = r
  11542.             exit
  11543.             end if
  11544.         end for
  11545.         else
  11546.         basic_targ = EUPHORIA
  11547.         end if
  11548.     end if
  11549.     targ = basic_targ
  11550.     else
  11551.     targ = Java_target(row)
  11552.     end if
  11553.  
  11554.     quadrant[row] = stdtype[t]
  11555.     quadrant[row][Q_X] = x
  11556.     quadrant[row][Q_Y] = y
  11557.     c = read_screen(x, y, oshape[t][1])
  11558.     c *= (c > 64)
  11559.     quadrant[row][Q_UNDER] = c
  11560.     quadrant[row][Q_TARG] = targ
  11561.     if x < quadrant[EUPHORIA][Q_X] then
  11562.     c = oshape[t][2]
  11563.     else
  11564.     c = oshape[t][1]
  11565.     end if
  11566.     write_screen(x, y, c)
  11567.     return TRUE
  11568. end function
  11569.  
  11570. global function task_enter()
  11571. -- independent task: enemy ship enters quadrant
  11572.  
  11573.     natural q
  11574.     h_coord enterx, max_h
  11575.     v_coord entery, max_v
  11576.     natural entert
  11577.     sequence enterc
  11578.     g_index randcol, randrow, fromcol, fromrow
  11579.     image shape
  11580.     
  11581.     schedule(t_enter, 0,  3 + rand(30) * (curwarp > 2) + 
  11582.                quadrant[EUPHORIA][Q_EN]/(3000 + rand(6000)), 0.5, {})
  11583.     if rand(3+7*(level = 'n')) != 1 then
  11584.     return {}  -- adjust wait time only
  11585.     end if
  11586.  
  11587.     for i = 1 to 2 do
  11588.     entert = 0
  11589.     q = rand(8)
  11590.     if q = 1 then     -- left
  11591.         fromrow = qrow
  11592.         fromcol = gmod(qcol-1)
  11593.     
  11594.     elsif q = 2 then  -- top left
  11595.         fromrow = gmod(qrow-1)
  11596.         fromcol = gmod(qcol-1)
  11597.     
  11598.     elsif q = 3 then  -- top
  11599.         fromrow = gmod(qrow-1)
  11600.         fromcol = qcol
  11601.     
  11602.     elsif q = 4 then  -- top right
  11603.         fromrow = gmod(qrow-1)
  11604.         fromcol = gmod(qcol+1)
  11605.     
  11606.     elsif q = 5 then  -- right
  11607.         fromrow = qrow
  11608.         fromcol = gmod(qcol+1)
  11609.     
  11610.     elsif q = 6 then  -- bottom right
  11611.         fromrow = gmod(qrow+1)
  11612.         fromcol = gmod(qcol+1)
  11613.     
  11614.     elsif q = 7 then  -- bottom
  11615.         fromrow = gmod(qrow+1)
  11616.         fromcol = qcol
  11617.     
  11618.     else              -- bottom left
  11619.         fromrow = gmod(qrow+1)
  11620.         fromcol = gmod(qcol-1)
  11621.     
  11622.     end if
  11623.     if galaxy[fromrow][fromcol][G_CPP] then
  11624.         entert = G_CPP -- two tries to pick C++ to enter
  11625.         exit
  11626.     end if
  11627.     end for
  11628.     if entert = G_CPP then
  11629.     -- C++
  11630.     elsif galaxy[fromrow][fromcol][G_ANC] then
  11631.     entert = G_ANC
  11632.     elsif galaxy[fromrow][fromcol][G_KRC] then
  11633.     entert = G_KRC
  11634.     else
  11635.     randcol = rand(G_SIZE)
  11636.     randrow = rand(G_SIZE)
  11637.     if randcol != qrow or randcol != qcol then
  11638.         if galaxy[randrow][randcol][G_JAV] then
  11639.         fromrow = randrow
  11640.         fromcol = randcol
  11641.         enterx = rand(HSIZE-length(oshape[G_JAV][1][1]))
  11642.         entery = rand(VSIZE-length(oshape[G_JAV][1])+1)
  11643.         entert = G_JAV
  11644.         end if
  11645.     end if
  11646.     end if
  11647.     if entert = 0 then
  11648.     if galaxy[fromrow][fromcol][G_BAS] then
  11649.         entert = G_BAS
  11650.     end if
  11651.     end if
  11652.     if entert then
  11653.     shape = oshape[entert][1]
  11654.     if entert != G_JAV then
  11655.         max_v = VSIZE - length(shape) + 1
  11656.         max_h = HSIZE - length(shape[1]) + 1
  11657.         if q = 1 then     -- left
  11658.         enterx = 1
  11659.         entery = rand(max_v)
  11660.         
  11661.         elsif q = 2 then  -- top left
  11662.         enterx = 1
  11663.         entery = 1
  11664.         
  11665.         elsif q = 3 then  -- top
  11666.         enterx = rand(max_h)
  11667.         entery = 1
  11668.         
  11669.         elsif q = 4 then  -- top right
  11670.         enterx = max_h
  11671.         entery = 1
  11672.         
  11673.         elsif q = 5 then  -- right
  11674.         enterx = max_h
  11675.         entery = rand(max_v)
  11676.         
  11677.         elsif q = 6 then  -- bottom right
  11678.         enterx = max_h
  11679.         entery = max_v
  11680.         
  11681.         elsif q = 7 then  -- bottom
  11682.         enterx = rand(max_h)
  11683.         entery = max_v
  11684.         
  11685.         else              -- bottom left                
  11686.         enterx = 1
  11687.         entery = max_v
  11688.         
  11689.         end if      
  11690.     end if
  11691.     
  11692.     enterc = read_screen(enterx, entery, shape)
  11693.     if not all_clear(enterc) then
  11694.         return {}
  11695.     end if
  11696.     if add2quadrant(entert, enterx, entery) then
  11697.         galaxy[qrow][qcol][entert] += 1
  11698.         galaxy[fromrow][fromcol][entert] -= 1
  11699.         upg(qrow, qcol)
  11700.         upg(fromrow, fromcol)
  11701.         if entert = G_JAV then
  11702.         Java_enter_sound()
  11703.         end if
  11704.         fmsg("%s HAS ENTERED QUADRANT", {otype[entert]})
  11705.         sched_move_fire()
  11706.     end if
  11707.     end if
  11708.     return {}
  11709. end function
  11710.  
  11711. LW.DOC
  11712. 18720
  11713.             ============
  11714.             Language War
  11715.             ============
  11716.  
  11717.  Open a full-screen DOS window (press Alt-Enter) and type:
  11718.       
  11719.       ex lw
  11720.  
  11721.  More games, with faster action and Sound Blaster sound effects, await you on 
  11722.  the Euphoria Web site:
  11723.       
  11724.       http://members.aol.com/FilesEu/
  11725.       
  11726.       - click the "Archive" link and then click "Games"
  11727.       
  11728.  
  11729.  Object of the Game
  11730.  ------------------
  11731.  It's the year 2399. The galaxy is dominated by the evil forces of the
  11732.  C empire. Programmers' minds are being enslaved to the C language. Your 
  11733.  objective as commander of the Euphoria is to rid the galaxy of the 50 C ships
  11734.  and spread euphoria throughout the galaxy. 40 of these evil ships are regular
  11735.  C ships, 9 are the more powerful ANSI C ships, and a single ship, lurking 
  11736.  somewhere in the galaxy is the extremely powerful and terrifying C++.
  11737.  
  11738.  You will encounter other ships in the galaxy as well. These are the BASIC 
  11739.  ships and the Java ships, remnants of previous empires. While it is not 
  11740.  your prime objective to destroy these ships, they will at times attack you 
  11741.  and you will want to eliminate them. This is particularly true when they 
  11742.  threaten friendly bases and planets. 
  11743.  
  11744.  Start at the novice level -- type 'n' to start the game. At the novice level 
  11745.  the enemy ships don't move around as much, or shoot at you as often.
  11746.  When you are able to win at the novice level, move up to the expert level. 
  11747.  Type 'e' or just hit Enter for the expert level.
  11748.  
  11749.  
  11750.  Moving the Euphoria through space
  11751.  ---------------------------------
  11752.  The galaxy consists of 49 quadrants arranged in a 7x7 grid. Due to the
  11753.  curvature of space, when you travel off the edge of the galaxy you will
  11754.  arrive in the quadrant on the opposite side. At any one time you can only
  11755.  see the action taking place in the current quadrant that you are located in.
  11756.  When you move past the edge of the screen you enter an adjacent quadrant.
  11757.  
  11758.  The ship moves at a certain warp speed from 0 to 5, and a certain direction
  11759.  from 1 to 8 as shown below. 
  11760.  
  11761.                      directions
  11762.  
  11763.                          3
  11764.                     4    |    2
  11765.                          |   
  11766.                   5------+------1
  11767.                          |
  11768.                     6    |    8
  11769.                          7 
  11770.  
  11771.  To move at warp 3 in direction 2 you would type
  11772.  
  11773.      w 3
  11774.      2
  11775.      (or 2 w 3)
  11776.  
  11777.  i.e. entering a number from 1 to 8 by itself will set your direction.
  11778.  You cannot move in a fractional direction. Your current direction is 
  11779.  displayed in the navigation box in the lower left of the screen. This box 
  11780.  also serves to remind you of the directions for firing weapons.
  11781.  
  11782.  
  11783.  Weapon Systems (in General)
  11784.  ---------------------------
  11785.  Ships fire phasors with a certain amount of input energy. The impact of the 
  11786.  phasor diminishes with distance to the target but the enemy always loses more
  11787.  energy than was put into the phasor. A ship loses energy when it fires a
  11788.  phasor, whether the phasor hits or not. Torpedos pack a 4000-unit impact
  11789.  regardless of the distance to the target. A torpedo will be neutralized
  11790.  by a torpedo deflector, if one exists on the target ship.
  11791.  
  11792.  
  11793.  Weapons on board the Euphoria
  11794.  -----------------------------
  11795.  The Euphoria comes equipped with conventional phasors and torpedos. It can 
  11796.  also fire an extremely powerful antimatter pod. The Euphoria stores a maximum
  11797.  of 50000 units of energy, and must be refueled at either a base or a planet. 
  11798.  It carries up to 10 torpedos, 3 torpedo deflectors and 4 antimatter pods. 
  11799.  Weapons and deflectors can only be replenished at a base. They appear on 
  11800.  your console as up-arrow, semi-circle, and circular pod shapes. 
  11801.  
  11802.  You can fire a phasor with input energy from 000 to 900 units. This input 
  11803.  energy is deducted from the amount that the Euphoria has left. To fire a 
  11804.  500-unit phasor in direction 1.0 type:
  11805.       
  11806.       p 5 1 0
  11807.  
  11808.  To fire a torpedo in direction 3.9 type:
  11809.       
  11810.       t 3 9
  11811.  
  11812.  To fire an antimatter pod in direction 2.1 type:
  11813.       
  11814.       a 2 1   ... then press Enter to detonate
  11815.  
  11816.  Exactly 2 digits are required on directions for weapons. The '.' is
  11817.  displayed automatically for you - you don't actually type it. The torpedo, 
  11818.  pod or phasor originates from a point near the middle of the Euphoria.
  11819.  
  11820.  Occasionally, you may need more than 2-digit precision, especially when the 
  11821.  target is far away from you. You can adjust the fine control on your
  11822.  weapons by adding '<' (less than) or '>' (greater than) to the direction.
  11823.  For example, if both 1.5 and 1.6 miss the enemy, type:
  11824.  
  11825.       t 1 > 5    "tee one, greater than five"
  11826.  
  11827.  to get, effectively t 1.533. Or type:
  11828.   
  11829.       t 1 < 6    "tee one, less than six"
  11830.  
  11831.  to get t 1.566. Between any adjacent two-digit directions, you have 2, 
  11832.  equally-spaced fine control directions. This works with phasors, torpedos and 
  11833.  pods. You can also type:
  11834.  
  11835.       t > 1 5 
  11836.  or
  11837.       t < 1 6
  11838.  
  11839.  i.e. the placement of the '<' or '>' symbol in the direction doesn't matter, 
  11840.  as long as it comes after 't', 'a' or 'p x', and before you type the 
  11841.  second digit. When you type the second digit the weapon fires immediately.
  11842.  
  11843.  Quickly typing the correct direction is important to winning the game. It may 
  11844.  take you a while to get used to it. It's better to use the numbers across the 
  11845.  top of your keyboard, than the numeric keypad on the right. The numbers on 
  11846.  the keypad are not arranged according to the directions, and they may confuse 
  11847.  you. (The intensity of the action in this game makes it necessary to use
  11848.  keyboard input for commands and directions, rather than mouse or arrow-key 
  11849.  input.)
  11850.  
  11851.  The antimatter pod will head out from the Euphoria in the direction you have 
  11852.  chosen. It will pass through any matter in its path. At the precise moment 
  11853.  that you want it to detonate, press Enter. A powerful explosion, equivalent to
  11854.  a 1000-unit phasor blast in all directions, will spread out from the point of 
  11855.  detonation. As with a phasor, the damage inflicted will decline with distance 
  11856.  from the epicenter. All objects in the quadrant, including the Euphoria and 
  11857.  any bases or planets, will be affected. If you leave the quadrant before 
  11858.  pressing Enter, the antimatter pod will not receive your signal.
  11859.  
  11860.  The pod is clearly a double-edged sword in your arsenal. You should try to 
  11861.  detonate it in the middle of a large number of C ships and other enemy ships,
  11862.  as far away as possible from the Euphoria and any planets or bases. It's very 
  11863.  useful for destroying cloaking BASIC ships. When you have a truce with the
  11864.  BASIC ships, it's considered an act of war.
  11865.  
  11866.  The Euphoria initially carries one pod. Each base will provide one additional
  11867.  pod the first time you dock with it. If you fire more than one pod at one
  11868.  time, both will explode simultaneously when you press Enter. After you 
  11869.  detonate a pod, any enemy survivors can probably be polished off with some 
  11870.  weak phasor blasts (unless you leave the quadrant).
  11871.  
  11872.  
  11873.  Canceling a Command
  11874.  -------------------
  11875.  To cancel a command, you can stop, part way through the command, and start
  11876.  typing a new one that begins with a letter, or you can type Backspace or 'c' 
  11877.  to clear the command display.
  11878.  
  11879.  
  11880.  Freezing the Game
  11881.  -----------------
  11882.  To temporarily suspend the game type 'f'. To resume type 'c' or Backspace.
  11883.  Note: This is only allowed to answer a phone call, or go to the bathroom.
  11884.  You can also press Esc to abort the game.
  11885.  
  11886.  
  11887.  Know Your Enemy
  11888.  ---------------
  11889.  C ships (red) come in 3 different sizes. All have torpedos and conventional 
  11890.  phasors. The regular ships have 4000 units of energy and 2 torpedos. A single 
  11891.  torpedo is just enough to destroy them. A 900-unit phasor from not too far 
  11892.  way will also do the trick. The ANSI C ships are somewhat larger, have 8000 
  11893.  units of energy and carry 4 torpedos. C++ has 25000 units of energy and 
  11894.  carries 10 torpedos. C++ is the largest ship in the galaxy, and has a 
  11895.  distinctive magenta color. A couple of phasor blasts from C++ at close range
  11896.  and you are dead. Watch out! C ships will never attack other C ships, and
  11897.  their phasors and torpedos have a safety mechanism that prevents accidental
  11898.  damage to other C ships.
  11899.  
  11900.  BASIC ships are sometimes at TRUCE (bright blue) and will not fire at you 
  11901.  unless you fire first and break the TRUCE. Sometimes they will spontaneously 
  11902.  change to HOSTILE (dark blue and harder to see), and will start firing. They 
  11903.  also have a deadly cloaking device that can make them invisible. (If you
  11904.  watch very carefully you might see a star disappear temporarily when a 
  11905.  cloaking BASIC ship moves in front of it.) When a BASIC ship is attacked, all 
  11906.  other BASIC ships in the quadrant will fire back on the attacker. BASIC ships 
  11907.  have 2 torpedos and conventional phasors. They only have 2000 units of energy. 
  11908.  BASIC ships will never attack other BASIC ships, and their weapons use a 
  11909.  similar safety mechanism as the C ships.
  11910.  
  11911.  The Java ships (green) are very unpredictable and will shoot at anything, 
  11912.  including other Java ships. They can enter a higher dimension that lets them 
  11913.  travel from any other quadrant in the galaxy and arrive at any point in the 
  11914.  current quadrant. Their invisible phasors can travel through anything. They
  11915.  have a red spot that lights up while they are phasoring another ship. They 
  11916.  have 3000 units of energy.
  11917.  
  11918.  Enemy ships always put a fixed percentage of their remaining energy into 
  11919.  each phasor blast. A fresh ANSI C will hit you with twice the impact of a 
  11920.  regular C ship. C++ will hit you with more than 6 times the impact! 
  11921.  Enemy ships gradually weaken as they shoot more and more phasors. 
  11922.  
  11923.  
  11924.  Destroying ships
  11925.  ----------------
  11926.  Any ship, including the Euphoria, is destroyed when its energy reserves reach
  11927.  0. Enemy ships regain their full energy when you leave the quadrant, so be 
  11928.  sure to finish them off while you can. Bases and planets also regain their 
  11929.  defensive energy when you leave.
  11930.  
  11931.  
  11932.  Damage
  11933.  ------
  11934.  5 different subsystems of the Euphoria are subject to damage. The harder you
  11935.  get hit by a phasor, torpedo or pod, the greater the chance of damage. On 
  11936.  your console, you will see an estimate of the time required to repair each 
  11937.  subsystem. The engines will sometimes sustain partial damage and a recommended 
  11938.  maximum warp speed will be posted. You may exceed this speed, but only at 
  11939.  great risk of total engine failure that will take a while to fix.
  11940.  
  11941.  
  11942.  The Assembly Language space shuttle
  11943.  -----------------------------------
  11944.  Your energy is about to expire! Your engines have broken down! Enemy ships
  11945.  at shooting at you! What do you do? Panic? Of course! But then you press 's',
  11946.  to abandon the Euphoria and enter the Assembly Language shuttle. This 
  11947.  small craft carries 5000 units of energy and 1 torpedo deflector. It's your
  11948.  last hope. It can dock at a base or a planet for energy. You will get a 
  11949.  new Euphoria-class ship if you dock with a base. Fortunately, this smaller
  11950.  ship consumes much less energy than the Euphoria while moving through space.
  11951.  
  11952.  
  11953.  Docking
  11954.  -------
  11955.  The Euphoria must periodically dock at an energy source (base or planet)
  11956.  to replenish its supplies. Planets offer energy only. Bases offer energy, 
  11957.  torpedos, pods, deflectors, and quick repairs to any subsystems of the ship
  11958.  that need it. To dock, you must bump the Euphoria into the energy source 
  11959.  while traveling at WARP 1. Moving once at WARP 1 takes about 20 seconds. 
  11960.  Typically you will cruise up to the planet or base at warp 4 or so, bump
  11961.  into it, and then lower your speed to warp 1 and wait for the 
  11962.  "DOCKING COMPLETED" message. The planet or base will remind you to lower your
  11963.  speed to warp 1. During these 20 seconds you must be prepared to defend 
  11964.  yourself and the base or planet from attackers. Bases can fire back at any 
  11965.  ship that fires upon them, but they only have 6000 units of defensive energy,
  11966.  so guard them well. C ships that enter the quadrant will usually attack your 
  11967.  base first, rather than you. Planets have 7000 units of defensive energy to 
  11968.  withstand attacks but cannot fire back. To dock again at the same source you 
  11969.  must first move away from it, and then bump into it again.
  11970.  
  11971.  Bases and planets have finite reserves of energy to give you. After docking
  11972.  a few times at the same energy source, you may notice that it has dried
  11973.  up, and has not given you the full amount of energy that you expected. It is 
  11974.  time to find new sources. A base will always provide repairs and new deflector
  11975.  shields, but it has only one pod and a finite supply of energy and torpedos. 
  11976.  A base might still have some torpedos available, even when it has no energy 
  11977.  to give you.
  11978.  
  11979.  
  11980.  The Galaxy Scan
  11981.  ---------------
  11982.  Command 'g' displays a view of the entire galaxy. You can see the locations
  11983.  of planets, bases and enemy ships for any quadrant that you have visited. The 
  11984.  current quadrant is brighter, and is updated frequently so you can see the
  11985.  location of all objects including the Euphoria. Typing 'g' again will restore 
  11986.  the normal full-screen view of the current quadrant. Sometimes your sensors 
  11987.  will be damaged and you will not be able to view the galaxy scan. It also
  11988.  shows how many enemy ships are remaining, and you can find out if the BASIC 
  11989.  ships are at TRUCE, are HOSTILE, or are CLOAKING (invisible). This scan is 
  11990.  particularly important when your reserves are getting low and you are 
  11991.  searching for an energy source. As you view the scan, the action continues. 
  11992.  Your ship is still moving and you can be struck by enemy fire - watch out! 
  11993.  
  11994.  Note that when you enter a quadrant the number of enemy ships will be as
  11995.  shown on the scan, but the positions of these ships could be very different.
  11996.  Only planets and bases have fixed positions in space. Only the scan for 
  11997.  the current quadrant shows precise enemy locations.
  11998.  
  11999.  If you bump into anything while viewing the galaxy scan, it will be turned
  12000.  off immediately for your safety.
  12001.  
  12002.  The galaxy scan indicates a dried up energy source by showing the planet or 
  12003.  base in white. 
  12004.  
  12005.  When the BASIC ships are cloaking, you will not see any BASIC ships on the
  12006.  scan.
  12007.  
  12008.  
  12009.  Tips
  12010.  ----
  12011.  Winning this game requires your full concentration. You must act quickly and 
  12012.  decisively when there is a threat to your safety. You must keep an eye on your
  12013.  energy reserves, and plan where your next docking will take place. Do not just 
  12014.  fly around aimlessly, picking fights with whoever comes along. You need a plan.
  12015.  
  12016.  Be aware when your deflectors have run out and you become vulnerable to 
  12017.  4000-unit torpedo blasts. 
  12018.  
  12019.  It's a good idea to focus on quadrants that contain energy sources. Clear out 
  12020.  any enemy ships and make it a safe place to dock. 
  12021.  
  12022.  Do not have a showdown with C++ until you are physically and emotionally
  12023.  ready. It takes several torpedo hits or medium-range phasor blasts to kill 
  12024.  him. He will hit you with phasor blasts that are much stronger than you are 
  12025.  used to from other enemy craft. You might consider using a pod - but be sure 
  12026.  to detonate it very close to him.
  12027.  
  12028.  From a tactical point of view you are safer to travel near the edge of 
  12029.  quadrants, since you can quickly escape into the adjacent quadrant when 
  12030.  you are in danger. When entering a new quadrant be prepared to immediately 
  12031.  back out if you don't like what you see. 
  12032.  
  12033.  Travel at WARP 4 most of the time. It's the most energy-efficient way to
  12034.  travel. WARP 5 is faster but burns energy at a very high rate. Note that
  12035.  even at warp 0, you still use a small amount of "life support" energy.
  12036.  
  12037.  Enemy ships can enter your quadrant from the 8 neighboring quadrants. 
  12038.  (Javas can enter from any quadrant). They tend to do so when your energy 
  12039.  is low or you are moving slowly. You should anticipate their sudden arrival, 
  12040.  especially when you are attempting to dock. Be prepared to act quickly, or
  12041.  your energy source may be blown out from under you, just before you dock with
  12042.  it.
  12043.  
  12044.  You will need some practice before you are skilled at typing in commands and
  12045.  aiming your weapons. It might be a good idea to print lw.sum and have it
  12046.  beside you as you learn. 
  12047.  
  12048.  You don't have to wait for a command to finish before typing in your next 
  12049.  command. For instance, after firing a torpedo, you can fire a second, third, 
  12050.  etc. torpedo without waiting for the first to hit or miss.
  12051.   
  12052.  When shooting at an enemy target, it helps to stop at WARP 0 or, if you are 
  12053.  docking, move at WARP 1. You can shoot on the run, but it gets frustrating 
  12054.  when you miss and waste your torpedo, or phasor energy. Enemy ships tend to
  12055.  keep moving in the same direction for a little while, before changing
  12056.  direction. Sometimes it helps to shoot just ahead of where they are moving.
  12057.  If you glance at the screen just before typing the last digit, you can
  12058.  sometimes make a last-second adjustment that will result in a hit.
  12059.  
  12060.  You can fire a trial phasor with 0 units of energy to see what the correct 
  12061.  direction is before you waste energy on a real phasor. 0-unit phasors are 
  12062.  also useful for finding cloaking BASIC ships, If the Euphoria suddenly stops 
  12063.  moving, it's very likely that you have bumped into a cloaking BASIC ship. 
  12064.  Destroy it immediately before it hits you with a huge close-range phasor blast!
  12065.  
  12066.  When docking, be very careful not to hit the planet or base you are docked 
  12067.  with. Use a 0-unit phasor to test. 
  12068.  
  12069.  Do not use 900-unit phasors when something a lot less will finish off your 
  12070.  enemy. Torpedos are useful when the enemy ship is far away. Unfortunately, 
  12071.  torpedos are slower than phasors, and the enemy ship might move away before 
  12072.  the torpedo gets there.
  12073.  
  12074.  Enemy ships will always try to destroy the last ship that fired and struck
  12075.  them, but when you leave the quadrant this information is lost. You can 
  12076.  often set up situations where two enemy ships will get into a battle among 
  12077.  themselves. 
  12078.  
  12079.  It is quite an achievement to win this game at the expert level. 
  12080.  
  12081.  If you think of a way of improving the game, by all means go ahead!
  12082.  
  12083.  
  12084.                  Objects in the Galaxy
  12085.          ---------------------
  12086.  The Good Guys:
  12087.      Euphoria (yellow)
  12088.      Assembly Language Shuttle (yellow)
  12089.      Base     (yellow)
  12090.      Planet   (brown)
  12091.  
  12092.  The Bad Guys:
  12093.      C        (red)
  12094.      ANSI C   (red)
  12095.      C++      (magenta)
  12096.  
  12097.  The Annoying Guys:
  12098.      BASIC    (blue/dark blue/invisible)
  12099.      Java     (green)
  12100.  
  12101.  
  12102.      Good Luck!
  12103.                        
  12104. LW.EX
  12105. 9388
  12106.                ------------------
  12107.                -- Language War --
  12108.                ------------------
  12109. -- Run with:  ex lw
  12110. -- in pure DOS, or a full-screen DOS window. (press Alt+Enter)
  12111.  
  12112. -- See lw.doc for a complete description of how to play.
  12113. -- See lw.sum for a brief summary of the commands that you can print.
  12114.  
  12115. -- This is based on a space war game developed in 1979 for the TRS-80 by 
  12116. -- David A. Craig with assistance from Robert H. Craig. 
  12117.  
  12118. -- Language War uses graphics mode 18 and PC speaker sound effects.
  12119. -- Standard Euphoria routines, such as pixel(), display_image() etc. are used. 
  12120. -- There are no calls to low-level routines such as peek(), poke(), or 
  12121. -- mem_copy(). See the Euphoria Web site for examples of really fast graphics.
  12122.  
  12123. -- Language War is organized as a loose collection of independent "tasks" 
  12124. -- that run in "parallel" with each other. A scheduler decides which task to 
  12125. -- run next. See sched.e for the details. This cooperative, non-preemptive
  12126. -- tasking approach could be applied to other kinds of programs as well.
  12127.  
  12128. -- It seems to run well on any 486 or higher with at least 8Mb RAM. It should 
  12129. -- also run on a 4Mb RAM system with SMARTDRV disabled. It will run correctly 
  12130. -- on a 386, but the performance may be too sluggish for the game to be 
  12131. -- enjoyable.
  12132.  
  12133. global constant QUIET = 0  -- set this to 1 to turn off all sounds
  12134.  
  12135. without type_check -- makes it a bit faster
  12136.  
  12137. type file_number(integer x)
  12138.     return x >= -1
  12139. end type
  12140.  
  12141. file_number sum_no
  12142. object line
  12143.  
  12144. include image.e
  12145. include graphics.e
  12146. include get.e
  12147.  
  12148. include vars.e
  12149.  
  12150. include putsxy.e
  12151.  
  12152. if graphics_mode(18) then
  12153.     puts(1, "you need mode 18\n")
  12154.     abort(0)
  12155. end if
  12156.  
  12157. text_color(7)
  12158.  
  12159. include pictures.e
  12160. include screen.e
  12161.  
  12162. set_bk_color(BLUE)
  12163. bk_color(BLUE)
  12164. set_color(WHITE)
  12165. clear_screen()
  12166.  
  12167. -- display summary file
  12168. sum_no = open("lw.sum", "r")
  12169. if sum_no != -1 then
  12170.     for i = 2 to 26 do
  12171.     line = gets(sum_no)
  12172.     if atom(line) then
  12173.         exit
  12174.     end if
  12175.     line = line[1..length(line)-1]
  12176.     position(i, 1)
  12177.     console_puts(line)
  12178.     end for
  12179.     close(sum_no)
  12180. end if
  12181.  
  12182. set_color(YELLOW)
  12183. position(28, 5)
  12184. console_puts("novice or expert level? (n or e): _ ")
  12185.  
  12186. include sched.e
  12187. include soundeff.e
  12188. include display.e
  12189. include damage.e
  12190. include weapons.e
  12191. include commands.e
  12192. include emove.e
  12193. include enemy.e
  12194.  
  12195. type energy_source(integer x)
  12196.     return x = G_PL or x = G_BS
  12197. end type
  12198.  
  12199. procedure setpb(pb_row row, energy_source stype)
  12200. -- initialize a planet or a base
  12201.  
  12202.     g_index r, c, ri, ci
  12203.     h_coord x, xi
  12204.     v_coord y, yi
  12205.     boolean unique
  12206.     natural e_height, e_width
  12207.     
  12208.     -- choose a quadrant
  12209.     pb[row][P_TYPE] = stype
  12210.     r = rand(G_SIZE)
  12211.     c = rand(G_SIZE)
  12212.     pb[row][P_QR] = r
  12213.     pb[row][P_QC] = c
  12214.     
  12215.     pb[row][P_EN] = (rand(250) + rand(250)) * 70 + 60000
  12216.     galaxy[r][c][stype] += 1
  12217.     e_height = length(EUPHORIA_L)
  12218.     e_width  = length(EUPHORIA_L[1])
  12219.     -- choose a position in the quadrant
  12220.     while TRUE do
  12221.     if stype = G_PL then
  12222.         x = e_width  + rand(HSIZE - length(PLANET[1]) - 2*e_width)
  12223.         y = e_height + rand(VSIZE - length(PLANET)    - 2*e_height)
  12224.     else
  12225.         x = e_width  + rand(HSIZE - length(BASE[1]) - 2*e_width)
  12226.         y = e_height + rand(VSIZE - length(BASE)    - 2*e_height)
  12227.         pb[row][P_POD] = 1
  12228.         pb[row][P_TORP] = rand(14) + 16
  12229.     end if
  12230.     pb[row][P_X] = x
  12231.     pb[row][P_Y] = y
  12232.  
  12233.     -- make sure position doesn't overlap another planet or base
  12234.     unique = TRUE
  12235.     for i = 1 to row - 1 do
  12236.         ri = pb[i][P_QR]
  12237.         ci = pb[i][P_QC]
  12238.         if r = ri and c = ci then
  12239.         -- in the same quadrant
  12240.         xi = pb[i][P_X]
  12241.         -- allow enough room for a planet - bigger than a base
  12242.         if x >= xi - length(PLANET[1]) and
  12243.            x <= xi + length(PLANET[1]) then
  12244.             yi = pb[i][P_Y]
  12245.             if y >= yi-length(PLANET) and y <= yi+length(PLANET) then
  12246.             unique = FALSE
  12247.             exit
  12248.             end if
  12249.         end if
  12250.         end if
  12251.     end for
  12252.     if unique then
  12253.         exit
  12254.     end if
  12255.     end while
  12256. end procedure
  12257.  
  12258. procedure init()
  12259. -- initialize
  12260.     g_index r, c
  12261.     
  12262.     wrap(0)
  12263.     
  12264.     -- objects in the Galaxy (facing left and right):
  12265.     
  12266.     oshape = {{EUPHORIA_L, EUPHORIA_R},  -- Euphoria
  12267.           {KRC_L,       KRC_R},      -- K&R C
  12268.           {ANC_L,       ANC_R},      -- ANSI C
  12269.           {CPP_L,       CPP_R},      -- C++
  12270.           {BASIC_L,     BASIC_R},    -- BASIC
  12271.           {JAVA_L,      JAVA_R},     -- Java
  12272.           {PLANET,      PLANET},     -- Planet
  12273.           {BASE,        BASE}}       -- Base
  12274.     
  12275.     otype = {"EUPHORIA",
  12276.          "C",
  12277.          "ANSI C",
  12278.          "C++",
  12279.          "BASIC",
  12280.          "Java",
  12281.          "PLANET",
  12282.          "BASE"}
  12283.           
  12284.     -- set number of objects in the galaxy
  12285.     nobj = {1,  -- Euphoria (must be 1)
  12286.        40,  -- regular K&R C ships
  12287.         9,  -- ANSI C ships
  12288.         1,  -- C++
  12289.        50,  -- BASIC ships
  12290.        20,  -- Java ships
  12291.        NPLANETS,  -- planets
  12292.        NBASES}    -- bases
  12293.  
  12294.     -- create the standard, initial tasks
  12295.     
  12296.     t_emove = create_task(routine_id("task_emove"))
  12297.     schedule(t_emove, 0, warp_time[1+4], 0.01, {}) -- runs first
  12298.     
  12299.     t_keyb  = create_task(routine_id("task_keyb"))
  12300.     schedule(t_keyb, 0.1, 0.20, 0.15, {})
  12301.     
  12302.     t_life  = create_task(routine_id("task_life"))
  12303.     schedule(t_life, 1.8, 1.8, .10, {})
  12304.     
  12305.     t_bstat = create_task(routine_id("task_bstat"))
  12306.     schedule(t_bstat, rand(300), INACTIVE, .3, {})
  12307.     
  12308.     t_fire  = create_task(routine_id("task_fire"))
  12309.     
  12310.     t_enter = create_task(routine_id("task_enter"))
  12311.     schedule(t_enter, rand(30), INACTIVE, 1, {})
  12312.     
  12313.     -- initially inactive tasks:
  12314.     t_move  = create_task(routine_id("task_move"))
  12315.     t_message = create_task(routine_id("task_message"))
  12316.     t_sound_effect = create_task(routine_id("task_sound_effect"))
  12317.     t_dead  = create_task(routine_id("task_dead"))
  12318.     t_damage_report = create_task(routine_id("task_damage_report"))
  12319.     t_gquad = create_task(routine_id("task_gquad"))
  12320.     scanon = FALSE
  12321.  
  12322.     -- blank lower portion
  12323.     set_bk_color(WHITE)
  12324.     for i = WARP_LINE to WARP_LINE + 2 do
  12325.     position(i, 1)
  12326.     console_puts(BLANK_LINE)
  12327.     end for
  12328.  
  12329.     quadrant[EUPHORIA][Q_TYPE] = G_EU
  12330.     quadrant[EUPHORIA][Q_DEFL] = 3
  12331.     ds = repeat(DEFL_SYM, 3)
  12332.     quadrant[EUPHORIA][Q_TORP] = 10
  12333.     ts = repeat(TORP_SYM, 10)
  12334.     ps = repeat(POD_SYM, 1)
  12335.     quadrant[EUPHORIA][Q_EN] = 50000
  12336.     wlimit = 5
  12337.     curwarp = 4
  12338.     curdir = 1
  12339.     exi = 1
  12340.     eyi = 0
  12341.     truce_broken = FALSE
  12342.     qrow = 1
  12343.     qcol = 1
  12344.     stext()
  12345.  
  12346.     -- initialize galaxy sequence
  12347.     galaxy = repeat(repeat(repeat(0, NTYPES), G_SIZE), G_SIZE)
  12348.     for i = G_KRC to G_JAV do
  12349.     for j = 1 to nobj[i] do
  12350.         r = rand(G_SIZE)
  12351.         c = rand(G_SIZE)
  12352.         galaxy[r][c][i] += 1
  12353.     end for
  12354.     end for
  12355.  
  12356.     -- initialize planet/base sequence
  12357.     for i = 1 to nobj[G_BS] do
  12358.     setpb(i, G_BS)
  12359.     end for
  12360.     for i = nobj[G_BS]+1 to PROWS do
  12361.     setpb(i, G_PL)
  12362.     end for
  12363.     esymr = EUPHORIA_R
  12364.     esyml = EUPHORIA_L
  12365.     esym = EUPHORIA_R
  12366.     quadrant[EUPHORIA][Q_X] = HSIZE - length(esym[1]) + 1
  12367.     quadrant[EUPHORIA][Q_Y] = floor(VSIZE/2) - length(esym) + 1
  12368.     quadrant[EUPHORIA][Q_UNDER] = 0 * esym
  12369.     qrow = pb[1][P_QR]
  12370.     qcol = gmod(pb[1][P_QC] - 1)
  12371.     bstat = TRUCE
  12372.     reptime[1..NSYS] = 0
  12373.     ndmg = 0
  12374.     shuttle = FALSE
  12375.     set_bk_color(BLACK)
  12376.     bk_color(BLACK)
  12377.     set_color(WHITE)
  12378.     BlackScreen()  -- blank upper portion
  12379. end procedure
  12380.  
  12381. function task_end_game()
  12382. -- end the game
  12383.     gameover = TRUE
  12384.     return {}
  12385. end function
  12386.  
  12387. procedure trek()
  12388. -- Language War Main Routine
  12389.  
  12390.     natural nk
  12391.     
  12392.     init()
  12393.     
  12394.     current_task = t_keyb
  12395.     gameover = FALSE
  12396.  
  12397.     -- MAIN SCHEDULING LOOP FOR WHOLE GAME:
  12398.     while not gameover do
  12399.     next_task()
  12400.     end while
  12401.     
  12402.     -- shut down most tasks
  12403.     stop_weapons()
  12404.     delete_task(t_emove)
  12405.     delete_task(t_keyb)
  12406.     delete_task(t_life)
  12407.     delete_task(t_bstat)
  12408.     delete_task(t_fire)
  12409.     delete_task(t_move)
  12410.     delete_task(t_damage_report)
  12411.     delete_task(t_enter)
  12412.     delete_task(t_gquad)
  12413.     
  12414.     -- post game: allow 18 seconds max for explosions, pod explosion, 
  12415.     -- messages, sounds to finish
  12416.     current_task = create_task(routine_id("task_end_game"))
  12417.     schedule(current_task, 0, 18, 15, {}) 
  12418.     gameover = FALSE
  12419.     while not gameover do
  12420.     next_task()
  12421.     end while
  12422.     
  12423.     nk = c_remaining()
  12424.     if nk = 0 then
  12425.     set_color(RED)
  12426.     display_msg("PROGRAMMERS THROUGHOUT THE GALAXY ARE EUPHORIC!!!!!")
  12427.     victory_sound()
  12428.     else
  12429.     display_msg(sprintf(
  12430.         "%d C SHIPS REMAIN. YOU ARE DEAD. C RULES THE GALAXY!", nk))
  12431.     end if
  12432.     
  12433.     position(WARP_LINE+1, ENERGY_POS)
  12434.     set_color(BLUE)
  12435.     set_bk_color(WHITE)
  12436.     if level = 'e' then
  12437.     console_puts("expert")
  12438.     else
  12439.     console_puts("novice")
  12440.     end if
  12441.     console_puts(" level")
  12442.     
  12443.     while get_key() != -1 do
  12444.     -- clear any extra keystrokes
  12445.     end while
  12446.     delay(1.5) -- make sure he sees his failure (or victory)
  12447.     if wait_key() then
  12448.     end if
  12449.     quit()
  12450. end procedure
  12451.  
  12452. tick_rate(TICK_RATE) -- do it before init_delay() - it speeds up time() call
  12453. init_delay()         -- uses up some time - do it here while user is thinking
  12454.  
  12455. integer in 
  12456. while TRUE do
  12457.     in = get_key()
  12458.     if in != -1 then
  12459.     exit
  12460.     end if
  12461. end while
  12462.  
  12463. if in = 'n' or in = 'N' then
  12464.     level = 'n'
  12465. else
  12466.     level = 'e'    
  12467. end if
  12468.  
  12469. trek()
  12470.  
  12471. LW.SUM
  12472. 879
  12473.                 Language War Command Summary
  12474.                 ============================
  12475.  Examples
  12476.  --------
  12477.  3              move ship in direction 3 (up the screen) 
  12478.  w 4            set warp speed to 4   
  12479.  p 9 1 5        shoot 900-unit phasor in direction 1.5  
  12480.  t 3 2          shoot torpedo in direction 3.2
  12481.  a 5 0          shoot antimatter pod in direction 5.0 - Press Enter to detonate
  12482.  g              display or cancel galaxy scan
  12483.  s              abandon Euphoria for shuttlecraft
  12484.  f              freeze the game - hit 'c' to resume
  12485.  c              cancel a partially entered command
  12486.  Esc            abort the game
  12487.  
  12488.                     directions
  12489.                         3
  12490.                    4    |    2
  12491.                         |   
  12492.                  5------+------1
  12493.                         |
  12494.                    6    |    8
  12495.                         7 
  12496. PICTURES.E
  12497. 11357
  12498.     -----------------------------------------
  12499.     -- Bitmap images for various objects --
  12500.     -----------------------------------------
  12501.  
  12502. --   16 color graphics modes:
  12503.  
  12504. --   BLACK   = 0         GRAY           = 8
  12505. --   BLUE    = 1         BRIGHT_BLUE    = 9
  12506. --   GREEN   = 2         BRIGHT_GREEN   = A
  12507. --   CYAN    = 3         BRIGHT_CYAN    = B
  12508. --   RED     = 4         BRIGHT_RED     = C
  12509. --   MAGENTA = 5         BRIGHT_MAGENTA = D
  12510. --   BROWN   = 6         YELLOW         = E
  12511. --   WHITE   = 7         BRIGHT_WHITE   = F
  12512.  
  12513. -- low order 4 bits determine the color seen by the user
  12514. -- 0: black part of outer space
  12515. -- 1..15: colored part of a solid object
  12516. -- 16..31: POD - solid, but phasors/torps can pass through it
  12517. -- 32: black part of a solid object
  12518. -- 33..64: torpedos/phasors/explosion bits 
  12519. --         - ignorable fluff with no effect on the game
  12520. -- 65...: stars - no effect on game, but they shouldn't be destroyed
  12521.  
  12522. function make_image(sequence digits)
  12523. -- convert a 2-d sequence of hex digits into a 2-d image
  12524.     integer c
  12525.     
  12526.     for i = 1 to length(digits) do
  12527.     for j = 1 to length(digits[i]) do
  12528.         c = digits[i][j] 
  12529.         if c = ' ' then
  12530.         c = 32 -- BLACK (transparent) part of an object
  12531.         elsif c >= 'A' then
  12532.         c -= 'A' - 10
  12533.         else
  12534.         c -= '0'
  12535.         end if
  12536.         digits[i][j] = c
  12537.     end for
  12538.     end for
  12539.     return digits
  12540. end function
  12541.  
  12542. function flip_image(sequence digits)
  12543. -- make left-right mirror image
  12544.     integer temp
  12545.     
  12546.     for i = 1 to length(digits) do
  12547.     for j = 1 to floor(length(digits[i])/2) do
  12548.         temp = digits[i][j]
  12549.         digits[i][j] = digits[i][length(digits[i])-j+1]
  12550.         digits[i][length(digits[i])-j+1] = temp
  12551.     end for
  12552.     end for
  12553.     return digits
  12554. end function
  12555.  
  12556. global constant
  12557.     STAR1 = 64 + BRIGHT_WHITE,  -- bright star, greater than 64
  12558.  
  12559.     STAR2 = 64 + WHITE,   -- duller star, greater than 64
  12560.                
  12561.     TORPEDO = make_image({"FF",  -- the dot used for torpedos and phasors
  12562.               "FF"
  12563.              })+32,
  12564.     TORPEDO_WIDTH = length(TORPEDO[1]),
  12565.     TORPEDO_HEIGHT = length(TORPEDO),
  12566.     
  12567.     POD = make_image({"F0000F",
  12568.               "0FFFF0",
  12569.               "FF00FF",
  12570.               "0FFFF0",
  12571.               "F0000F"
  12572.              })+16,
  12573.     
  12574.     BASE = make_image({"          EEEEEEEE          ",
  12575.                "          EEEEEEEE          ",
  12576.                "             EE             ",
  12577.                "             EE             ",
  12578.                "             EE             ",
  12579.                "             EE             ",
  12580.                "        EEEEEEEEEEEE        ",
  12581.                "       EEEEEEEEEEEEEE       ",
  12582.                "      EEE    EE    EEE      ",
  12583.                "EE    EEE    EE    EEE    EE",
  12584.                "EE    EEE    EE    EEE    EE",
  12585.                "EEEEEEEEEEEEEEEEEEEEEEEEEEEE",
  12586.                "EEEEEEEEEEEEEEEEEEEEEEEEEEEE",
  12587.                "EE    EEE    EE    EEE    EE",
  12588.                "EE    EEE    EE    EEE    EE",
  12589.                "      EEE    EE    EEE      ",
  12590.                "       EEEEEEEEEEEEEE       ",
  12591.                "        EEEEEEEEEEEE        ",
  12592.                "             EE             ",
  12593.                "             EE             ",
  12594.                "             EE             ",
  12595.                "             EE             ",
  12596.                "          EEEEEEEE          ",
  12597.                "          EEEEEEEE          "
  12598.               }),
  12599.     
  12600.     PLANET  = make_image({
  12601.              "                   6666666666                   ",
  12602.              "                6666666666666666                ",
  12603.              "              66666666666666666666              ",
  12604.              "            666666666666666666666666            ",
  12605.              "          6666666666666666666666666666          ",
  12606.              "        66666666666666666666666666666666        ",
  12607.              "       6666666666666666666666666666666666       ",
  12608.              "      666666666666666666666666666666666666      ",
  12609.              "     66666666666666666666666666666666666666     ",
  12610.              "    6666666666666666666666666666666666666666    ",
  12611.              "    6666666666666666666666666666666666666666    ",
  12612.              "   666666666666666666666666666666666666666666   ",
  12613.              "   666666666666666666666666666666666666666666   ",
  12614.              "  66666666666666666666666666666666666666666666  ",
  12615.              "  66666666666666666666666666666666666666666666  ",
  12616.              "  66666666666666666666666666666666666666666666  ",
  12617.              " 6666666666666666666666666666666666666666666666 ",
  12618.              " 6666666666666666666666666666666666666666666666 ",
  12619.              " 6666666666666666666666666666666666666666666666 ",
  12620.              "666666666666666666666666666666666666666666666666",
  12621.              "666666666666666666666666666666666666666666666666",
  12622.              "666666666666666666666666666666666666666666666666",
  12623.              "666666666666666666666666666666666666666666666666",
  12624.              "666666666666666666666666666666666666666666666666",
  12625.              "666666666666666666666666666666666666666666666666",
  12626.              "666666666666666666666666666666666666666666666666",
  12627.              "666666666666666666666666666666666666666666666666",
  12628.              "666666666666666666666666666666666666666666666666",
  12629.              " 6666666666666666666666666666666666666666666666 ",
  12630.              " 6666666666666666666666666666666666666666666666 ",
  12631.              " 6666666666666666666666666666666666666666666666 ",
  12632.              "  66666666666666666666666666666666666666666666  ",
  12633.              "  66666666666666666666666666666666666666666666  ",
  12634.              "  66666666666666666666666666666666666666666666  ",
  12635.              "   666666666666666666666666666666666666666666   ",
  12636.              "   666666666666666666666666666666666666666666   ",
  12637.              "    6666666666666666666666666666666666666666    ",
  12638.              "    6666666666666666666666666666666666666666    ",
  12639.              "     66666666666666666666666666666666666666     ",
  12640.              "      666666666666666666666666666666666666      ",
  12641.              "       6666666666666666666666666666666666       ",
  12642.              "        66666666666666666666666666666666        ",
  12643.              "          6666666666666666666666666666          ",
  12644.              "            666666666666666666666666            ",
  12645.              "              66666666666666666666              ",
  12646.              "                6666666666666666                ",
  12647.              "                   6666666666                   "
  12648.              }),
  12649.     
  12650.     BASIC_L = make_image({"            9 9  9 9   ",
  12651.               "            9 9  9 9   ",
  12652.               "           99999 9999  ",
  12653.               "99999999999     9      ",
  12654.               "           99999 9999  ",
  12655.               "            9 9  9 9   ",
  12656.               "            9 9  9 9   "
  12657.                }),
  12658.     BASIC_R = flip_image(BASIC_L),
  12659.     
  12660.     SHUTTLE_L = make_image({"            EE",
  12661.                 "      EEEEEEE ",
  12662.                 "EEEEEEE     E ",
  12663.                 "      EEEEEEE ",
  12664.                 "            EE"
  12665.                }),
  12666.     SHUTTLE_R = flip_image(SHUTTLE_L),
  12667.     
  12668.     EUPHORIA_L = make_image({
  12669.                 "       EEEEEEEEEE",
  12670.                 " EEEE    EE      ",
  12671.                 "EE  EE   E       ",
  12672.                 "E    EEEEEEE     ",
  12673.                 "EE  EE   E       ",
  12674.                 " EEEE    EE      ",
  12675.                 "       EEEEEEEEEE"
  12676.               }),
  12677.     EUPHORIA_R = flip_image(EUPHORIA_L),
  12678.  
  12679.     -- Java when shooting
  12680.     JAVA_LS = make_image({
  12681.              "                  AAA", 
  12682.              "      AAAA       AA  ",
  12683.              "    AACCCCAA    AAA  ",
  12684.              "  AAACCCCCCAAAAAAAA  ",
  12685.              "AAAAACCCCCCAAAAAAAAAA",
  12686.              "  AAACCCCCCAAAAAAAA  ",
  12687.              "    AACCCCAA    AAA  ",
  12688.              "      AAAA       AA  ",
  12689.              "                  AAA"
  12690.             }),   
  12691.     JAVA_RS = flip_image(JAVA_LS),   
  12692.  
  12693.     -- normal Java
  12694.     JAVA_L = make_image({
  12695.              "                  AAA", 
  12696.              "      AAAA       AA  ",
  12697.              "    AA    AA    AAA  ",
  12698.              "  AAA      AAAAAAAA  ",
  12699.              "AAAAA      AAAAAAAAAA",
  12700.              "  AAA      AAAAAAAA  ",
  12701.              "    AA    AA    AAA  ",
  12702.              "      AAAA       AA  ",
  12703.              "                  AAA"
  12704.             }),   
  12705.     JAVA_R = flip_image(JAVA_L),   
  12706.  
  12707.     KRC_L = make_image({
  12708.             "              CC       ",
  12709.             "             CC        ",
  12710.             "            CC         ",
  12711.             "    CC     CC        CC",
  12712.             "   C  C    CC      CC  ",
  12713.             "   C  CCCCCCCCCCCCC    ",
  12714.             "CCCC  CCCCCCCCCCCCC    ",
  12715.             "   C  CCCCCCCCCCCCC    ",
  12716.             "   C  C    CC      CC  ",
  12717.             "    CC     CC        CC",
  12718.             "            CC         ",
  12719.             "             CC        ",
  12720.             "              CC       "
  12721.             }),   
  12722.     KRC_R = flip_image(KRC_L),   
  12723.     
  12724.     ANC_L = make_image({
  12725.             "                    CC        ",
  12726.             "                   CC         ",
  12727.             "                  CC          ",
  12728.             "       CCC       CCC       CCC",
  12729.             "     CC   CC    CCCC     CCC  ",
  12730.             "   CCC     CCCCCCCCCCCCCCCC   ",
  12731.             "CCCCC      CCCCCCCCCCCCCCCCCCC",
  12732.             "   CCC     CCCCCCCCCCCCCCCC   ",
  12733.             "     CC   CC    CCCC     CCC  ",
  12734.             "       CCC       CCC       CCC",
  12735.             "                  CC          ",
  12736.             "                   CC         ",
  12737.             "                    CC        "
  12738.             }),   
  12739.     ANC_R = flip_image(ANC_L),   
  12740.     
  12741.     -- =8**<",
  12742.     CPP_L = make_image({
  12743.             "                    DDDDDD    ",
  12744.             "                   DDDDD      ",
  12745.             "                  DDDDD       ",
  12746.             "                 DDDDD        ",
  12747.             "       DD       DDDD       DDD",
  12748.             "DDDDDDD  DD    DDDD       DD  ",
  12749.             "DDDDDD    DDDDDDDDDDDDDDDDD   ",
  12750.             "     D    DDDDDDDDDDDDDDDD    ",
  12751.             "     D    DDDDDDDDDDDDDDDDDDDD",
  12752.             "     D    DDDDDDDDDDDDDDDD    ",
  12753.             "DDDDDD    DDDDDDDDDDDDDDDDD   ",
  12754.             "DDDDDDD  DD    DDDD       DD  ",
  12755.             "       DD       DDDD       DDD",
  12756.             "                 DDDDD        ",
  12757.             "                  DDDDD       ",
  12758.             "                   DDDDD      ",
  12759.             "                    DDDDDD    "
  12760.             }),   
  12761.     CPP_R = flip_image(CPP_L)
  12762.  
  12763. font_index[1+'@'] = {  -- cross shape in direction box
  12764.         {0,0,0,0,0,0,0,0},
  12765.         {0,0,0,0,0,0,0,0},
  12766.         {0,0,0,0,0,0,0,0},
  12767.         {0,0,0,1,1,0,0,0},
  12768.         {0,0,0,1,1,0,0,0},
  12769.         {0,0,0,1,1,0,0,0},
  12770.         {0,0,0,1,1,0,0,0},
  12771.         {1,1,1,1,1,1,1,1},
  12772.         {1,1,1,1,1,1,1,1},
  12773.         {0,0,0,1,1,0,0,0},
  12774.         {0,0,0,1,1,0,0,0},
  12775.         {0,0,0,1,1,0,0,0},
  12776.         {0,0,0,1,1,0,0,0},
  12777.         {0,0,0,0,0,0,0,0},
  12778.         {0,0,0,0,0,0,0,0},
  12779.         {0,0,0,0,0,0,0,0}}
  12780.  
  12781. global constant TORP_SYM = 250,
  12782.         DEFL_SYM = 251,
  12783.          POD_SYM = 252
  12784.  
  12785. font_index[1+TORP_SYM] = {  -- torpedo symbol on console
  12786.         {0,0,0,0,0,0,0,0},
  12787.         {0,0,0,0,0,0,0,0},
  12788.         {0,0,0,1,1,0,0,0},
  12789.         {0,0,1,1,1,1,0,0},
  12790.         {0,1,1,1,1,1,1,0},
  12791.         {0,0,0,1,1,0,0,0},
  12792.         {0,0,0,1,1,0,0,0},
  12793.         {0,0,0,1,1,0,0,0},
  12794.         {0,0,0,1,1,0,0,0},
  12795.         {0,0,0,1,1,0,0,0},
  12796.         {0,0,0,1,1,0,0,0},
  12797.         {0,0,0,1,1,0,0,0},
  12798.         {0,0,0,0,0,0,0,0},
  12799.         {0,0,0,0,0,0,0,0},
  12800.         {0,0,0,0,0,0,0,0},
  12801.         {0,0,0,0,0,0,0,0}}
  12802.  
  12803. font_index[1+DEFL_SYM] = {  -- deflector symbol on console
  12804.         {0,0,0,0,0,0,0,0},
  12805.         {0,0,0,0,0,0,0,0},
  12806.         {0,0,0,0,0,0,0,0},
  12807.         {0,1,1,1,1,1,0,0},
  12808.         {1,1,1,1,1,1,1,0},
  12809.         {1,1,0,0,0,1,1,0},
  12810.         {1,0,0,0,0,0,1,0},
  12811.         {1,0,0,0,0,0,1,0},
  12812.         {1,0,0,0,0,0,1,0},
  12813.         {0,0,0,0,0,0,0,0},
  12814.         {0,0,0,0,0,0,0,0},
  12815.         {0,0,0,0,0,0,0,0},
  12816.         {0,0,0,0,0,0,0,0},
  12817.         {0,0,0,0,0,0,0,0},
  12818.         {0,0,0,0,0,0,0,0},
  12819.         {0,0,0,0,0,0,0,0}}
  12820.  
  12821. font_index[1+POD_SYM] = {  -- POD symbol on console
  12822.         {0,0,0,0,0,0,0,0},
  12823.         {0,0,0,0,0,0,0,0},
  12824.         {0,0,0,0,0,0,0,0},
  12825.         {1,1,0,0,0,0,1,1},
  12826.         {0,0,1,1,1,1,0,0},
  12827.         {0,0,1,1,1,1,0,0},
  12828.         {0,1,1,0,0,1,1,0},
  12829.         {0,1,1,0,0,1,1,0},
  12830.         {0,0,1,1,1,1,0,0},
  12831.         {0,0,1,1,1,1,0,0},
  12832.         {1,1,0,0,0,0,1,1},
  12833.         {0,0,0,0,0,0,0,0},
  12834.         {0,0,0,0,0,0,0,0},
  12835.         {0,0,0,0,0,0,0,0},
  12836.         {0,0,0,0,0,0,0,0},
  12837.         {0,0,0,0,0,0,0,0}}
  12838.         
  12839. PUTSXY.E
  12840. 3315
  12841. --  file    : putsxy.e
  12842. --  author  : jiri babor
  12843. --  project : variation on David Alan Gay's putsxy include
  12844. --  tool    : euphoria 2.2
  12845. --  email   : jbabor@paradise.net.nz
  12846. --  http    : homepages.paradise.net.nz/~jbabor/euphoria.html
  12847. --  date    : 00-01-12
  12848.  
  12849. ----------------------------------------------------------------------
  12850. --  The previous version of putsxy with Rob's enhancements did not  --
  12851. --  work in mode 19, could be initialized only while in graphics    --
  12852. --  mode and on my NT machine it took forever to load the images... --
  12853. ----------------------------------------------------------------------
  12854.  
  12855. without type_check
  12856. without warning
  12857.  
  12858. include image.e
  12859.  
  12860. global constant CLEAR = -1  -- transparent background 'color'
  12861. global sequence font_index  -- for compatibility with original putsxy.e (Rob)
  12862.  
  12863. function rtrim(sequence s)
  12864.     -- trim (discard) trailing zeros of sequence s
  12865.     integer i
  12866.     i=length(s)
  12867.     while i do
  12868.     if s[i] then exit end if
  12869.     i=i-1
  12870.     end while
  12871.     return s[1..i]
  12872. end function -- rtrim
  12873.  
  12874. procedure load_font()   -- load 8x16 font
  12875.     sequence cb,regs
  12876.     integer a
  12877.  
  12878.     regs = repeat(0,10)
  12879.     regs[REG_AX]=#1130
  12880.     regs[REG_BX]=#600
  12881.     regs=dos_interrupt(#10,regs)
  12882.     a=#10*regs[REG_ES]+regs[REG_BP]
  12883.     font_index={}
  12884.     for i=1 to 256 do
  12885.     cb=rtrim(peek({a,16}))              -- char bytes, right trimmed
  12886.     for j=1 to length(cb) do
  12887.         cb[j]=rtrim(and_bits(cb[j],{128,64,32,16,8,4,2,1}) and 1)
  12888.     end for
  12889.     a += 16
  12890.     font_index = append(font_index,cb)
  12891.     end for
  12892. end procedure -- load_font
  12893.  
  12894. global procedure putsxy(
  12895.     sequence loc,   -- {x,y} text pointer, top left pixel
  12896.     sequence text,  -- text to be displayed
  12897.     atom fc,        -- foreground color
  12898.     atom bc,        -- background color
  12899.     atom dir        -- print direction
  12900.     )
  12901.     -- Display text at an {x,y} pixel location, using the specified
  12902.     -- foreground and background colors. If direction is 'd' then text is
  12903.     -- printed down the screen, otherwise it is printed across the screen.
  12904.  
  12905.     sequence c,cj,s
  12906.     integer col,len,row,u,x,y
  12907.  
  12908.     len = length(text)
  12909.     x = loc[1]
  12910.     y = loc[2]
  12911.     if dir = 'd' or dir = 'D' then      -- down, vertical print
  12912.     if bc = CLEAR then
  12913.         s = save_image({x,y},{x+7,y+16*len-1})
  12914.     else
  12915.         s = repeat(repeat(bc, 8), 16*len)
  12916.     end if
  12917.     row = 1
  12918.     for i=1 to len do
  12919.         c = font_index[1+text[i]]   -- trimmed char image
  12920.         u = row
  12921.         for j=1 to length(c) do
  12922.         cj = c[j]
  12923.         for k=1 to length(cj) do
  12924.             if cj[k] then
  12925.             s[u][k] = fc
  12926.             end if
  12927.         end for
  12928.         u += 1
  12929.         end for
  12930.         row += 16
  12931.     end for
  12932.     else                                -- across, left-to-right
  12933.     if bc = CLEAR then
  12934.         s = save_image({x,y},{x+8*len-1,y+15})
  12935.     else
  12936.         s = repeat(repeat(bc, 8*len), 16)
  12937.     end if
  12938.     col = 1
  12939.     for i=1 to len do
  12940.         c = font_index[1+text[i]]   -- trimmed char image
  12941.         for j=1 to length(c) do
  12942.         cj = c[j]
  12943.         u = col
  12944.         for k=1 to length(cj) do
  12945.             if cj[k] then
  12946.             s[j][u] = fc
  12947.             end if
  12948.             u += 1
  12949.         end for
  12950.         end for
  12951.         col += 8
  12952.     end for
  12953.     end if
  12954.     display_image({x,y},s)
  12955. end procedure -- putsxy
  12956.  
  12957. load_font()
  12958.  
  12959.  
  12960. -- This file (unless modified) is FREE - 0 statements.
  12961. with 33046225 -- delete this statement if it causes an error
  12962.  
  12963. SCHED.E
  12964. 7231
  12965. -- sched.e
  12966. -- Task Scheduler
  12967.  
  12968. -- This is perhaps the most interesting source file since it shows a
  12969. -- simple technique of task scheduling that could be used in any action 
  12970. -- game or simulation program. 
  12971.  
  12972. -- We have implemented a form of cooperative multitasking to manage over 10 
  12973. -- independent tasks. There is a task that moves the Euphoria, another task 
  12974. -- that checks the keyboard for input, a task that makes enemy ships fire, 
  12975. -- another that counts down the damage report, etc. The sequence "tcb" records
  12976. -- the time at which each task wants to be activated next. When the time comes 
  12977. -- to run a given task, next_task() will run it. 
  12978.  
  12979. -- For example, the task that moves the Euphoria will ask to be activated 
  12980. -- again in 20 seconds if the Euphoria is moving at warp 1, or much less at 
  12981. -- higher warps. The keyboard checking task is activated very frequently, but 
  12982. -- usually returns quickly (no key pressed). 
  12983.  
  12984. -- Some tasks require very precise activation times to make things look 
  12985. -- realistic, e.g. Euphoria moving at warp 5. Others do not, for example the 
  12986. -- BASIC TRUCE/HOSTILE/CLOAKING task which is activated after a lengthy and 
  12987. -- random amount of time. In recognition of this we have the "eat" (early 
  12988. -- activation tolerance) variable. After choosing the next task to run, and 
  12989. -- before entering into a delay loop to wait for the activation time to come,
  12990. -- next_task() will check T_EARLY to see if it can activate the task a bit
  12991. -- sooner. This will get this task out of the way and reduce the chance of a 
  12992. -- timing conflict with the next task.
  12993.  
  12994. -- It's possible to have multiple logical tasks all running the same routine, 
  12995. -- but with different private data (parameters and private variables). For 
  12996. -- instance, there could be several torpedo tasks active at the same time. 
  12997. -- Each torpedo task has it's own set of private variables. It returns a 
  12998. -- sequence to next_task() containing the arguments that it wants to be 
  12999. -- called with the next time it is activated. This sequence is saved in the 
  13000. -- tcb for that task and allows it to preserve its own state variables 
  13001. -- between activations.
  13002.  
  13003. sequence tcb -- task control block
  13004. tcb = {}
  13005.  
  13006. global integer t_keyb,    -- keyboard input
  13007.            t_emove,   -- Euphoria move
  13008.            t_life,    -- life support energy consumption
  13009.            t_dead,    -- dead body cleanup
  13010.            t_bstat,   -- BASIC status change
  13011.            t_fire,    -- enemy firing
  13012.            t_move,    -- enemy moving 
  13013.            t_message, -- display messages
  13014.            t_damage_report,  -- damage count-down
  13015.            t_enter,   -- enemy ships enter quadrant
  13016.            t_sound_effect,   -- sound effects
  13017.            t_gquad    -- refresh current quadrant on scan
  13018.            
  13019. global constant INACTIVE = -1 
  13020. constant HUGE_TIME = 1e30
  13021.  
  13022. constant T_ROUTINE     = 1,  -- routine id
  13023.      T_ACTIVATE    = 2,  -- next activation time
  13024.      T_NORMAL_WAIT = 3,  -- normal time between activations
  13025.      T_EARLY       = 4,  -- early activation tolerance
  13026.      T_ARGS        = 5   -- private data passed as arguments to this task
  13027.  
  13028. global type task(integer x)
  13029. -- is x a valid task number?
  13030.     return x >= 1 and x <= length(tcb)
  13031. end type
  13032.  
  13033. global task current_task -- current task executing
  13034.  
  13035. type valid_routine_id(integer id)
  13036.     return id >= 0 and id <= 1000
  13037. end type
  13038.  
  13039. global function create_task(valid_routine_id proc_id)
  13040. -- create a new independent task
  13041.     sequence entry
  13042.     
  13043.     entry = {proc_id, HUGE_TIME, HUGE_TIME, 0, {}}
  13044.     for i = 1 to length(tcb) do
  13045.     if tcb[i][T_ROUTINE] = -1 then
  13046.         -- found an empty spot, insert it here
  13047.         tcb[i] = entry
  13048.         return i
  13049.     end if
  13050.     end for
  13051.     -- grow the tcb
  13052.     tcb = append(tcb, entry)
  13053.     return length(tcb)
  13054. end function
  13055.  
  13056. global procedure delete_task(task t)
  13057. -- delete task t
  13058.     tcb[t][T_ROUTINE] = -1
  13059.     tcb[t][T_ACTIVATE] = HUGE_TIME
  13060.     tcb[t][T_NORMAL_WAIT] = HUGE_TIME
  13061. end procedure
  13062.  
  13063. global procedure purge_tasks(valid_routine_id r)
  13064.     for i = 1 to length(tcb) do
  13065.     if tcb[i][T_ROUTINE] = r then
  13066.         delete_task(i)
  13067.     end if
  13068.     end for
  13069. end procedure
  13070.  
  13071. global procedure schedule(task t, atom next, 
  13072.                   atom again, 
  13073.                   atom early,
  13074.                   object args)
  13075. -- schedule a task to start in <next> seconds from now, 
  13076. -- repeat every <again> seconds, 
  13077. -- with early activation tolerance of <early>
  13078. -- and private state information contained in <args>
  13079.  
  13080.     -- activate the task in wait seconds *from now*
  13081.     if next = INACTIVE then
  13082.     -- deactivate the task
  13083.     tcb[t][T_ACTIVATE] = HUGE_TIME
  13084.     else
  13085.     tcb[t][T_ACTIVATE] = time() + next
  13086.     end if
  13087.     
  13088.     if again = INACTIVE then
  13089.     -- no more after next activation
  13090.     tcb[t][T_NORMAL_WAIT] = HUGE_TIME
  13091.     else
  13092.     tcb[t][T_NORMAL_WAIT] = again
  13093.     end if
  13094.     
  13095.     tcb[t][T_EARLY] = early
  13096.     tcb[t][T_ARGS] = args
  13097. end procedure
  13098.  
  13099. integer late, not_late
  13100. not_late = 0
  13101. late = 0
  13102.  
  13103. global procedure next_task()
  13104. -- choose the next task and execute it
  13105.  
  13106.     positive_atom min_time, base_time, start_time
  13107.     task min_task
  13108.     
  13109.     -- reschedule the current task
  13110.     base_time = time()
  13111.     if base_time < tcb[current_task][T_ACTIVATE] then
  13112.     base_time = tcb[current_task][T_ACTIVATE]
  13113.     end if
  13114.     tcb[current_task][T_ACTIVATE] = base_time + tcb[current_task][T_NORMAL_WAIT]
  13115.     
  13116.     -- find the task with minimum activation time
  13117.     min_task = 1
  13118.     min_time = tcb[1][T_ACTIVATE]
  13119.     for i = 2 to length(tcb) do
  13120.     if tcb[i][T_ACTIVATE] < min_time then
  13121.         min_task = i
  13122.         min_time = tcb[i][T_ACTIVATE]
  13123.     end if
  13124.     end for
  13125.  
  13126.     -- subtract it's early-activation tolerance
  13127.     start_time = tcb[min_task][T_ACTIVATE] - tcb[min_task][T_EARLY]
  13128.  
  13129.     -- wait until it is time to activate it
  13130.     while time() < start_time do
  13131.     end while
  13132.  
  13133.     current_task = min_task
  13134.     tcb[current_task][T_ARGS] = call_func(tcb[current_task][T_ROUTINE], 
  13135.                       tcb[current_task][T_ARGS])
  13136. end procedure
  13137.  
  13138. global procedure shift_task_times(atom amount)
  13139. -- adjust all task times (when user delays the game)
  13140.     for i = 1 to length(tcb) do
  13141.     tcb[i][T_ACTIVATE] += amount
  13142.     end for
  13143. end procedure
  13144.  
  13145.  
  13146. -- below we have some code that lets us perform short accurate time delays
  13147. -- with better resolution than the usual 18.2 ticks per second under MS-DOS
  13148. constant sample_interval = 1.0
  13149. atom sample_count
  13150.  
  13151. type reasonable_delay(atom x)
  13152.     return x >= 0 and x < 30
  13153. end type
  13154.  
  13155. global procedure init_delay()
  13156. -- since time() does not have fine enough
  13157. -- resolution for small delays, we see how many for-loop iterations
  13158. -- we can complete over a small sample period
  13159.  
  13160.     atom t
  13161.  
  13162.     t = time() + sample_interval
  13163.     for i = 1 to 999999999 do
  13164.     if time() < t then
  13165.     else
  13166.         sample_count = i
  13167.         exit
  13168.     end if
  13169.     end for
  13170. end procedure
  13171.  
  13172. global procedure delay(reasonable_delay t)
  13173. -- delay for t seconds
  13174.     atom stop
  13175.     if t > sample_interval then
  13176.     -- time() should be precise enough
  13177.     stop = time() + t
  13178.     while time() < stop do
  13179.     end while
  13180.     else
  13181.     -- loop a certain number of times
  13182.     stop = time() + sample_interval
  13183.     for i = 1 to floor(t / sample_interval * sample_count) do
  13184.         if time() < stop then
  13185.         else
  13186.         end if
  13187.     end for
  13188.     end if
  13189. end procedure
  13190.  
  13191. SCREEN.E
  13192. 8404
  13193. -- screen.e: access to the screen
  13194.  
  13195.           ---------------------
  13196.           -- graphics screen --
  13197.           ---------------------
  13198. -- in calls to read_screen and write_screen
  13199. -- the screen looks like:
  13200.  
  13201. -- (1,1)..................(1,HSIZE)
  13202. -- ................................
  13203. -- ................................
  13204. -- (VSIZE,1)..........(VSIZE,HSIZE)
  13205.  
  13206. -- Note however that pixel() uses origin (0,0) coordinates
  13207.  
  13208. global constant HSIZE = 80 * 8,  -- horizontal size (char positions)
  13209.         VSIZE = 26 * 16  -- vertical size (lines)
  13210.  
  13211. global type h_coord(integer x)
  13212. -- true if x is a horizontal screen coordinate
  13213.     return x >= 1 and x <= HSIZE
  13214. end type
  13215.  
  13216. global type v_coord(integer y)
  13217. -- true if y is a vertical screen coordinate
  13218.     return y >= 1 and y <= VSIZE
  13219. end type
  13220.  
  13221. global type extended_h_coord(atom x)
  13222.     -- horizontal coordinate, can be reasonably far off the screen
  13223.     return x >= -1000 and x <= HSIZE + 1000
  13224. end type
  13225.  
  13226. global type extended_v_coord(atom y)
  13227.     -- vertical coordinate, can be reasonably far off the screen
  13228.     return y >= -1000 and y <= VSIZE + 1000
  13229. end type
  13230.  
  13231. integer last_text_color
  13232. last_text_color = -1
  13233.  
  13234. global procedure set_color(integer color)
  13235. -- all foreground color changes come through here
  13236.     last_text_color = color
  13237. end procedure
  13238.  
  13239. integer last_bk_color
  13240. last_bk_color = -1
  13241.  
  13242. global procedure set_bk_color(integer color)
  13243. -- all background color changes come through here
  13244.     last_bk_color = color
  13245. end procedure
  13246.  
  13247. global boolean scanon -- galaxy scan on/off
  13248.  
  13249. integer cursor_line, cursor_column
  13250.  
  13251. -- override position()
  13252.  
  13253. without warning
  13254. global procedure position(integer line, integer column)
  13255.     cursor_line = line
  13256.     cursor_column = column
  13257. end procedure
  13258.  
  13259. global type image(sequence s)
  13260. -- a 2-d rectangular image
  13261.     return sequence(s[1])
  13262. end type
  13263.  
  13264. global procedure console_puts(object string)
  13265. -- write text to the screen
  13266.     sequence gpos
  13267.     
  13268.     if atom(string) then
  13269.     string = {string}
  13270.     elsif length(string) = 0 then
  13271.     return
  13272.     end if
  13273.     
  13274.     gpos = {(cursor_column-1) * 8, (cursor_line-1) * 16}  -- {x pixel, y pixel}
  13275.     cursor_column += length(string)
  13276.     putsxy(gpos, string, last_text_color, last_bk_color, 'a')
  13277. end procedure
  13278.  
  13279. global procedure console_printf(sequence format, object values)
  13280. -- write printf output to the screen
  13281.     console_puts(sprintf(format, values))   
  13282. end procedure
  13283.  
  13284. global function is_pod(image s)
  13285. -- check if an image contains any POD pixels, range 16..31 
  13286.     sequence row
  13287.     
  13288.     for i = 1 to length(s) do
  13289.     row = s[i]
  13290.     for j = 1 to length(row) do
  13291.         if row[j] >= 16 and row[j] <= 31 then
  13292.         return TRUE  
  13293.         end if
  13294.     end for
  13295.     end for
  13296.     return FALSE
  13297. end function
  13298.  
  13299. global function all_clear(image s)
  13300. -- check if an image contains only 0's, stars and torpedo/phasor/explosion
  13301. -- "fluff".
  13302. -- 33..47 is just "fluff" (not really there - phasors etc.)
  13303. -- 32 is transparent areas of an object
  13304.     sequence row
  13305.     
  13306.     for i = 1 to length(s) do
  13307.     row = s[i]
  13308.     for j = 1 to length(row) do
  13309.         if row[j] >= 1 and row[j] <= 32 then
  13310.         return FALSE  
  13311.         end if
  13312.     end for
  13313.     end for
  13314.     return TRUE
  13315. end function
  13316.  
  13317. global sequence screen -- Contains a copy of what should be on the
  13318.                -- action screen above the console.
  13319.                -- The galaxy scan is handled separately.
  13320.                
  13321. global function read_screen(h_coord x, extended_v_coord y, image shape)
  13322. -- return the rectangular 2-d image at (x, y) with the same dimensions as shape
  13323.     sequence r
  13324.     integer width1
  13325.     
  13326.     width1 = length(shape[1])-1
  13327.     r = repeat(0, length(shape))
  13328.     y -= 1
  13329.     for i = 1 to length(shape) do
  13330.     r[i] = screen[y+i][x..x+width1]
  13331.     end for
  13332.     return r
  13333. end function
  13334.  
  13335. global function read_torp(h_coord x, v_coord y)
  13336. -- read the torpedo shape - assumed to be 2x2 for higher performance
  13337.     return {screen[y][x..x+1], 
  13338.         screen[y+1][x..x+1]}
  13339. end function
  13340.  
  13341. global function update_image(image background, positive_int x, positive_int y,
  13342.                  image shape)
  13343. -- write shape into background image    
  13344.     integer width1
  13345.     
  13346.     width1 = length(shape[1])-1
  13347.     y -= 1
  13348.     for i = 1 to length(shape) do
  13349.     background[y+i][x..x+width1] = shape[i]
  13350.     end for
  13351.     return background
  13352. end function
  13353.  
  13354. global procedure write_screen(h_coord x, extended_v_coord y, image shape)
  13355. -- write a rectangular 2-d image into the screen variable and onto the 
  13356. -- physical screen
  13357.  
  13358.     integer width1
  13359.     
  13360.     width1 = length(shape[1])-1
  13361.     y -= 1
  13362.     for i = 1 to length(shape) do
  13363.     screen[y+i][x..x+width1] = shape[i]
  13364.     end for
  13365.     if not scanon then
  13366.     display_image({x-1, y}, shape)
  13367.     end if
  13368. end procedure
  13369.  
  13370. -- delayed-write rectangular region {{xmin,ymin}, {xmax, ymax}}
  13371. object delayed 
  13372. delayed = 0
  13373.  
  13374. global procedure delayed_write_screen(h_coord x, extended_v_coord y, image shape)
  13375. -- write a rectangular 2-d image into the screen variable but *not* to the 
  13376. -- physical screen (yet). Avoids flicker.
  13377.  
  13378.     integer w, x1, y1
  13379.     
  13380.     w = length(shape[1])-1
  13381.     y -= 1
  13382.     for i = 1 to length(shape) do
  13383.     screen[y+i][x..x+w] = shape[i]
  13384.     end for
  13385.     y += 1
  13386.     x1 = x + w
  13387.     y1 = y + length(shape)-1
  13388.     if atom(delayed) then
  13389.     delayed = {{x,y},{x1,y1}}
  13390.     else
  13391.     -- enlarge the delayed-write region?
  13392.     if x < delayed[1][1] then
  13393.         delayed[1][1] = x
  13394.     end if
  13395.     if y < delayed[1][2] then
  13396.         delayed[1][2] = y
  13397.     end if
  13398.     if x1 > delayed[2][1] then
  13399.         delayed[2][1] = x1
  13400.     end if
  13401.     if y1 > delayed[2][2] then
  13402.         delayed[2][2] = y1
  13403.     end if
  13404.     end if
  13405. end procedure
  13406.  
  13407. global procedure flush_screen()
  13408. -- write the delayed-write region to the physical screen   
  13409.     sequence delayed_image
  13410.     natural xmin, xmax, ybase
  13411.     
  13412.     if not scanon and sequence(delayed) then
  13413.     delayed_image = repeat(0, delayed[2][2] - delayed[1][2] + 1)
  13414.     xmin = delayed[1][1]
  13415.     xmax = delayed[2][1]
  13416.     ybase = delayed[1][2]-1
  13417.     for i = 1 to length(delayed_image) do
  13418.         delayed_image[i] = screen[ybase+i][xmin..xmax]
  13419.     end for
  13420.     display_image(delayed[1]-1, delayed_image)
  13421.     end if
  13422.     delayed = 0
  13423. end procedure
  13424.  
  13425. global procedure write_torp(extended_h_coord x, v_coord y, image shape)
  13426. -- write a torpedo-shaped object - assumed to be 2x2 for higher performance
  13427.     screen[y  ][x..x+1] = shape[1]
  13428.     screen[y+1][x..x+1] = shape[2]
  13429.     if not scanon then
  13430.     x -= 1
  13431.     pixel(shape[1], {x, y-1})
  13432.     pixel(shape[2], {x, y  })
  13433.     end if
  13434. end procedure
  13435.  
  13436. global constant BLANK_LINE = repeat(' ', 80)
  13437.  
  13438. sequence black_screen
  13439. -- (doesn't use much space, because of shared pointers)
  13440. black_screen = repeat(repeat(BLACK, HSIZE), VSIZE)
  13441.  
  13442. -- quadrants on galaxy scan
  13443. global constant QXSIZE = 64, 
  13444.         QYSIZE = 40,
  13445.         QXBASE = 31,
  13446.         QYBASE = -8      
  13447.  
  13448. sequence blue_screen -- background for scan
  13449. sequence blue_black_line, blue_line
  13450. blue_screen = repeat(0, VSIZE)
  13451. blue_black_line = repeat(BLUE, QXBASE+QXSIZE) & 
  13452.           repeat(BLACK, QXSIZE*G_SIZE) &
  13453.           repeat(BLUE, QXBASE+QXSIZE)
  13454. blue_line = repeat(BLUE, HSIZE)
  13455. for i = 1 to VSIZE do
  13456.     if i > QYBASE+QYSIZE and i <= QYBASE+QYSIZE+G_SIZE*QYSIZE then
  13457.     blue_screen[i] = blue_black_line
  13458.     else
  13459.     blue_screen[i] = blue_line
  13460.     end if
  13461. end for
  13462.  
  13463. global procedure BlueScreen()
  13464. -- set physical upper screen to BLUE for scan
  13465.     display_image({0,0}, blue_screen)
  13466. end procedure
  13467.  
  13468. global procedure BlackScreen()
  13469. -- Set physical upper screen to BLACK
  13470. -- and set the screen variable too.
  13471. -- Initially the screen variable is undefined
  13472.  
  13473.     screen = black_screen
  13474.     if not scanon then
  13475.     display_image({0,0}, screen)
  13476.     end if
  13477. end procedure
  13478.  
  13479. global procedure ShowScreen()
  13480. -- rewrite screen after galaxy scan
  13481.     display_image({0, 0}, screen)
  13482. end procedure
  13483.  
  13484.        ----------------------------
  13485.        -- text portion of screen --
  13486.        ----------------------------
  13487.  
  13488. global constant QUAD_LINE = VSIZE/16 + 1,
  13489.         WARP_LINE = VSIZE/16 + 2,
  13490.         CMD_LINE  = VSIZE/16 + 3,
  13491.         MSG_LINE  = VSIZE/16 + 4
  13492.  
  13493. global constant CMD_POS = 18,     -- place for first char of user command
  13494.            WARP_POS = 9,      -- place for "WARP:" to appear
  13495.            DREP_POS = 51,     -- place for damage report
  13496.            WEAPONS_POS = 30,  -- place for torpedos/pos/deflectors display
  13497.            ENERGY_POS = 67,   -- place for ENERGY display
  13498.            MSG_POS = 16,      -- place for messages to start
  13499.            DIRECTIONS_POS = 1 -- place to put directions
  13500.  
  13501. SOUNDEFF.E
  13502. 4383
  13503. -- soundeff.e: Sound Effects
  13504.  
  13505. constant FREQ = 1, DURATION = 2
  13506.  
  13507. sequence sound_stream  -- sounds to be played
  13508. sound_stream = {{0,0}}
  13509.  
  13510. boolean playing_sound
  13511. playing_sound = FALSE
  13512.  
  13513. atom backlog  -- number of seconds of sounds still to play
  13514. backlog = 0
  13515.  
  13516. global function task_sound_effect()
  13517. -- process a stream of sound frequencies and durations
  13518.     
  13519.     if playing_sound then
  13520.     -- we've finished the previous frequency:
  13521.     backlog -= sound_stream[1][DURATION]
  13522.     sound_stream = sound_stream[2..length(sound_stream)]
  13523.     end if
  13524.     if length(sound_stream) > 0 then
  13525.     -- start a new frequency
  13526.     playing_sound = TRUE
  13527.     -- turn on the speaker
  13528.     sound(sound_stream[1][FREQ])
  13529.     -- we'll come back later to change it
  13530.     schedule(t_sound_effect, 0, sound_stream[1][DURATION], 0, {})
  13531.     else
  13532.     -- nothing left to do
  13533.     playing_sound = FALSE
  13534.     sound(0)
  13535.     schedule(t_sound_effect, INACTIVE, INACTIVE, 0, {})
  13536.     backlog = 0 -- otherwise f.p. "fuzz" might build up
  13537.     end if
  13538.     return {}
  13539. end function
  13540.  
  13541. procedure start_sound_effect()
  13542. -- start a new sound effect
  13543.     if QUIET then
  13544.     return
  13545.     end if
  13546.     if not playing_sound then
  13547.     schedule(t_sound_effect, 0, 0, 0, {}) -- start immediately
  13548.     end if
  13549.     -- else task_sound_effect is currently processing another effect -
  13550.     -- it will continue processing the sound stream when it's ready
  13551. end procedure
  13552.  
  13553. global procedure errbeep()
  13554. -- error signal
  13555.     if backlog < 1 then
  13556.     sound_stream = append(sound_stream, {1000, 0.1})
  13557.     backlog += .1
  13558.     start_sound_effect()
  13559.     end if
  13560. end procedure
  13561.  
  13562. global procedure explosion_sound(natural n)
  13563. -- something is destroyed
  13564.     if backlog < 2 then
  13565.     for i = 1 to floor(n/3) do
  13566.         sound_stream = append(sound_stream, {20+rand(30), .02})
  13567.         backlog += .02
  13568.     end for
  13569.     for i = 1 to 2*n do
  13570.         sound_stream = append(sound_stream, {200+rand(150), .01})
  13571.         backlog += .01
  13572.     end for
  13573.     for i = 1.5*n to 3 by -1 do
  13574.         sound_stream = append(sound_stream, {19+rand(i/2), .02})
  13575.         backlog += .02
  13576.     end for
  13577.     start_sound_effect()
  13578.     end if
  13579. end procedure
  13580.  
  13581. global procedure phasor_sound(atom n)
  13582. -- phasor hits enemy with n-unit blast
  13583.     if backlog < 0.4 then
  13584.     -- 0.4 seconds, no matter what n is
  13585.     for i = 1 to 1+log(n+1) do
  13586.         sound_stream = append(sound_stream, {1000, .025})
  13587.         sound_stream = append(sound_stream, {3000, .025})
  13588.         backlog += .05
  13589.     end for
  13590.     start_sound_effect()
  13591.     end if
  13592. end procedure
  13593.  
  13594. global procedure deflected_sound()
  13595. -- sound of a deflected torpedo
  13596.     if backlog < 0.4 then
  13597.     sound_stream = append(sound_stream, {1000, .1})
  13598.     backlog += .1
  13599.     start_sound_effect()
  13600.     end if
  13601. end procedure
  13602.  
  13603. global procedure pod_sound(integer freq, atom duration)
  13604. -- pod in flight
  13605.     if backlog < 0.4 then
  13606.     sound_stream = append(sound_stream,{freq, duration})
  13607.     backlog += duration
  13608.     start_sound_effect()
  13609.     end if
  13610. end procedure
  13611.  
  13612. global procedure torpedo_sound(integer freq, atom duration)
  13613. -- torpedo in flight
  13614.     if backlog < 0.1 then
  13615.     sound_stream = append(sound_stream, {freq, duration})
  13616.     backlog += duration
  13617.     start_sound_effect()
  13618.     end if
  13619. end procedure
  13620.  
  13621. global procedure torpedo_hit()
  13622. -- torpedo hits enemy
  13623.     if backlog < 0.4 then
  13624.     sound_stream = append(sound_stream, {120, .35})
  13625.     backlog += .35
  13626.     start_sound_effect()
  13627.     end if
  13628. end procedure
  13629.  
  13630. global procedure Java_enter_sound()
  13631. -- Java enters quadrant
  13632.     if backlog < 0.4 then
  13633.     sound_stream &= {{120, .08},{240, .08}, {480, .08}, {960, .08}}
  13634.     backlog += .32
  13635.     start_sound_effect()
  13636.     end if
  13637. end procedure
  13638.  
  13639. global procedure Java_phasor_sound(integer freq, atom duration)
  13640. -- torpedo in flight
  13641.     if backlog < 0.4 then
  13642.     sound_stream = append(sound_stream, {freq, duration})
  13643.     backlog += duration
  13644.     start_sound_effect()
  13645.     end if
  13646. end procedure
  13647.  
  13648. global procedure docking_sound()
  13649. -- Euphoria successfully docks with a planet or base
  13650.     if backlog < 3.0 then
  13651.     for i = 1 to 3 do
  13652.         sound_stream &= {{2000, .07}, {5000, .07}}
  13653.         backlog += .14
  13654.     end for
  13655.     start_sound_effect()
  13656.     end if
  13657. end procedure
  13658.  
  13659. global procedure victory_sound()
  13660. -- sound when you win the game 
  13661. -- (no tasking going on at this point)
  13662.     if QUIET then
  13663.     return
  13664.     end if
  13665.     for j = 1 to 10 do
  13666.     for i = 1000 to 2000 by 20 do
  13667.         sound(i)
  13668.         delay(.02)
  13669.         sound(2*i)
  13670.         delay(.02)
  13671.     end for
  13672.     end for
  13673.     sound(0)
  13674. end procedure
  13675.  
  13676. VARS.E
  13677. 6479
  13678. -- vars.e
  13679. -- declarations of global variables and constants
  13680.  
  13681. global constant TRUE = 1, FALSE = 0
  13682.  
  13683. global constant BS = 8  -- backspace key
  13684.  
  13685. global constant G_SIZE = 7 -- the galaxy is a G_SIZE x G_SIZE
  13686.                -- grid of quadrants
  13687.  
  13688. global constant INVISIBLE_CHAR = 32 -- prints as ' ', but has different value
  13689.  
  13690. global constant TICK_RATE = 100, TICK_PERIOD = 1/TICK_RATE
  13691.  
  13692. global type boolean(integer x)
  13693.     return x = TRUE or x = FALSE
  13694. end type
  13695.  
  13696. global type char(integer c)
  13697. -- true if c is a character that can be printed on the screen
  13698.     return c >= 0 and c <= 127
  13699. end type
  13700.  
  13701. global type byte(integer x)
  13702.     return x >= -1 and x <= 255
  13703. end type
  13704.  
  13705. global type natural(integer x)
  13706.     return x >= 0
  13707. end type
  13708.  
  13709. global type positive_int(integer x)
  13710.     return x >= 1
  13711. end type
  13712.  
  13713. global type positive_atom(atom x)
  13714.     return x >= 0
  13715. end type
  13716.  
  13717. -----------------------------------------------------------------------------
  13718. -- the 2-d quadrant sequence: status of all objects in the current quadrant
  13719. -- The first object is always the Euphoria. There will be 0 or more
  13720. -- additional objects (planets/bases/enemy ships).
  13721. -----------------------------------------------------------------------------
  13722. global constant EUPHORIA = 1    -- object 1 is Euphoria
  13723.  
  13724. global constant
  13725.     Q_TYPE =   1, -- type of object
  13726.     Q_EN   =   2, -- energy
  13727.     Q_TORP =   3, -- number of torpedos
  13728.     Q_DEFL =   4, -- number of deflectors
  13729.     Q_FRATE =  5, -- firing rate
  13730.     Q_MRATE =  6, -- moving rate
  13731.     Q_TARG =   7, -- target
  13732.     Q_PBX =    8, -- planet/base sequence index
  13733.     Q_X =      9, -- x coordinate
  13734.     Q_Y =     10, -- y coordinate
  13735.     Q_UNDER = 11, -- characters underneath
  13736.     Q_DIRECTION = 12 -- direction enemy ship moved in last time
  13737. global constant QCOLS = 12 -- number of attributes for each object in quadrant
  13738.     
  13739. global sequence quadrant
  13740. quadrant = repeat(repeat(0, QCOLS), 1)
  13741.  
  13742. global type valid_quadrant_row(integer x)
  13743. -- true if x is a valid row number in the quadrant sequence
  13744.     return x >= 1 and x <= length(quadrant)
  13745. end type
  13746.  
  13747. global type quadrant_row(object x)
  13748. -- either a quadrant row or -1 or 0 (null value)
  13749.     return valid_quadrant_row(x) or x = -1 or x = 0
  13750. end type
  13751.  
  13752. -----------------------------------------------------------------------------
  13753. -- the 3-d galaxy sequence: (records number of objects of each type in
  13754. --                           each quadrant of the galaxy)
  13755. -----------------------------------------------------------------------------
  13756. -- first two subscripts select quadrant, 3rd is type...
  13757.  
  13758. global constant DEAD = 0 -- object that has been destroyed
  13759. global constant
  13760.     G_EU = 1,   -- Euphoria (marks if Euphoria has been this quadrant)
  13761.     G_KRC = 2,  -- K&R C ship
  13762.     G_ANC = 3,  -- ANSI C ship
  13763.     G_CPP = 4,  -- C++
  13764.     G_BAS = 5,  -- basic
  13765.     G_JAV = 6,  -- Java
  13766.     G_PL = 7,   -- planet
  13767.     G_BS = 8,   -- base
  13768.     NTYPES = 8, -- number of different types of (real) object
  13769.     G_POD = 9   -- temporary pseudo object
  13770.  
  13771. global sequence otype
  13772.  
  13773. global type object_type(integer x)
  13774. -- is x a type of object?
  13775.     return x >= 1 and x <= NTYPES
  13776. end type
  13777.  
  13778. global sequence galaxy
  13779.  
  13780. -----------------------------------------------------------------------------
  13781. -- the planet/base 2-d sequence (info on each planet and base in the galaxy)
  13782. -----------------------------------------------------------------------------
  13783. global constant NBASES = 3,  -- number of bases
  13784.         NPLANETS = 6 -- number of planets
  13785. global constant
  13786.     PROWS = NBASES+NPLANETS,
  13787.     PCOLS = 9     -- number of planet/base attributes
  13788. global constant
  13789.     P_TYPE  = 1, -- G_PL/G_BS/DEAD
  13790.     P_QR    = 2, -- quadrant row
  13791.     P_QC    = 3, -- quadrant column
  13792.     P_X     = 4, -- x coordinate within quadrant
  13793.     P_Y     = 5, -- y coordinate within quadrant
  13794.     P_EN    = 6, -- energy available
  13795.     P_TORP  = 7, -- torpedos available
  13796.     P_POD   = 8  -- pods available
  13797.  
  13798. global sequence pb
  13799. pb = repeat(repeat(0, PCOLS), PROWS)
  13800.  
  13801. global type pb_row(integer x)
  13802. -- is x a valid row in the planet/base sequence?
  13803.     return x >= 1 and x <= PROWS
  13804. end type
  13805.  
  13806. global type g_index(integer x)
  13807. -- a valid row or column index into the galaxy sequence
  13808.     return x >= 1 and x <= G_SIZE
  13809. end type
  13810.  
  13811. global boolean gameover  -- is game over?
  13812.  
  13813. global g_index qrow, qcol  -- current quadrant row and column
  13814.  
  13815. ------------------
  13816. -- BASIC status:
  13817. ------------------
  13818. global constant
  13819.     TRUCE    = 0,
  13820.     HOSTILE  = 1,
  13821.     CLOAKING = 2
  13822.  
  13823. type basic_status(object x)
  13824.     return find(x, {TRUCE, HOSTILE, CLOAKING})
  13825. end type
  13826.  
  13827. global basic_status bstat       -- BASIC status
  13828. global quadrant_row basic_targ  -- BASIC group target
  13829. global boolean truce_broken     -- was the truce with the BASICs broken?
  13830.  
  13831. global boolean shuttle -- are we in the shuttle?
  13832.  
  13833. -----------------
  13834. -- damage report:
  13835. -----------------
  13836. global constant NSYS = 5  -- number of systems that can be damaged
  13837. global constant ENGINES        = 1,
  13838.         TORPEDOS       = 2,
  13839.         GUIDANCE       = 3,
  13840.         PHASORS        = 4,
  13841.         GALAXY_SENSORS = 5
  13842.  
  13843. global constant dtype = {"ENGINES",
  13844.              "TORPEDO LAUNCHER",
  13845.              "GUIDANCE SYSTEM",
  13846.              "PHASORS",
  13847.              "SENSORS"}
  13848. global type subsystem(integer x)
  13849.     return x >= 1 and x <= NSYS
  13850. end type
  13851.  
  13852. global sequence reptime  -- time to repair a subsystem
  13853. reptime = repeat(0, NSYS)
  13854.  
  13855. type damage_count(integer x)
  13856.     return x >= 0 and x <= NSYS
  13857. end type
  13858.  
  13859. global damage_count ndmg
  13860.  
  13861. --------------
  13862. -- warp speed:
  13863. --------------
  13864. global constant MAX_WARP = 5
  13865.  
  13866. global type warp(integer x)
  13867.     return x >= 0 and x <= MAX_WARP
  13868. end type
  13869.  
  13870. global warp curwarp, wlimit
  13871.  
  13872. global type direction(atom x)
  13873.     return x >= 0 and x < 10
  13874. end type
  13875.  
  13876. global direction curdir -- current Euphoria direction
  13877.  
  13878. -------------------------------------
  13879. -- Euphoria position and direction:
  13880. -------------------------------------
  13881. type euphoria_x_inc(integer x)
  13882.     return x >= -1 and x <= +1
  13883. end type
  13884.  
  13885. type euphoria_y_inc(integer x)
  13886.     return x >= -1 and x <= +1
  13887. end type
  13888.  
  13889. global euphoria_x_inc exi
  13890. global euphoria_y_inc eyi
  13891.  
  13892. global sequence esym,   -- euphoria/shuttle symbol
  13893.         esyml,  -- euphoria/shuttle facing left
  13894.         esymr   -- euphoria/shuttle facing right
  13895.  
  13896. global sequence nobj  -- number of each type of object in galaxy
  13897.  
  13898. global sequence wipeout
  13899. wipeout = {}
  13900.  
  13901. type game_level(integer x)
  13902.     return x = 'n' or x = 'e'
  13903. end type
  13904.  
  13905. global game_level level
  13906.  
  13907. WEAPONS.E
  13908. 16295
  13909. -- weapons.e
  13910. -- phasors, torpedos, antimatter pods
  13911.  
  13912. extended_h_coord x0
  13913. extended_v_coord y0
  13914. atom xinc
  13915. atom yinc
  13916.  
  13917. function diftype(valid_quadrant_row shooter, valid_quadrant_row victim)
  13918. -- return TRUE if shooter and victim are on opposing sides
  13919.  
  13920.     if quadrant[shooter][Q_TYPE] = G_BS then
  13921.     return victim != EUPHORIA
  13922.     else
  13923.     if find(quadrant[shooter][Q_TYPE], {G_KRC, G_ANC, G_CPP}) and
  13924.        find(quadrant[victim][Q_TYPE] , {G_KRC, G_ANC, G_CPP}) then
  13925.         -- both are C ships
  13926.         return FALSE
  13927.     else
  13928.         return quadrant[shooter][Q_TYPE] != quadrant[victim][Q_TYPE]
  13929.     end if
  13930.     end if
  13931. end function
  13932.  
  13933. function task_pod_effect(integer i, sequence p)
  13934. -- make the pod explosion effect
  13935.  
  13936.     if i < 25 then
  13937.     all_palette(rand(repeat({63, 63, 63}, 16)))
  13938.     i += 1
  13939.     return {i, p}
  13940.     else
  13941.     all_palette(p)
  13942.     delete_task(current_task)
  13943.     return {}
  13944.     end if
  13945. end function
  13946.  
  13947. procedure pod_effect(h_coord rx,v_coord ry)
  13948. -- Detonate an antimatter pod. All objects in the quadrant are
  13949. -- affected. It's like a 1000-unit phasor blast directed toward everyone
  13950. -- *including* the Euphoria and all planets and bases in the quadrant.
  13951. -- The closer an object is to the pod when it explodes, the more
  13952. -- of a blast that object will feel.
  13953.     sequence p
  13954.     task t
  13955.     valid_quadrant_row shooter
  13956.     
  13957.     p = get_all_palette()
  13958.     end_scan()
  13959.     -- add POD to the quadrant temporarily
  13960.     quadrant = append(quadrant, repeat(0, length(quadrant[1]))) 
  13961.     shooter = length(quadrant)    
  13962.     quadrant[shooter][Q_TYPE] = G_POD
  13963.     quadrant[shooter][Q_X] = rx
  13964.     quadrant[shooter][Q_Y] = ry
  13965.     
  13966.     for i = length(quadrant)-1 to 1 by -1 do
  13967.     if quadrant[i][Q_TYPE] != DEAD then
  13968.         dodmg(bcalc(1000, shooter, i), FALSE, shooter, i)
  13969.     end if
  13970.     end for
  13971.     quadrant = quadrant[1..length(quadrant)-1] -- delete POD
  13972.     t = create_task(routine_id("task_pod_effect"))
  13973.     schedule(t, 0, .10, .02, {1, p})
  13974. end procedure
  13975.  
  13976. global boolean EnterPressed
  13977.  
  13978. function task_pod(extended_h_coord prev_rx,
  13979.           extended_v_coord prev_ry,
  13980.           extended_h_coord x,
  13981.           extended_v_coord y,
  13982.           extended_h_coord rx,
  13983.           extended_v_coord ry,
  13984.           atom xinc,
  13985.           atom yinc,
  13986.           sequence under)
  13987. -- Independent task to run one iteration of an antimatter pod.
  13988. -- There can be many "instances" of this task active simultaneously.
  13989.     image c
  13990.  
  13991.     if rx >= 1 and rx <= HSIZE-length(POD[1]) and
  13992.       ry >= 1 and ry <= VSIZE-length(POD) then
  13993.     if length(under) != 0 then
  13994.         write_screen(under[1][1], under[1][2], under[1][3])
  13995.     end if
  13996.     c = read_screen(rx, ry, POD)
  13997.     prev_rx = rx
  13998.     prev_ry = ry
  13999.     if all_clear(c) then
  14000.         -- keep stars, lose phasor/torpedo dust
  14001.         write_screen(rx, ry, POD)
  14002.         c = c * (c > 64) 
  14003.         under = {{rx, ry, c}}
  14004.     else
  14005.         under = {}
  14006.     end if
  14007.     if EnterPressed then
  14008.         pod_effect(rx, ry)
  14009.     end if
  14010.     pod_sound(290, .01)
  14011.     if not EnterPressed then
  14012.         while TRUE do
  14013.         x += xinc
  14014.         y += yinc
  14015.         rx = floor(x+0.5)
  14016.         ry = floor(y+0.5)
  14017.         if rx != prev_rx or ry != prev_ry then
  14018.             exit
  14019.         end if
  14020.         end while
  14021.         return {prev_rx, prev_ry, x, y, rx, ry, xinc, yinc, under}
  14022.     end if
  14023.     end if
  14024.  
  14025.     if length(under) then
  14026.     write_screen(under[1][1], under[1][2], under[1][3])
  14027.     end if
  14028.     delete_task(current_task)
  14029.     return {}
  14030. end function
  14031.  
  14032. global procedure pod()
  14033. -- fire a pod from shooter starting from (x0,y0) and
  14034. -- proceeding in steps of xinc, yinc until Enter is pressed, 
  14035. -- or the edge of the screen is reached
  14036.  
  14037.     task t
  14038.     
  14039.     t = create_task(routine_id("task_pod"))
  14040.     -- start right away, repeat every .06 sec.
  14041.     schedule(t, 0, .04, 0.02, {0, 0, x0, y0, x0, y0, xinc, yinc, {}}) 
  14042.     msg("PRESS Enter TO DETONATE!")
  14043.     msg("PRESS Enter TO DETONATE!")
  14044. end procedure
  14045.  
  14046. constant TORPEDO_ZERO = TORPEDO * 0
  14047.  
  14048. function task_phasor(extended_h_coord prev_rx,
  14049.              extended_v_coord prev_ry,
  14050.              extended_h_coord x,
  14051.              extended_v_coord y,
  14052.              extended_h_coord rx,
  14053.              extended_v_coord ry,
  14054.              atom xinc,
  14055.              atom yinc,
  14056.              sequence under,
  14057.              positive_atom strength,
  14058.              valid_quadrant_row my_shooter
  14059. )
  14060. -- Independent task to run one iteration of a phasor.
  14061. -- There can be many "instances" of this task active simultaneously.
  14062.     boolean ahit
  14063.     sequence who
  14064.     positive_atom units
  14065.     image c
  14066.     object u
  14067.     quadrant_row victim
  14068.     
  14069.     ahit = FALSE
  14070.     if rx >= 1 and rx <= HSIZE-TORPEDO_WIDTH and
  14071.       ry >= 1 and ry <= VSIZE-TORPEDO_HEIGHT then
  14072.     c = read_torp(rx, ry)
  14073.     if all_clear(c) then
  14074.         prev_rx = rx
  14075.         prev_ry = ry
  14076.         c *= (c > 64)
  14077.         if equal(c, TORPEDO_ZERO) then
  14078.         under = append(under, {rx, ry, 0})
  14079.         else
  14080.         under = append(under, {rx, ry, c})
  14081.         end if
  14082.         write_torp(rx, ry, TORPEDO)
  14083.     else
  14084.         who = who_is_it(rx, ry, TORPEDO)
  14085.         if find(FALSE, who = my_shooter) then
  14086.         -- if anyone other than the shooter
  14087.         ahit = TRUE
  14088.         end if
  14089.     end if
  14090.     if not ahit then
  14091.         -- skip to next location on path and return
  14092.         while TRUE do 
  14093.         x += xinc
  14094.         y += yinc
  14095.         rx = floor(x+0.5)
  14096.         ry = floor(y+0.5)
  14097.         if rx != prev_rx or ry != prev_ry then
  14098.             exit
  14099.         end if
  14100.         end while
  14101.         return {prev_rx, prev_ry, x, y, rx, ry, xinc, yinc,
  14102.             under, strength, my_shooter}
  14103.     end if
  14104.     end if
  14105.  
  14106.     -- phasor completed
  14107.     if ahit then
  14108.     who = who_is_it(rx, ry, TORPEDO)
  14109.     for i = 1 to length(who) do
  14110.         if who[i] != my_shooter then
  14111.         victim = who[i]
  14112.         exit
  14113.         end if
  14114.     end for
  14115.     if diftype(my_shooter, victim) then
  14116.         units = bcalc(strength, my_shooter, victim)
  14117.         phasor_sound(units)
  14118.         dodmg(units, FALSE, my_shooter, victim)
  14119.     end if
  14120.     if gameover then
  14121.         delay(.10)
  14122.     else
  14123.         -- come back and erase the phasor a bit later
  14124.         schedule(current_task, .09, .09, .02, {})
  14125.         return {0, 0, 0, 0, 0, 0, 0, 0, under, 0, 1}
  14126.     end if
  14127.     end if
  14128.     
  14129.     -- Erase the phasor, most recent first.
  14130.     -- Looks better when it's done quickly.
  14131.     for i = length(under) to 1 by -1 do
  14132.     x = under[i][1]
  14133.     y = under[i][2]
  14134.     c = read_torp(x, y)
  14135.     -- Some care is required, 
  14136.     -- a solid object may have moved across the phasor path.
  14137.     if c[1][1] >= 33 then c[1][1] = 0 end if
  14138.     if c[1][2] >= 33 then c[1][2] = 0 end if
  14139.     if c[2][1] >= 33 then c[2][1] = 0 end if
  14140.     if c[2][2] >= 33 then c[2][2] = 0 end if
  14141.     u = under[i][3]
  14142.     if sequence(u) then
  14143.         -- star(s) to replace
  14144.         for r = 1 to TORPEDO_HEIGHT do         
  14145.         for s = 1 to TORPEDO_WIDTH do
  14146.             if c[r][s] = 0 and u[r][s] > 64 then
  14147.             c[r][s] = u[r][s]  -- replace star
  14148.             end if
  14149.         end for
  14150.         end for
  14151.     end if
  14152.     write_torp(x, y, c)
  14153.     end for
  14154.     delete_task(current_task)
  14155.     return {}
  14156. end function
  14157.  
  14158. global procedure phasor(valid_quadrant_row shooter, positive_atom strength)
  14159. -- fire a phasor from shooter starting from (x0,y0) and
  14160. -- proceeding in steps of xinc, yinc until something is hit or the
  14161. -- edge of the screen is reached
  14162.     task t
  14163.     
  14164.     t = create_task(routine_id("task_phasor"))
  14165.     -- Start right away, repeat until done.
  14166.     -- Normal delay is less than the tick period (1/100),
  14167.     -- but setting T_EARLY to the tick period will give us the correct number
  14168.     -- of executions in each period (usually).
  14169.     schedule(t, 0, .002, TICK_PERIOD, 
  14170.          {0, 0, x0, y0, x0, y0, xinc, yinc, {}, strength, shooter}) 
  14171. end procedure
  14172.  
  14173. function task_torpedo(extended_h_coord prev_rx,
  14174.               extended_v_coord prev_ry,
  14175.               extended_h_coord x,
  14176.               extended_v_coord y,
  14177.               extended_h_coord rx,
  14178.               extended_v_coord ry,
  14179.               atom xinc,
  14180.               atom yinc,
  14181.               sequence under,
  14182.               integer freq,
  14183.               valid_quadrant_row my_shooter)
  14184. -- Independent task to run one iteration of a torpedo.
  14185. -- There can be many "instances" of this task active simultaneously.
  14186.  
  14187.     boolean ahit
  14188.     sequence who
  14189.     image c, u
  14190.     quadrant_row victim
  14191.     
  14192.     ahit = FALSE
  14193.     if rx >= 1 and rx <= HSIZE-TORPEDO_WIDTH and
  14194.       ry >= 1 and ry <= VSIZE-TORPEDO_HEIGHT then
  14195.     if length(under) = 7 then
  14196.         c = read_torp(under[1][1], under[1][2])
  14197.         c *= (c < 33)
  14198.         -- merge in any stars that were hidden
  14199.         c += ((c = 0) and (under[1][3] > 64)) * under[1][3]
  14200.         write_torp(under[1][1], under[1][2], c)
  14201.         under = under[2..length(under)]
  14202.     end if
  14203.     c = read_torp(rx, ry)
  14204.     if all_clear(c) then
  14205.         prev_rx = rx
  14206.         prev_ry = ry
  14207.         write_torp(rx, ry, TORPEDO)
  14208.         c *= (c > 64) -- only keep stars
  14209.         under = append(under, {rx, ry, c})
  14210.         torpedo_sound(freq, .02)
  14211.         if freq > 600 then
  14212.         freq -= 50
  14213.         end if
  14214.     else
  14215.         who = who_is_it(rx, ry, TORPEDO)
  14216.         if find(FALSE, who = my_shooter) then
  14217.         -- if anyone other than the shooter
  14218.         ahit = TRUE
  14219.         end if
  14220.     end if
  14221.     if not ahit then
  14222.         while TRUE do
  14223.         x += xinc
  14224.         y += yinc
  14225.         rx = floor(x+0.5)
  14226.         ry = floor(y+0.5)
  14227.         if rx != prev_rx or ry != prev_ry then
  14228.             exit
  14229.         end if
  14230.         end while
  14231.         return {prev_rx, prev_ry, x, y, rx, ry, xinc, yinc,
  14232.             under, freq, my_shooter}
  14233.     end if
  14234.     end if
  14235.  
  14236.     -- torpedo completed
  14237.     if ahit then
  14238.     who = who_is_it(rx, ry, TORPEDO)
  14239.     for i = 1 to length(who) do
  14240.         if who[i] != my_shooter then
  14241.         victim = who[i]
  14242.         exit
  14243.         end if
  14244.     end for
  14245.     if diftype(my_shooter, victim) then
  14246.         dodmg(4000, TRUE, my_shooter, victim)
  14247.     end if
  14248.     if gameover then
  14249.         delay(.05)
  14250.     else
  14251.         -- display for a fraction of a second before erasing
  14252.         schedule(current_task, .04, .04, .02, {})
  14253.         return {0, 0, 0, 0, 0, 0, 0, 0, under, 0, 1}
  14254.     end if
  14255.     end if
  14256.     
  14257.     for i = length(under) to 1 by -1 do
  14258.     x = under[i][1]
  14259.     y = under[i][2]
  14260.     c = read_torp(x, y)
  14261.     if c[1][1] >= 33 then c[1][1] = 0 end if
  14262.     if c[1][2] >= 33 then c[1][2] = 0 end if
  14263.     if c[2][1] >= 33 then c[2][1] = 0 end if
  14264.     if c[2][2] >= 33 then c[2][2] = 0 end if
  14265.     u = under[i][3]
  14266.     for r = 1 to TORPEDO_HEIGHT do         
  14267.         for s = 1 to TORPEDO_WIDTH do
  14268.         if c[r][s] = 0 and u[r][s] > 64 then
  14269.             c[r][s] = u[r][s]  -- put star back
  14270.         end if
  14271.         end for
  14272.     end for
  14273.     write_torp(x, y, c)
  14274.     end for
  14275.     delete_task(current_task)
  14276.     return {}
  14277. end function
  14278.  
  14279. global procedure torpedo(valid_quadrant_row shooter)
  14280. -- fire a torpedo from shooter starting from (x0,y0) and
  14281. -- proceeding in steps of xinc, yinc until something is hit or the
  14282. -- edge of the screen is reached
  14283.  
  14284.     task t
  14285.     
  14286.     t = create_task(routine_id("task_torpedo"))
  14287.     -- start right away, repeat every .01 sec.
  14288.     schedule(t, 0, .01, .001, {0,0,x0,y0,x0,y0,xinc,yinc,{},3500,shooter}) 
  14289. end procedure
  14290.  
  14291. type object_height(integer x)
  14292.     return x >= TORPEDO_HEIGHT and x <= length(PLANET)
  14293. end type
  14294.  
  14295. procedure euphoria_color(natural c)
  14296. -- change color of EUPHORIA 
  14297.     esym  += (esym != 32) * (c - esym)
  14298.     esyml += (esyml != 32) * (c - esyml)
  14299.     esymr += (esymr != 32) * (c - esymr)
  14300. end procedure
  14301.  
  14302. function task_Java_phasor(positive_atom blast,
  14303.               integer i,
  14304.               image v,
  14305.               image j,
  14306.               valid_quadrant_row shooter,
  14307.               valid_quadrant_row victim)
  14308.     h_coord targx
  14309.     v_coord targy
  14310.     natural c
  14311.     
  14312.     if quadrant[victim][Q_TYPE] != DEAD then
  14313.     targx = quadrant[victim][Q_X]
  14314.     targy = quadrant[victim][Q_Y]
  14315.     if i <= blast / 300 + 9 then
  14316.         Java_phasor_sound(1500 + 1000 * (integer(i / 2)), .08)
  14317.         if remainder(i, 2) then
  14318.         c = BRIGHT_WHITE
  14319.         else
  14320.         c = GREEN
  14321.         end if
  14322.         write_screen(targx, targy, v + (v != 32) * (c - v))
  14323.         if victim = EUPHORIA then
  14324.         euphoria_color(c)
  14325.         end if
  14326.         return {blast, i+1, v, j, shooter, victim}
  14327.     end if
  14328.     -- make sure right color is restored
  14329.     if quadrant[victim][Q_TYPE] = G_BS then
  14330.         v = BASE
  14331.     elsif quadrant[victim][Q_TYPE] = G_PL then
  14332.         v = PLANET
  14333.     end if
  14334.     write_screen(targx, targy, v)
  14335.     dodmg(blast, FALSE, shooter, victim)
  14336.     if victim = EUPHORIA then
  14337.         euphoria_color(YELLOW)
  14338.     end if
  14339.     end if
  14340.     if quadrant[shooter][Q_TYPE] != DEAD then
  14341.     write_screen(quadrant[shooter][Q_X], quadrant[shooter][Q_Y], j)
  14342.     quadrant[shooter][Q_MRATE] = 90
  14343.     quadrant[shooter][Q_FRATE] = 40
  14344.     end if
  14345.     delete_task(current_task)
  14346.     return {}
  14347. end function
  14348.  
  14349. global procedure Java_phasor(valid_quadrant_row shooter, positive_atom pen)
  14350. -- perform Java phasor: no phasor drawn, can't miss
  14351.  
  14352.     positive_atom blast
  14353.     h_coord targx
  14354.     v_coord targy
  14355.     image v, j
  14356.     natural len
  14357.     task t
  14358.     quadrant_row victim
  14359.     
  14360.     quadrant[shooter][Q_MRATE] = 0 -- don't move or fire until it's over
  14361.     quadrant[shooter][Q_FRATE] = 0
  14362.     j = read_screen(quadrant[shooter][Q_X], quadrant[shooter][Q_Y], JAVA_L)
  14363.     if equal(j, JAVA_L) then
  14364.     write_screen(quadrant[shooter][Q_X], quadrant[shooter][Q_Y], 
  14365.              JAVA_LS)
  14366.     else    
  14367.     write_screen(quadrant[shooter][Q_X], quadrant[shooter][Q_Y], 
  14368.              JAVA_RS)
  14369.     end if
  14370.     victim = quadrant[shooter][Q_TARG]
  14371.     targx = quadrant[victim][Q_X]
  14372.     targy = quadrant[victim][Q_Y]
  14373.     len   = length(oshape[quadrant[victim][Q_TYPE]][1][1])
  14374.     blast = bcalc(pen, shooter, victim)
  14375.     v = read_screen(targx, targy, oshape[quadrant[victim][Q_TYPE]][1])
  14376.     t = create_task(routine_id("task_Java_phasor"))
  14377.     schedule(t, 0, .15, .15, {blast, 1, v, j, shooter, victim})
  14378. end procedure
  14379.  
  14380. global procedure setpt(valid_quadrant_row r, boolean torp)
  14381. -- set up enemy (or base) phasor or torpedo
  14382.  
  14383.     positive_atom dist, rough_dist, lead, fuzz
  14384.     valid_quadrant_row targ
  14385.     extended_h_coord targx
  14386.     extended_v_coord targy
  14387.     object_type t
  14388.  
  14389.     x0 = quadrant[r][Q_X]
  14390.     y0 = quadrant[r][Q_Y]
  14391.     targ = quadrant[r][Q_TARG]
  14392.     -- aim roughly at center
  14393.     targx = quadrant[targ][Q_X] + 10
  14394.     targy = quadrant[targ][Q_Y] + 3 
  14395.     
  14396.     rough_dist = sqrt(power(x0-targx, 2) + power(y0-targy, 2))
  14397.     if targ = EUPHORIA and curwarp > 2 then
  14398.     -- Make a leading shot for better results.
  14399.     -- This is a rough adjustment for phasor or torpedo shot.
  14400.     lead = rough_dist / (830 * warp_time[1+curwarp]) * (1 + torp*4)
  14401.     targx += exi * lead
  14402.     targy += eyi * lead
  14403.     end if
  14404.     t = quadrant[r][Q_TYPE]
  14405.  
  14406.     -- decide which side to shoot from
  14407.     if x0 + 8 < targx then
  14408.     if t != G_BS then
  14409.         write_screen(x0, y0, oshape[t][2])      
  14410.     end if
  14411.     x0 += length(oshape[t][1][1])
  14412.     else
  14413.     if t != G_BS then
  14414.         write_screen(x0, y0, oshape[t][1])      
  14415.     end if
  14416.     x0 -= TORPEDO_WIDTH
  14417.     end if
  14418.     if y0 < targy then
  14419.     y0 += length(oshape[t][1])
  14420.     else
  14421.     y0 -= TORPEDO_HEIGHT
  14422.     end if
  14423.  
  14424.     -- add a bit of randomness so they might miss
  14425.     fuzz = 20 + rough_dist/10
  14426.     xinc = targx - x0 + rand(fuzz) - fuzz/2
  14427.     yinc = targy - y0 + rand(fuzz) - fuzz/2
  14428.     if xinc = 0 and yinc = 0 then
  14429.     xinc = 1 -- prevent infinite loop
  14430.     end if
  14431.     dist = sqrt(0.1 + xinc * xinc + yinc * yinc) / TORPEDO_HEIGHT
  14432.     xinc /= dist
  14433.     yinc /= dist
  14434.     -- make it a bit thicker
  14435.     xinc *= 0.8
  14436.     yinc *= 0.8
  14437. end procedure
  14438.  
  14439. type angle(atom x)
  14440.     return x >= -2 * PI and x <= 2 * PI
  14441. end type
  14442.  
  14443. global procedure esetpt(direction dir, integer dir_adjust)
  14444. -- set up for euphoria phasor/torpedo/pod firing
  14445.  
  14446.     angle theta
  14447.     atom xdir
  14448.     
  14449.     xdir = dir - 1
  14450.     if dir_adjust = '>' then
  14451.     xdir += .03333
  14452.     elsif dir_adjust = '<' then
  14453.     xdir -= .03333
  14454.     end if
  14455.     theta = xdir/8.0 * 2 * PI
  14456.     xinc = cos(theta) * TORPEDO_WIDTH
  14457.     yinc = -sin(theta) * TORPEDO_HEIGHT -- / ASPECT_RATIO
  14458.     
  14459.     -- make it a bit thicker:
  14460.     xinc *= 0.7
  14461.     yinc *= 0.7 
  14462.     
  14463.     x0 = quadrant[EUPHORIA][Q_X]
  14464.     y0 = quadrant[EUPHORIA][Q_Y]
  14465.     if curdir = 3 or curdir = 7 then
  14466.     -- Euphoria can face either way
  14467.     if xinc < -0.001 then
  14468.         esym = esyml
  14469.         write_screen(x0, y0, esym)
  14470.     elsif xinc > 0.001 then
  14471.         esym = esymr
  14472.         write_screen(x0, y0, esym)
  14473.     end if
  14474.     end if
  14475.     -- start in middle
  14476.     x0 += floor(length(esym[1])/2)
  14477.     y0 += floor(length(esym)/2)
  14478.     -- skip first two iterations (inside the ship image)
  14479.     x0 = floor(x0 + 2*xinc + 0.5)
  14480.     y0 = floor(y0 + 2*yinc + 0.5)
  14481. end procedure
  14482.  
  14483. global procedure stop_weapons()
  14484. -- stop all active weapons
  14485.     purge_tasks(routine_id("task_phasor"))
  14486.     purge_tasks(routine_id("task_torpedo"))
  14487.     purge_tasks(routine_id("task_pod"))
  14488.     purge_tasks(routine_id("task_Java_phasor"))
  14489.     euphoria_color(YELLOW)
  14490. end procedure
  14491.  
  14492. MYDATA.EX
  14493. 6809
  14494. ----------------------- Simple Customizable Database -----------------------
  14495.  
  14496. -- files to store the database and a backup copy:
  14497. constant DB_NAME   = "mydata.dat",
  14498.      BACK_NAME = "mybackup.dat"
  14499.  
  14500. constant FIELDS = {  -- Have as many fields as you like. The first one is 
  14501.              -- used for look-ups. Start a new database if you
  14502.              -- change or add fields.
  14503. -- example fields:
  14504.     "Surname",
  14505.     "First name and initial",
  14506.     "Phone number"
  14507.     }
  14508.  
  14509. constant FALSE = 0
  14510.  
  14511. -- Assume all field values are strings:
  14512. constant SOME_NUMERIC_FIELDS = FALSE 
  14513.  
  14514. ----------------------------------------------------------------------------
  14515. -- How it works:
  14516. --
  14517. -- The database is just a big Euphoria sequence that is read from
  14518. -- a disk file using get(), updated in memory, then written back
  14519. -- to the file using print().
  14520. --
  14521. -- For small amounts of data (up to a few thousand records) this works fine. 
  14522. -- For very large databases you should use the random access I/O 
  14523. -- functions: seek() and where(), to read/write only a specific portion
  14524. -- of the data each time.
  14525. ---------------------------------------------------------------------------- 
  14526.  
  14527. include get.e
  14528. include sort.e
  14529. include wildcard.e
  14530.  
  14531. constant KEYBOARD = 0,
  14532.      SCREEN   = 1,
  14533.      ERROR    = 2
  14534.  
  14535. constant TRUE = 1
  14536. constant WHITE_SPACE = " \t\n"
  14537. constant FORM_FEED = 12
  14538.  
  14539. type file_number(integer x)
  14540.     return x >= -1
  14541. end type
  14542.  
  14543. type record(sequence s)
  14544.     return length(s) = length(FIELDS)
  14545. end type
  14546.  
  14547. file_number db    -- number of file containing database
  14548.  
  14549. sequence database -- the in-memory database
  14550.  
  14551. type record_number(integer x)
  14552.     return x >= 0 and x <= length(database)
  14553. end type
  14554.  
  14555. procedure error(sequence msg)
  14556. -- fatal error
  14557.     puts(ERROR, '\n' & msg & '\n')
  14558.     abort(1)
  14559. end procedure
  14560.  
  14561. function user_input()
  14562. -- get user input from keyboard
  14563.     object line
  14564.  
  14565.     while TRUE do
  14566.     line = gets(KEYBOARD)
  14567.     if sequence(line) then
  14568.         -- delete any leading whitespace
  14569.         while find(line[1], WHITE_SPACE) do
  14570.         line = line[2..length(line)]
  14571.         if length(line) = 0 then
  14572.             exit
  14573.         end if
  14574.         end while
  14575.         if length(line) > 0 then
  14576.         exit
  14577.         end if
  14578.     end if
  14579.     puts(SCREEN, "\n? ")
  14580.     end while
  14581.     -- delete trailing whitespace
  14582.     while find(line[length(line)], WHITE_SPACE) do
  14583.     line = line[1..length(line)-1] 
  14584.     end while
  14585.     return line
  14586. end function
  14587.  
  14588. procedure show(file_number f, record rec)
  14589.     puts(f, "\n" & rec[1] & '\n')
  14590.     for i = 2 to length(FIELDS) do
  14591.     puts(f, '\t' & rec[i] & '\n')
  14592.     end for
  14593. end procedure
  14594.  
  14595. function lookup(sequence name)
  14596. -- return record numbers matching name
  14597.     sequence matches
  14598.     
  14599.     matches = {}
  14600.     name = upper(name)
  14601.     for i = 1 to length(database) do
  14602.     if equal(name, upper(database[i][1])) then
  14603.         matches &= i
  14604.     end if
  14605.     end for
  14606.     return matches
  14607. end function
  14608.  
  14609. procedure db_add()
  14610. -- add a new record to the database
  14611.     record rec
  14612.     sequence matches
  14613.  
  14614.     rec = repeat(0, length(FIELDS))
  14615.     puts(SCREEN, "\n\t" & FIELDS[1] & ": ")
  14616.     rec[1] = user_input()
  14617.     matches = lookup(rec[1])
  14618.     for i = 1 to length(matches) do
  14619.     show(SCREEN, database[matches[i]])
  14620.     end for
  14621.     for i = 2 to length(FIELDS) do
  14622.     puts(SCREEN, "\n\t" & FIELDS[i] & ": ")
  14623.     rec[i] = user_input()
  14624.     end for
  14625.     puts(SCREEN, '\n')
  14626.     database = append(database, rec)
  14627. end procedure 
  14628.  
  14629. procedure db_delete()
  14630. -- delete a record, given first field 
  14631.     sequence name, answer
  14632.     record_number rec_num
  14633.     sequence matches
  14634.     integer i
  14635.  
  14636.     puts(SCREEN, "\n\t" & FIELDS[1] & ": ")
  14637.     name = user_input()
  14638.     matches = lookup(name)
  14639.     if length(matches) = 0 then
  14640.     puts(SCREEN, "\n\tnot found\n")
  14641.     return
  14642.     end if 
  14643.     i = 1
  14644.     while i <= length(matches) do
  14645.     show(SCREEN, database[matches[i]])
  14646.     puts(SCREEN, "Delete? ")
  14647.     answer = gets(KEYBOARD)
  14648.     if find('y', answer) then
  14649.         rec_num = matches[i]
  14650.         database = database[1..rec_num-1] & 
  14651.                database[rec_num+1..length(database)]
  14652.         exit
  14653.     end if
  14654.     i += 1
  14655.     end while
  14656. end procedure
  14657.  
  14658. procedure db_find()
  14659. -- find all records that match value of first field
  14660.     sequence name, matches
  14661.  
  14662.     puts(SCREEN, "\n\t" & FIELDS[1] & ": ")
  14663.     name = user_input()
  14664.     matches = lookup(name)
  14665.     if length(matches) = 0 then
  14666.     puts(SCREEN, "\n\tnot found\n")
  14667.     end if 
  14668.     for i = 1 to length(matches) do
  14669.     show(SCREEN, database[matches[i]])
  14670.     end for
  14671. end procedure
  14672.  
  14673. procedure db_list(file_number f)
  14674. -- list the entire database to a device
  14675.     sequence sorted_database
  14676.  
  14677.     sorted_database = sort(database)
  14678.     puts(f, '\n')
  14679.     for i = 1 to length(sorted_database) do
  14680.     show(f, sorted_database[i]) 
  14681.     end for
  14682. end procedure
  14683.  
  14684. procedure db_save()
  14685. -- save in-memory database to disk file
  14686.     system("copy " & DB_NAME & " " & BACK_NAME, 2)
  14687.     db = open(DB_NAME, "w")
  14688.     if db = -1 then
  14689.     system("copy " & BACK_NAME & " " & DB_NAME, 2)
  14690.     error("Can't save database")
  14691.     end if
  14692.     
  14693.     if SOME_NUMERIC_FIELDS then
  14694.     print(db, database)  -- very simple: fields can be strings or numbers
  14695.     else
  14696.     -- Save space in the file by using puts() to output strings
  14697.     -- as "ABC". print() outputs strings as {65, 66, 67}.
  14698.     -- This way the database file is more human-readable. 
  14699.     
  14700.     puts(db, "{\n")
  14701.     for i = 1 to length(database) do
  14702.         -- output next record
  14703.         puts(db, '{')
  14704.         for j = 1 to length(FIELDS) do
  14705.         puts(db, "\"" & database[i][j] & "\"")
  14706.         if j != length(FIELDS) then
  14707.             puts(db, ",")
  14708.         end if
  14709.         end for
  14710.         puts(db, "}")
  14711.         if i != length(database) then
  14712.         puts(db, ",")
  14713.         end if
  14714.         puts(db, '\n')
  14715.     end for
  14716.     puts(db, "}\n")
  14717.     end if
  14718.     close(db)
  14719. end procedure
  14720.  
  14721. procedure db_create()
  14722. -- create a new database
  14723.      
  14724.     db = open(DB_NAME, "w")
  14725.     database = {}
  14726.     print(db, database)
  14727.     close(db)
  14728.     db = open(DB_NAME, "r")
  14729.     if db = -1 then
  14730.     error("Couldn't open database")
  14731.     end if    
  14732. end procedure
  14733.  
  14734. procedure db_main()
  14735.     sequence command
  14736.     file_number printer
  14737.  
  14738.     db = open(DB_NAME, "r")
  14739.     if db = -1 then
  14740.     db_create()
  14741.     else
  14742.     database = get(db)
  14743.     if database[1] != GET_SUCCESS then
  14744.         error("Couldn't read database")
  14745.     end if
  14746.     database = database[2]
  14747.     end if
  14748.     close(db)
  14749.  
  14750.     clear_screen()
  14751.     puts(SCREEN, "\t\tSimple Database\n")
  14752.     while TRUE do
  14753.     puts(SCREEN, 
  14754.     "\n(a)dd, (d)elete, (f)ind, (l)ist, (p)rint, (s)ave, (q)uit: ")
  14755.     command = upper(user_input())
  14756.     if 'A' = command[1] then
  14757.         db_add()
  14758.  
  14759.     elsif 'D' = command[1] then
  14760.         db_delete()
  14761.  
  14762.     elsif 'F' = command[1] then
  14763.         db_find()
  14764.  
  14765.     elsif 'Q' = command[1] then
  14766.         exit
  14767.  
  14768.     elsif 'S' = command[1] then
  14769.         db_save()
  14770.         exit
  14771.  
  14772.     elsif 'L' = command[1] then
  14773.         db_list(SCREEN)
  14774.  
  14775.     elsif 'P' = command[1] then
  14776.         printer = open("PRN", "w")
  14777.         if printer = -1 then
  14778.         puts(SCREEN, "Can't open printer device\n")
  14779.         else
  14780.         db_list(printer)
  14781.         puts(printer, FORM_FEED)
  14782.         close(printer)
  14783.         end if
  14784.     else
  14785.         puts(SCREEN, "\nsay what?\n")                   
  14786.     end if 
  14787.     end while
  14788. end procedure
  14789.  
  14790. db_main()
  14791.  
  14792. QUEENS.EX
  14793. 2074
  14794. -- The N Queens Problem:
  14795. -- Place N Queens on an NxN chess board
  14796. -- such that they don't threaten each other.
  14797.  
  14798. constant N = 8 -- try some other sizes
  14799.  
  14800. constant ROW = 1, COLUMN = 2
  14801. constant TRUE = 1, FALSE = 0
  14802.  
  14803. type square(sequence x)
  14804. -- a square on the board
  14805.     return length(x) = 2
  14806. end type
  14807.  
  14808. type row(integer x)
  14809. -- a row on the board
  14810.     return x >= 1 and x <= N
  14811. end type
  14812.  
  14813. function threat(square q1, square q2)
  14814. -- do two queens threaten each other?
  14815.     if q1[COLUMN] = q2[COLUMN] then
  14816.     return TRUE
  14817.     elsif q1[ROW] - q1[COLUMN] = q2[ROW] - q2[COLUMN] then
  14818.     return TRUE
  14819.     elsif q1[ROW] + q1[COLUMN] = q2[ROW] + q2[COLUMN] then
  14820.     return TRUE
  14821.     elsif q1[ROW] = q2[ROW] then
  14822.     return TRUE
  14823.     else
  14824.     return FALSE
  14825.     end if
  14826. end function
  14827.  
  14828. function conflict(square q, sequence queens)
  14829. -- Would square p cause a conflict with other queens on board so far?
  14830.     for i = 1 to length(queens) do
  14831.     if threat(q, queens[i]) then
  14832.         return TRUE
  14833.     end if
  14834.     end for
  14835.     return FALSE
  14836. end function
  14837.  
  14838. integer soln
  14839. soln = 0 -- solution number
  14840.  
  14841. procedure print_board(sequence queens)
  14842. -- print a solution, showing the Queens on the board
  14843.     integer k
  14844.  
  14845.     position(1, 1)
  14846.     printf(1, "Solution #%d\n\n  ", soln)
  14847.     for c = 'a' to 'a' + N - 1 do
  14848.     printf(1, "%2s", c)
  14849.     end for
  14850.     puts(1, "\n")
  14851.     for r = 1 to N do
  14852.     printf(1, "%2d ", r)
  14853.     for c = 1 to N do
  14854.         if find({r,c}, queens) then
  14855.         puts(1, "Q ")
  14856.         else
  14857.         puts(1, ". ")
  14858.         end if
  14859.     end for
  14860.     puts(1, "\n")
  14861.     end for
  14862.     puts(1, "\nPress Enter. (q to quit) ")
  14863.     while TRUE do
  14864.     k = get_key()
  14865.     if k = 'q' then
  14866.         abort(0)
  14867.     elsif k != -1 then
  14868.         exit
  14869.     end if
  14870.     end while
  14871. end procedure
  14872.  
  14873. procedure place_queen(sequence queens)
  14874. -- place queens on a NxN chess board
  14875. -- (recursive procedure)
  14876.     row r -- only need to consider one row for each queen
  14877.  
  14878.     if length(queens) = N then
  14879.     soln += 1
  14880.     print_board(queens)
  14881.     return
  14882.     end if
  14883.     r = length(queens)+1
  14884.     for c = 1 to N do
  14885.     if not conflict({r,c}, queens) then
  14886.         place_queen(append(queens, {r,c}))
  14887.     end if
  14888.     end for
  14889. end procedure
  14890.  
  14891. clear_screen()
  14892. place_queen({})
  14893.  
  14894. SANITY.EX
  14895. 27141
  14896.         ------------------------------------------
  14897.         -- AUTOMATIC SELF-CHECKING SANITY TEST  --
  14898.         -- for Euphoria                         --
  14899.         -- A quick test of most of the features --
  14900.         ------------------------------------------
  14901. -- Usage:
  14902. --        ex sanity
  14903. --       exw sanity.ex
  14904.  
  14905. with type_check
  14906. with trace
  14907. trace(0)
  14908. include get.e
  14909. include graphics.e  -- comment after include is ok
  14910. include sort.e
  14911. include machine.e
  14912. include file.e
  14913. include wildcard.e
  14914. include image.e
  14915. include misc.e
  14916. include dll.e
  14917. include msgbox.e
  14918.  
  14919. integer SLASH
  14920. if platform() = LINUX then
  14921.     SLASH = '/'
  14922. else
  14923.     SLASH = '\\'
  14924. end if
  14925.  
  14926. constant msg = 1 -- place to send messages
  14927. atom t
  14928. t = time()
  14929. object y
  14930.  
  14931. procedure the_end()
  14932.     puts(msg, "Press Enter to continue\n")
  14933.     if atom(gets(0)) then
  14934.     end if
  14935.     if graphics_mode(-1) then
  14936.     end if
  14937.     abort(0)
  14938. end procedure
  14939.  
  14940. procedure make_sound()
  14941. -- test sound() built-in
  14942.     for i = 400 to 4000 by 400 do
  14943.     sound(i)
  14944.     for j = 1 to 100000 do
  14945.     end for
  14946.     sound(0)
  14947.     end for
  14948. end procedure
  14949.  
  14950. without warning
  14951. procedure abort()
  14952. -- force abort with trace back
  14953.     puts(msg, "\ndivide by 0 to get trace back...Press Enter\n")
  14954.     if sequence(gets(0)) then
  14955.     end if
  14956.     ? 1/0
  14957. end procedure
  14958. with warning
  14959.  
  14960. constant epsilon = 1e-10 -- allow for small floating point inaccuracy
  14961.  
  14962. procedure show(object x, object y)
  14963. -- show the mismatched values
  14964.     puts(msg, "\n   ---MISMATCH--- \n   x is ")
  14965.     ? x
  14966.     puts(msg, "   y is ")
  14967.     ? y
  14968.     puts(msg, " y - x is ")
  14969.     ? y - x
  14970.     abort()
  14971. end procedure
  14972.  
  14973. procedure same(object x, object y)
  14974. -- object x must be identical to object y else abort program
  14975.     atom ratio
  14976.  
  14977.     if atom(x) and atom(y) then
  14978.     if x = y then
  14979.         return
  14980.     else
  14981.         if y = 0 then
  14982.         show(x, y)
  14983.         else
  14984.         ratio = x / y
  14985.         if ratio < 1 - epsilon or ratio > 1 + epsilon then
  14986.             show(x, y)
  14987.         end if
  14988.         end if
  14989.     end if
  14990.     elsif length(x) = length(y) then
  14991.     for i = 1 to length(x) do
  14992.         same(x[i], y[i])
  14993.     end for
  14994.     else
  14995.     show(x, y)
  14996.     end if
  14997. end procedure
  14998.  
  14999. integer abs_id
  15000.  
  15001. function built_in()
  15002. -- built-in tests
  15003.     sequence d
  15004.  
  15005.     d = date()
  15006.     if d[1] < 93 or d[2] > 12 or d[3] < 1 or d[4] > 23 or d[5] > 59 or
  15007.     d[6] >59 or d[7] > 7  or d[8] > 366 then
  15008.     abort()
  15009.     end if
  15010.     d = power({-5, -4.5, -1,  0, 1,  2,  3.5, 4, 6},
  15011.           { 3,    2, -1,0.5, 0, 29, -2.5, 5, 8})
  15012.     if d[1] != -125 or d[2] != 20.25 or d[3] != -1 or d[4] != 0 then
  15013.     abort()
  15014.     end if 
  15015.     if d[5] != 1 or d[6] != 536870912 or d[7] <.043 or d[7] > .044 then
  15016.     abort()
  15017.     end if
  15018.     if d[8] != 1024 or d[9] != 1679616 or power(2,3) != 8 then
  15019.     abort()
  15020.     end if
  15021.     same(power(16, 0.5), 4)
  15022.     d = remainder({5, 9, 15, -27}, {3, 4, 5, 6})
  15023.     if d[1] != 2 or d[2] != 1 or d[3] != 0 or d[4] != -3 then
  15024.     abort()
  15025.     end if
  15026.     d = remainder({11.5, -8.8, 3.5, 5.0}, {2, 3.5, -1.5, -100.0})
  15027.     if d[1] != 1.5 or d[2] < -1.81 or d[2] > -1.79 or d[3] != 0.5 or d[4] != 5 then
  15028.     abort()
  15029.     end if
  15030.     same(4, sqrt(16))
  15031.     same(3, length("ABC"))
  15032.     same({1, 1, 1, 1}, repeat(1, 4))
  15033.     if rand(10) > 10 or rand(20) < 1 or not find(rand(5.5), {1,2,3,4,5}) then
  15034.     abort()
  15035.     end if
  15036.     if equal(0,1) or 
  15037.        not equal(-9,-9) or 
  15038.        equal(5,{{{}}}) or 
  15039.        not equal(5,5.0) then
  15040.     abort()
  15041.     end if
  15042.     set_rand(5555)
  15043.     d = rand(repeat(10,20))
  15044.     set_rand(5555)
  15045.     if not equal(d, rand(repeat(10,20))) then
  15046.     abort()
  15047.     end if
  15048.     if time() < 0 then
  15049.     abort()
  15050.     end if
  15051.     if call_func(abs_id, {sin(3.1415)}) > 0.02 then
  15052.     abort()
  15053.     end if
  15054.     if cos(0) < .98 then
  15055.     abort()
  15056.     end if
  15057.     if call_func(abs_id, {tan(3.14/4) - 1}) > .02 then
  15058.     abort()
  15059.     end if
  15060.     if (call_func(abs_id, {tan(arctan(1)) - 1}) > 000.02) then
  15061.     abort()
  15062.     end if
  15063.     if log(2.7) < 0.8 or log(2.7) > 1.2 then
  15064.     abort()
  15065.     end if
  15066.     if floor(-3.3) != -4 then
  15067.     abort()
  15068.     end if
  15069.     if floor(-999/3.000000001) != -333 then
  15070.     abort()
  15071.     end if
  15072.     if floor(9.99/1) != 9 then
  15073.     abort()
  15074.     end if
  15075.     for i = -9 to 2 do
  15076.     if i = 1 then
  15077.         return i
  15078.     end if
  15079.     end for
  15080. end function
  15081.  
  15082. function abs(atom x)
  15083. -- absolute value
  15084.     if x < 0 then
  15085.     return -x
  15086.     else
  15087.     return x
  15088.     end if
  15089. end function
  15090.  
  15091. abs_id = routine_id("abs")
  15092. if abs_id = -1 then
  15093.     abort()
  15094. end if
  15095.  
  15096. procedure sub()
  15097.     y = 200
  15098. end procedure
  15099.  
  15100. procedure overflow()
  15101. -- test overflows from integer into floating point
  15102.     object two29, two30, maxint, prev_i
  15103.     integer two30i, mtwo30i
  15104.     sequence s
  15105.  
  15106.     two30 = 1
  15107.     for i = 1 to 30 do
  15108.     two30 *= 2
  15109.     end for
  15110.     s = {two30, two30+1, two30+2}
  15111.     s += s
  15112.     if compare(s, {two30*2, two30*2+2, two30*2+4}) then
  15113.     abort()
  15114.     end if
  15115.     mtwo30i = -1
  15116.     for i = 1 to 29 do
  15117.     mtwo30i *= 2
  15118.     end for
  15119.     two30i = 1
  15120.     for i = 1 to 29 do
  15121.     two30i *= 2
  15122.     end for
  15123.     if 2 * two30i != -2 * mtwo30i then
  15124.     abort()
  15125.     end if
  15126.     if two30i*2 != two30 then
  15127.     abort()
  15128.     end if
  15129.     two29 = floor(two30 / 2)
  15130.     if two29 + two29 != two30 then
  15131.        abort()
  15132.     end if
  15133.  
  15134.     maxint = floor(two30 - 1)
  15135.     if maxint + 1 != two30 then
  15136.     abort()
  15137.     end if
  15138.  
  15139.     if 2 + maxint != two30 + 1 then
  15140.     abort()
  15141.     end if
  15142.  
  15143.     if (-maxint - 1) * -1 != two30 then
  15144.     abort()
  15145.     end if
  15146.  
  15147.     prev_i = -maxint + 1
  15148.     for i = -maxint to -maxint -5 by -1 do
  15149.     if i != prev_i - 1 then
  15150.         abort()
  15151.     end if
  15152.     prev_i = i
  15153.     end for
  15154.  
  15155.     prev_i = maxint - 5
  15156.     for i = maxint - 3 to maxint + 3 by 2 do
  15157.     if i != prev_i + 2 then
  15158.         abort()
  15159.     end if
  15160.     prev_i = i
  15161.     end for
  15162.  
  15163.     if floor(two30) != two30 then
  15164.     abort()
  15165.     end if
  15166.  
  15167.     if floor(two30 + two30 - 1) != two30 * 2 - 1 then
  15168.     abort()
  15169.     end if
  15170. end procedure
  15171.  
  15172. type natural(integer x)
  15173.     return x >= 0
  15174. end type
  15175.  
  15176. procedure atomic_ops()
  15177. -- test operations on atoms
  15178.     object a, x, z
  15179.     integer n, m
  15180.     natural p
  15181.  
  15182.     if arcsin(.5) <.523 or arcsin(.5) >.524 then
  15183.     abort()
  15184.     end if
  15185.     p = 0
  15186.     p = 0.000
  15187.     p = 4.0/2.0
  15188.     if p != 2.0 then
  15189.     abort()
  15190.     end if    
  15191.     n = 1
  15192.     m = 1
  15193.     if n and m then
  15194.     else
  15195.     abort()  
  15196.     end if
  15197.     if atom(n) or 1/0 then
  15198.     -- short-circuit skips the divide
  15199.     end if
  15200.     if sequence(n) and n[1] then
  15201.     -- short-circuit skips the subscript
  15202.     end if
  15203.     if 1 xor 1 then
  15204.     abort()
  15205.     end if
  15206.     if not ((0 xor 1) and (1 xor 0))then
  15207.     abort()
  15208.     end if
  15209.     if 0 xor 0 then
  15210.     abort()
  15211.     end if
  15212.     x = 100
  15213.     sub() -- y = 200
  15214.     z = 300
  15215.  
  15216.     if x + y != z then
  15217.     abort()
  15218.     end if
  15219.  
  15220.     if x != 100 then
  15221.     abort()
  15222.     end if
  15223.  
  15224.     if 3 * 3 != 9 or
  15225.        3 * 900000000 != 2700000000 or
  15226.        15000 * 32000 != 480000000 or
  15227.        32000 * 15000 != 480000000 or
  15228.        1000 * 13000 != 13000000 or
  15229.        13000 * 1000 != 13000000 then
  15230.     abort()
  15231.     end if
  15232.     while x != 100 do
  15233.     abort()
  15234.     end while
  15235.  
  15236.     if not (z - y = 100) then
  15237.     abort()
  15238.     end if
  15239.  
  15240.     if #FFFFFFFF != 4294967295 then
  15241.     abort()
  15242.     end if
  15243.    
  15244.     p = 20
  15245.     while not (p < 10) do
  15246.     p -= 2       
  15247.     end while
  15248.     if p != 8 then
  15249.     abort()
  15250.     end if
  15251.  
  15252.     if x * 1000.5 != 100050 or x * y != 20000 or x / y != 0.5 then
  15253.     abort()
  15254.     end if
  15255.  
  15256.     if y < x then
  15257.     abort()
  15258.     end if
  15259.  
  15260.     if y <= x then
  15261.     abort()
  15262.     end if
  15263.  
  15264.     if x > y then
  15265.     abort()
  15266.     end if
  15267.  
  15268.     if x >= y then
  15269.     abort()
  15270.     end if
  15271.  
  15272.     if -x != -100 then
  15273.     abort()
  15274.     end if
  15275.  
  15276.     if x = x and y > z then
  15277.     abort()
  15278.     end if
  15279.  
  15280.     x = 0
  15281.  
  15282.     y = {"ten", "one", "two", "three", "four", "five", "six", "seven", "eight",
  15283.      "nine", "ten", "ten"}
  15284.  
  15285.     while x <= 11 do
  15286.     if x = 1 then a = "one"
  15287.     elsif x = 2 then a = "two"
  15288.     elsif x = 3 then a = "three"
  15289.     elsif x = 4 then a = "four"
  15290.     elsif x = 5 then a = "five"
  15291.     elsif x = 6 then a = "six"
  15292.     elsif x = 7 then a = "seven"
  15293.              if 1 + 1 = 2 then
  15294.                  same(a, "seven")
  15295.              elsif 1 + 1 = 3 then
  15296.                  abort()
  15297.              else
  15298.                  abort()
  15299.              end if
  15300.     elsif x = 8 then a = "eight"
  15301.     elsif x = 9 then a = "nine"
  15302.     else a = "ten"
  15303.     end if
  15304.     same(a, y[1+x])
  15305.     x = x + 1
  15306.     end while
  15307.  
  15308.     y = 0
  15309.     for xx = 100 to 0 by -2 do
  15310.     y = y + xx
  15311.     end for
  15312.     same(y, 50 * 51)
  15313.  
  15314.     for xx = 1 to 10 do
  15315.     if xx = 6 then
  15316.         x = 6
  15317.         exit
  15318.     end if
  15319.     y = 1
  15320.     while y < 25 do
  15321.         y = y + 1
  15322.         if y = 18 then
  15323.         exit
  15324.         end if
  15325.     end while
  15326.     same(y, 18)
  15327.     end for
  15328.     y = repeat(-99, 7)
  15329.     for xx = +3 to -3 by -1 do
  15330.     y[xx+4] = xx
  15331.     end for
  15332.     same(y, {-3, -2, -1, 0, +1, +2, +3})
  15333.  
  15334.     y = {1,2,3}
  15335.     for xx = 1.5 to +3.0 by .5 do
  15336.       y[xx] = xx
  15337.     end for
  15338.     same(y, {1.5, 2.5, 3.0})
  15339.     y = {}
  15340.     for xx = -9.0 to -9.5 by -.25 do
  15341.       y = y & xx
  15342.     end for
  15343.     same(y, {-9, -9.25, -9.5})
  15344.     y = {}
  15345.     for i = 800000000 to 900000000 by 800000000 do
  15346.     y = append(y, i)        
  15347.     end for
  15348.     if compare(y, {800000000}) then
  15349.     abort()
  15350.     end if
  15351.     y = 5
  15352.     n = 3
  15353.     a = 2
  15354.     for i = 1 to y by a do
  15355.     n = n - 1
  15356.     y = 155
  15357.     a = 1
  15358.     end for
  15359.     same(n, 0)
  15360. end procedure
  15361.  
  15362. procedure floating_pt()
  15363. -- test floating-point operations
  15364.     sequence x
  15365.     atom final
  15366.  
  15367.     x = {1.5, -3.5, 1e10, -1e20, 0.0, 0.0001}
  15368.     y = repeat(x, 10)
  15369.     if x[1]/x[2] > -0.42 or x[1]/x[2] < -0.43 then
  15370.     abort()
  15371.     end if
  15372.     if find(1e10, x) != 3 then
  15373.     abort()
  15374.     end if
  15375.     for a = -1.0 to sqrt(999) by 2.5 do
  15376.     if a > 20.0 then
  15377.         final = a
  15378.         exit
  15379.     end if
  15380.     end for
  15381.     if final < 20.0 or final > 23 then
  15382.     abort()
  15383.     end if
  15384. end procedure
  15385.  
  15386. function one()
  15387.     return 1
  15388. end function
  15389.  
  15390. function two()
  15391.     return 2.000
  15392. end function
  15393.  
  15394. function sequence_ops()
  15395. -- test operations on sequences
  15396.     object i, w, x, y, z
  15397.     sequence s
  15398.     integer j
  15399.  
  15400.     x = {0, 1, 2, 3, 4, 5}
  15401.     y = {1, 0, 1, 1, 0, 0}
  15402.     
  15403.     if not equal(x xor y, y xor x) then
  15404.     abort()
  15405.     end if
  15406.     if compare({{1,1,0,0,1,1}}, {x} xor {y}) != 0 then
  15407.     abort()
  15408.     end if
  15409.     if compare({{1,1}, {2,3}} xor 
  15410.            {{0,0}, {1,1}}, 
  15411.            {{1,1}, {0,0}}) != 0 then
  15412.     abort()
  15413.     end if
  15414.     x = "Hello "
  15415.     y = "World"
  15416.  
  15417.     if find(0, x = x) then
  15418.     abort()
  15419.     end if
  15420.     if x[two()*two() - two()] != 'e' then
  15421.     abort()
  15422.     end if
  15423.     if x[one()+one()] != x[two()] then
  15424.     abort()
  15425.     end if
  15426.  
  15427.     j = x[1]
  15428.     if j != 'H' then
  15429.     abort()
  15430.     end if
  15431.     s = {3.0}
  15432.     s[1] = 1.0000
  15433.     j = s[1]
  15434.     if j != 1 then
  15435.     abort()
  15436.     end if
  15437.     i = 1
  15438.     if not atom(i) or not integer(i) then 
  15439.     abort()
  15440.     end if
  15441.     if length(y) != 5 then 
  15442.     abort()
  15443.     end if
  15444.     while i <= 5 do
  15445.     x = append(x, y[i])
  15446.     i = i + 1
  15447.     end while
  15448.     i = 1
  15449.     while i <= 3 do
  15450.     x = append(x, '.')
  15451.     x = append(x, '\'')
  15452.     i = i + 1
  15453.     end while
  15454.     same(x, "Hello World.'.'.'")
  15455.     x = {}
  15456.     x = append(x, {20,30,5})
  15457.     same(x, {{20,30,5}})
  15458.     x = repeat(5, 19)
  15459.     x = append(x, 20)
  15460.     x[7] = 9
  15461.     y = {9, 9, {9}}
  15462.     y = prepend(y, 8)
  15463.     y = prepend(y, {9, 9})
  15464.     same(y, {{9, 9}, 8, 9, 9, {9}})
  15465.     y = x
  15466.     z = y * x + x + 1000
  15467.     w = z > 1030 or x = 9
  15468.     same(z, {1030, 1030, 1030, 1030, 1030, 1030, 1090, 1030, 1030, 1030,
  15469.          1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1420})
  15470.     same(w, {0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
  15471.          0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
  15472.     x = {"",""}
  15473.     x[1] &= "Euph"
  15474.     x[2] &= "oria"
  15475.     same(x, {"Euph", "oria"})
  15476.     x = {100, 200, {1, 2, {0, 0, 0}}, 300}
  15477.     x[3][3][3] = 26
  15478.     x[3][3][3] += 0+0
  15479.     x[3][3][3] -= 2
  15480.     x[3][3][2..3] += 1
  15481.     x[3][3][2..3] -= {0,0}
  15482.     x[3][3][3] *= 8
  15483.     x[3][3][3] /= 8
  15484.     x = x * x
  15485.     same(x, {10000, 40000, {1, 4, {0, 1, 625}}, 90000})
  15486.     y = x / {1, 2, 3, 4}
  15487.     same(y, {10000, 20000, {1/3, 4/3, {0, 1/3, 625/3}}, 22500})
  15488.     -- & tests
  15489.  
  15490.     same(2 & {5, 6,7}, {2, 5, 6, 7})
  15491.     same({} & 3, {3})
  15492.     same("ABC" & "DEF" & "GHIJ" & {}, "ABCDEFGHIJ")
  15493.     same('A' & 'B' & 'C', "ABC")
  15494.  
  15495.     -- slice tests
  15496.     x = "ABCDEFGHIJKLMNOP"
  15497.     same(x[1..4], "ABCD")
  15498.     y = x[2..5]
  15499.     same(y, "BCDE")
  15500.     same(x[4..3], {})
  15501.     same(x[4..4], "D")
  15502.     x[3..5] = "000"
  15503.     same(x, "AB000FGHIJKLMNOP")
  15504.     x[6..9] = '8'
  15505.     same(x, "AB0008888JKLMNOP")
  15506.  
  15507.     same(floor({1, 2, -3, 4, -5} / 3), {0, 0, -1, 1, -2})
  15508.     same(and_bits({#0FFFFFFF, #7000, 5}, 
  15509.           {#F0F0F0F0, #4010, 3}),
  15510.           {#00F0F0F0, #4000, 1})
  15511.     same(or_bits({#0FFFFFFF, #7000, 5}, 
  15512.          {#00F0F0F0, #4010, 3}),
  15513.          {#0FFFFFFF, #7010, 7})
  15514.     same(xor_bits({#0FFFFFFF, #7000, 5}, 
  15515.           {#00F0F0F0, #4010, 3}),
  15516.           {#0F0F0F0F, #3010, 6})
  15517.     same(and_bits(not_bits({#0FFFFFFF, #7000, #05}), #0000FFFF), 
  15518.           {#00000000, #00008FFF, #0000FFFA})
  15519.     return y
  15520. end function
  15521.  
  15522.  
  15523. procedure sequence_ops2()
  15524. -- more tests of sequence operations
  15525. object x, y
  15526.  
  15527.     x = "ABCDEFGHIJKLMNOP"
  15528.     if find('D', x) != 4 then
  15529.     abort()
  15530.     end if
  15531.     if match("EFGH", x) != 5 then
  15532.     abort()
  15533.     end if
  15534.     if match({"AB", "CD"}, {0, 1, 3, {}, {"AB", "C"}, "AB", "CD", "EF"}) != 6 then
  15535.     abort()
  15536.     end if
  15537.     if not equal(x,x) then
  15538.     abort()
  15539.     end if
  15540.     if compare({}, {}) != 0 then
  15541.     abort()
  15542.     end if
  15543.     y = repeat(repeat(repeat(99, 5), 5), 5)
  15544.     if y[3][3][3] != 99 then
  15545.     abort()
  15546.     end if
  15547.     if compare(y[4][4][3..5], repeat(99, 3)) != 0 then
  15548.     abort()
  15549.     end if
  15550.     y[3][2][1..4] = 88
  15551.     if compare(y[3][2], {88, 88, 88, 88, 99}) != 0 then
  15552.     abort()
  15553.     end if
  15554. end procedure
  15555.  
  15556. procedure circularity()
  15557. -- test for circular references in internal garbage collector
  15558.     object x, y
  15559.  
  15560.     x = {{"abc", {0, 0, 0}}, "def", 1, 2}
  15561.     x[3] = x
  15562.     x[1..2] = x[2..3]
  15563.     x = append(x, x)
  15564.     x = prepend(x, x)
  15565.     if compare(x, x) != 0 then
  15566.     abort()
  15567.     end if
  15568.     y = "ABCDE"
  15569.     y[2] = repeat(y, 3)
  15570.     if compare(y, y) != 0 then
  15571.     abort()
  15572.     end if
  15573. end procedure
  15574.  
  15575. procedure patterns()
  15576. -- test wildcard routines   
  15577.     if wildcard_file("ABC*DEF.*", "XBCDEF.E") then
  15578.     abort()
  15579.     end if
  15580.     if not wildcard_file("A?B?C?D", "a1b2C3D") then
  15581.     abort()
  15582.     end if
  15583.     if wildcard_match("AAA", "AAa") then
  15584.     abort()
  15585.     end if
  15586.     if not wildcard_match("??Z*Z*", "ABZ123Z123") then
  15587.     abort()
  15588.     end if
  15589. end procedure
  15590.  
  15591. procedure conversions()
  15592. -- test conversion of values to/from string representation   
  15593.     sequence v
  15594.     
  15595.     v = sprintf("values are: %5d, %3d, %4.2f", {1234, -89, 6.22})
  15596.     if compare(v, "values are:  1234, -89, 6.22") != 0 then
  15597.     abort()
  15598.     end if
  15599.     v = value("{1,2,3}")
  15600.     if compare(v, {GET_SUCCESS, {1,2,3}}) != 0 then
  15601.     abort()
  15602.     end if
  15603.     for x = 1 to 100 by 3 do
  15604.     v = value(sprintf("%d", x)) 
  15605.     if compare(v, {GET_SUCCESS, x}) != 0 then
  15606.         abort()
  15607.     end if
  15608.     v = value(sprintf("#%x ", x))
  15609.     if compare(v, {GET_SUCCESS, x}) != 0 then
  15610.         abort()
  15611.     end if
  15612.     end for
  15613. end procedure
  15614.  
  15615. procedure output()
  15616. -- test file output routines
  15617.     integer file_no
  15618.  
  15619.     file_no = open("sanityio.tst", "w")
  15620.     if file_no < 0 then
  15621.     abort() 
  15622.     end if
  15623.     puts(file_no, "-- io test\n")
  15624.     print(file_no, {1,2,3})
  15625.     puts(file_no, '\n')
  15626.     print(file_no, -99)
  15627.     puts(file_no, " {11, {33, {#33}}, 4, 5 } {\t\t}\n")
  15628.     puts(file_no, "{} .999 -.999 1.55e00 {11,   22 , {33, 33}, 4, 5  }\n") 
  15629.     printf(file_no, "%e", 10000)
  15630.     printf(file_no, " %d", -123)
  15631.     printf(file_no, " %5.1f", 5+1/2)
  15632.     printf(file_no, "%50s\n", {"+99 1001 {1,2,3} 1E-4 {1.002e23,-59e-5,"})
  15633.     printf(file_no, "%9e}\t\t-1e-20\t   -.00001e5\n", 59e30)
  15634.     puts(file_no, "\"Rob\" \"ert\" \"Craig\"  ")
  15635.     puts(file_no, "\"\" \"\\n\" \"\\t\\r\"\t")
  15636.     puts(file_no, "\"\\'\\\"\" 'A' '\\n' '\\\"' '\\'' '\\r'\n")
  15637.     printf(file_no, "{#%x, ", 291)
  15638.     puts(file_no, "\"ABC\"} {'A', 'B', '\\n'}")  
  15639.     close(file_no)
  15640. end procedure
  15641.  
  15642. procedure input()
  15643. -- test file input routines
  15644.     integer file_no
  15645.     object line
  15646.     integer char
  15647.  
  15648.     file_no = open("sanityio.tst", "r")
  15649.     if file_no < 0 then
  15650.     abort()
  15651.     end if
  15652.     if seek(file_no, 5) then
  15653.     abort()
  15654.     end if
  15655.     if seek(file_no, -1) then
  15656.     abort()
  15657.     end if
  15658.     if seek(file_no, 0) then
  15659.     abort()
  15660.     end if
  15661.     if where(file_no) != 0 then
  15662.     abort()
  15663.     end if
  15664.     line = gets(file_no)
  15665.     if compare(line, "-- io test\n") != 0 then
  15666.     abort()
  15667.     end if
  15668.     char = getc(file_no)
  15669.     if char != '{' then
  15670.     abort()
  15671.     end if
  15672.     close(file_no)
  15673. end procedure
  15674.  
  15675. without type_check
  15676. integer color
  15677. color = 1
  15678. sequence v
  15679.  
  15680. procedure testgr()
  15681. -- test basic VGA graphics operations
  15682.     sequence x
  15683.     
  15684.     if v[VC_XPIXELS] < 100 or v[VC_YPIXELS] < 100 then
  15685.     abort()
  15686.     end if
  15687.     draw_line(BLUE, {{20, 100}, {600, 100}})
  15688.  
  15689.     for i = 1 to 200 by 5 do
  15690.     pixel(WHITE, {3*i, i})
  15691.     if get_pixel({3*i, i}) != 7 then
  15692.         abort()
  15693.     end if
  15694.     end for
  15695.  
  15696.     polygon(color, 0, {{20,350}, {40, 250}, {80, 400}})
  15697.     ellipse(color+5, 1, {350, 350}, {440,440})
  15698.     color = color + 1
  15699.     x = {}
  15700.     for i = 0 to 63 do
  15701.     x = x & repeat(i, 2)
  15702.     end for
  15703.     for p = 220 to 320 by 4 do
  15704.     display_image({p,p}, repeat(x+color, 2))
  15705.     end for
  15706. end procedure
  15707. with type_check
  15708.  
  15709. constant TRUE = 1/1, FALSE = 0, junk=-TRUE
  15710. if junk != -1 then
  15711.     abort()
  15712. end if
  15713.  
  15714. procedure testget()
  15715. -- test input of Euphoria objects
  15716.     object gd
  15717.     object x, i
  15718.     object results
  15719.  
  15720.     gd = open("sanityio.tst", "r")
  15721.     if gd < 0 or gd > 10 then
  15722.     abort()
  15723.     end if
  15724.     if not sequence(gets(gd)) then
  15725.     abort()
  15726.     end if
  15727.     results = {
  15728.      {0, {1,2,3}},
  15729.      {0, -99},
  15730.      {0, {11, {33, {#33}}, 4, 5}},
  15731.      {0, {}},
  15732.      {0, {}},
  15733.      {0, 0.999},
  15734.      {0, -0.999},
  15735.      {0, 1.55},
  15736.      {0, {11, 22, {33, 33}, 4, 5}},
  15737.      {0, 10000},
  15738.      {0, -123},
  15739.      {0, 5.5},
  15740.      {0, 99},
  15741.      {0, 1001},
  15742.      {0, {1, 2, 3}},
  15743.      {0, 0.0001},
  15744.      {0, {1.002e+23, -0.00059, 5.9e+31}},
  15745.      {0, -1e-20},
  15746.      {0, -1},
  15747.      {0, "Rob"},
  15748.      {0, "ert"},
  15749.      {0, "Craig"},
  15750.      {0, ""},
  15751.      {0, "\n"},
  15752.      {0, "\t\r"},
  15753.      {0, "\'\""},
  15754.      {0, 'A'},
  15755.      {0, '\n'},
  15756.      {0, '\"'},
  15757.      {0, '\''},
  15758.      {0, '\r'},
  15759.      {0, {#123, "ABC"}},
  15760.      {0, {'A', 'B', '\n'}},
  15761.      {-#1, 0}
  15762.     }
  15763.     i = 1
  15764.     while TRUE do
  15765.     x = get(gd)
  15766.     if x[1] = -1 then
  15767.         exit
  15768.     end if
  15769.     same(x, results[i])
  15770.     i = i + 1
  15771.     end while
  15772.     if compare(results[i], {-1, 0}) != 0 then
  15773.     puts(2, "wrong number of get values\n")
  15774.     end if
  15775.     close(gd)
  15776. end procedure
  15777.  
  15778. function fib(integer n)
  15779. -- fibonacci
  15780.     if n < 2 then
  15781.     return n
  15782.     else
  15783.     return fib(n-1) + fib(n-2)
  15784.     end if
  15785. end function
  15786.  
  15787. integer rp
  15788.  
  15789. procedure recursive_proc()
  15790. -- a recursively-called procedure
  15791.     if rp > 0 then
  15792.     rp = rp - 1
  15793.     recursive_proc()
  15794.     end if
  15795. end procedure
  15796.  
  15797. procedure machine_level()
  15798. -- quick test of machine-level routines
  15799.     atom addr, dest, src
  15800.  
  15801.     if 9.99 != float64_to_atom(atom_to_float64(9.99)) then
  15802.     abort()
  15803.     end if
  15804.     if -27 != float32_to_atom(atom_to_float32(-27)) then
  15805.     abort()
  15806.     end if
  15807.     addr = allocate(100)
  15808.     poke4(addr, #12345678)
  15809.     if peek4u(addr) != #12345678 then
  15810.     abort()
  15811.     end if
  15812.     if peek4s(addr) != #12345678 then
  15813.     abort()
  15814.     end if
  15815.     poke(addr, {77, -1, 5.1, -1.1})
  15816.     if compare(peek({addr, 4}), {77, 255, 5, 255}) then
  15817.     abort()
  15818.     end if
  15819.     poke(addr, #C3) -- RET instruction
  15820.     if peek(addr) != #C3 then
  15821.     abort()
  15822.     end if
  15823.     call(addr)
  15824.     free(addr)
  15825.     for x = 0 to +2000000 by 99999 do
  15826.     if bytes_to_int(int_to_bytes(x)) != x then
  15827.         abort()
  15828.     end if
  15829.     end for
  15830.     if bits_to_int({1,0,1,0}) != 5 then
  15831.     abort()
  15832.     end if
  15833.     if not equal(int_to_bits(17,8), {1,0,0,0,1,0,0,0}) then
  15834.     abort()
  15835.     end if
  15836.     -- mem_copy() and mem_set()
  15837.     dest = allocate(20)
  15838.     src = allocate(20)
  15839.     poke(src, {1,2,3,4,5,6,7,8,9})
  15840.     mem_copy(dest, src, 9)
  15841.     if compare(peek({dest, 9}), peek({src,9})) != 0 then
  15842.     abort()
  15843.     end if
  15844.     mem_set(dest+3, 100, 4)
  15845.     if compare(peek({dest, 9}), {1,2,3,100,100,100,100,8,9}) != 0 then
  15846.     abort()
  15847.     end if
  15848. end procedure
  15849.  
  15850. global type sorted(sequence x)
  15851. -- return TRUE if x is in ascending order
  15852.     for i = 1 to length(x)-1 do
  15853.     if compare(x[i], x[i+1]) > 0 then
  15854.         return FALSE
  15855.     end if
  15856.     end for
  15857.     return TRUE
  15858. end type
  15859.  
  15860.  
  15861. procedure win32_tests()
  15862. -- tests that require WIN32 platform (exw sanity.ex)
  15863.     atom lib
  15864.     integer Sleep, Beep
  15865.     
  15866.     if instance() < 0 then
  15867.     abort()
  15868.     end if
  15869.     
  15870.     lib = open_dll("kernel32")
  15871.     if lib = 0 then
  15872.     abort()
  15873.     end if
  15874.     Beep = define_c_func(lib, "Beep", {C_INT, C_INT}, C_INT)
  15875.     if Beep = -1 then
  15876.     abort()
  15877.     end if
  15878.     Sleep = define_c_proc(lib, "Sleep", {C_INT})
  15879.     if Sleep = -1 then
  15880.     abort()
  15881.     end if
  15882.     for i = 1 to 3 do
  15883.     if c_func(Beep, {0, 0}) = 0 then
  15884.         abort()
  15885.     end if
  15886.     t = time()
  15887.     c_proc(Sleep, {1000}) -- 1000 milliseconds
  15888.     if time() - t < .5 then
  15889.         abort()
  15890.     end if
  15891.     end for
  15892. end procedure
  15893.  
  15894. integer last_sum
  15895.  
  15896. function checksum(sequence filename)
  15897. -- Return the simple sum of all the bytes in a file, 
  15898. -- or 0 if file not found
  15899.     integer fn, c
  15900.     
  15901.     fn = open(filename, "rb")
  15902.     last_sum = 0
  15903.     if fn != -1 then
  15904.     while TRUE do
  15905.         c = getc(fn)
  15906.         if c = -1 then
  15907.         exit
  15908.         end if
  15909.         last_sum += c
  15910.     end while
  15911.     close(fn)
  15912.     end if
  15913.     return last_sum
  15914. end function
  15915.  
  15916. constant SUM_EX = 18883540,
  15917.      SUM_EXW = 7968963,
  15918.      SUM_PDEX = 18925198,
  15919.      SUM_PDEXW = 8028603
  15920.      
  15921. object eudir
  15922. sequence edition
  15923. edition = ""
  15924.  
  15925. procedure corrupt(sequence filename)
  15926. -- say that a file is corrupt   
  15927.     sequence full_name
  15928.  
  15929.     full_name = lower(eudir & filename)
  15930.     puts(msg, "\n\n")
  15931.     if length(edition) then
  15932.     puts(msg, lower(eudir) & "ex.exe" & " is the " & 
  15933.          edition & " Edition ex.exe file. \n")
  15934.     end if
  15935.     if last_sum = 0 then
  15936.     puts(msg, full_name & " does not exist. \n")
  15937.     puts(msg, "The install is not correct. ")
  15938.     else
  15939.     printf(msg, "%s seems to be incorrect. \n", {full_name})
  15940.     if    last_sum = SUM_EX then
  15941.         puts(msg, "It's the Complete Edition ex.exe file. ")
  15942.     elsif last_sum = SUM_EXW then
  15943.         puts(msg, "It's the Complete Edition exw.exe file. ")
  15944.     elsif last_sum = SUM_PDEX then
  15945.         puts(msg, "It's the Public Domain Edition ex.exe file. ")
  15946.     elsif last_sum = SUM_PDEXW then
  15947.         puts(msg, "It's the Public Domain Edition exw.exe file. ")
  15948.     else                
  15949.         printf(msg, "Its check-sum (%d) is wrong. \n", last_sum)
  15950.         puts(msg, 
  15951.         "Either it's an old version, or it has been corrupted. \n")
  15952.         puts(msg, 
  15953.         "You can download the latest version of Euphoria from: \n")
  15954.         puts(msg, "    http://www.RapidEuphoria.com/ ")
  15955.     end if
  15956.     end if
  15957.     puts(msg, "\n\n\n")
  15958.     the_end()
  15959. end procedure
  15960.  
  15961. procedure reboot_msg()
  15962.     if platform() = LINUX then
  15963.     puts(msg, "Did you forget to edit your profile and log in again?\n")
  15964.     else    
  15965.     puts(msg, "Did you forget to reboot (restart) your machine?\n")
  15966.     end if
  15967.     puts(msg, "See INSTALL.DOC\n")
  15968.     the_end()
  15969. end procedure
  15970.  
  15971. procedure check_install(integer doit)
  15972. -- see if Euphoria was installed correctly
  15973.     object path
  15974.     integer ex_sum
  15975.     
  15976.     if not doit then
  15977.     puts(1, "skipping checksum - press Enter\n")
  15978.     if getc(0) then
  15979.     end if
  15980.     return
  15981.     end if
  15982.     path = getenv("PATH")
  15983.     eudir = getenv("EUDIR")
  15984.     if atom(path) then
  15985.     puts(msg, "Note: Your PATH variable has not been set.\n")
  15986.     reboot_msg()
  15987.     else
  15988.     if not match("EUPHORIA" & SLASH & "BIN", upper(path)) then
  15989.         puts(msg, "Note: EUPHORIA" & SLASH & "BIN is not on your PATH.\n")
  15990.         reboot_msg()
  15991.     end if
  15992.     end if
  15993.     if atom(eudir) then
  15994.     puts(msg, "Note: Your EUDIR variable has not been set.\n")
  15995.     reboot_msg()
  15996.     else
  15997.     if length(eudir) and eudir[length(eudir)] = '\\' then
  15998.         eudir = eudir[1..length(eudir)-1]
  15999.     end if
  16000.     if platform() = LINUX then
  16001.         eudir &= "/bin/"
  16002.     else    
  16003.         eudir &= "\\BIN\\"
  16004.     end if
  16005.     
  16006.     -- check for corrupted files:
  16007.     ex_sum = checksum(eudir & "ex.exe")
  16008.     if ex_sum = SUM_EX then
  16009.         edition = "Complete"
  16010.         if checksum(eudir & "exw.exe") != SUM_EXW then
  16011.         corrupt("exw.exe")
  16012.         end if
  16013.         if checksum(eudir & "pdex.exe") != SUM_PDEX then
  16014.         corrupt("pdex.exe")
  16015.         end if
  16016.         if checksum(eudir & "pdexw.exe") != SUM_PDEXW then
  16017.         corrupt("pdexw.exe")
  16018.         end if
  16019.     elsif ex_sum = SUM_PDEX then
  16020.         -- Public Domain Edition    
  16021.         edition = "Public Domain"
  16022.         if checksum(eudir & "exw.exe") != SUM_PDEXW then
  16023.         corrupt("exw.exe")
  16024.         end if  
  16025.     else
  16026.         corrupt("ex.exe")
  16027.     end if   
  16028.     end if
  16029. end procedure
  16030.  
  16031. without profile
  16032. without warning
  16033. global procedure sanity()
  16034. -- main program
  16035.     sequence cmd_line, save_colors, s1, s2
  16036.     integer vga, ok
  16037.  
  16038.     check_install(TRUE)
  16039.     if platform() = WIN32 then
  16040.     vga = FALSE
  16041.     ok = message_box("Run the test?", "Euphoria WIN32 Sanity Test", 
  16042.     {MB_OKCANCEL, MB_SYSTEMMODAL})
  16043.     if ok = IDCANCEL then
  16044.         return
  16045.     end if
  16046.     else
  16047.     -- some text mode tests
  16048.     clear_screen()
  16049.     position(1,1)
  16050.     puts(1, "ABC")
  16051.     position(2,1)
  16052.     puts(1, "def")
  16053.     s1 = save_text_image({1,1}, {2,3})
  16054.     display_text_image({10,20}, s1)
  16055.     s2 = save_text_image({10, 20}, {11, 22})
  16056.     if not equal(s1, s2) then
  16057.         abort()
  16058.     end if
  16059.  
  16060.     -- graphics mode and other tests
  16061.     vga = not graphics_mode(18) 
  16062.     v = video_config()
  16063.     clear_screen()
  16064.     position(12, 20)
  16065.     if compare({12, 20}, get_position()) != 0 then
  16066.         abort()
  16067.     end if
  16068.     puts(msg, "Euphoria SANITY TEST ... ")
  16069.     end if
  16070.  
  16071.     if platform() = WIN32 then
  16072.     win32_tests()
  16073.     end if
  16074.  
  16075.     for j = 0 to 8 by 2 do
  16076.     cmd_line = command_line()
  16077.     if length(cmd_line) < 1 or length(cmd_line) > 10 then
  16078.         abort()
  16079.     end if
  16080.     if length(current_dir()) < 2 then
  16081.         abort()
  16082.     end if
  16083.     if length(dir(".")) < 2 then
  16084.         abort()
  16085.     end if
  16086.     if vga then
  16087. --          testgr()
  16088.     end if
  16089.     make_sound()
  16090.     same(built_in(), 1)
  16091.     atomic_ops()
  16092.  
  16093.     overflow()
  16094.     floating_pt()
  16095.     if compare(sequence_ops(), "BCDE") != 0 then
  16096.         puts(msg, "sequence_ops failed\n")
  16097.     end if
  16098.     sequence_ops2()
  16099.     circularity()
  16100.     output()
  16101.     input()
  16102.     testget()
  16103.     conversions()
  16104.     patterns()
  16105.     machine_level()
  16106.     rp = 100
  16107.     recursive_proc()
  16108.     if rp != 0 then
  16109.         puts(msg, "recursive proc failed\n")
  16110.     end if
  16111.     if fib(20) != 6765 then
  16112.         puts(msg, "fib failed\n")
  16113.     end if
  16114.     if not sorted(sort(-500 + rand(repeat(1000, 1000)))) then
  16115.         puts(msg, "standard sort failed\n")
  16116.     end if
  16117.     if not sorted(sort({"robert", "junko", "dave", "ken", "lurdes"})) then
  16118.         puts(msg, "standard general sort failed\n")
  16119.     end if
  16120.     end for
  16121.     if platform() = LINUX then
  16122.     system("rm sanityio.tst", 2)
  16123.     else
  16124.     system("del sanityio.tst", 2)
  16125.     end if  
  16126.     save_colors = {}
  16127.     if platform() = DOS32 then
  16128.     for i = 0 to v[VC_NCOLORS]-1 do
  16129.         save_colors = append(save_colors, palette(i, {0,0,0}))
  16130.     end for
  16131.     for i = 1 to 200 do
  16132.         sound(i*15)
  16133.         all_palette(rand(repeat({63,63,63}, v[VC_NCOLORS])))
  16134.     end for
  16135.     sound(0)
  16136.     all_palette(save_colors)
  16137.     end if
  16138.     if platform() = WIN32 then
  16139.     ok = message_box("PASSED (100%)", "Euphoria WIN32 Sanity Test", MB_OK)
  16140.     else
  16141.     puts(msg, "\nPASSED (100%)\n")
  16142.     the_end()    
  16143.     end if
  16144. end procedure
  16145.  
  16146. integer z
  16147.  
  16148. -- another for-loop test
  16149. z = 0
  16150. for j = 1 to 10 do
  16151.     z = z + j
  16152. end for
  16153. if z != 55 then
  16154.     abort()
  16155. end if
  16156.         
  16157. sanity()
  16158.  
  16159.  
  16160. TREE.EX
  16161. 2845
  16162. -- Count frequencies of words in standard input.
  16163. -- Uses a binary tree to speed lookups and write
  16164. -- an alphabetic listing to standard output.
  16165.  
  16166. -- usage: 
  16167. --        ex tree < file1 
  16168. --
  16169. -- You can direct standard output to a file with '>'
  16170.  
  16171. -- How it Works:
  16172. -- * tree.ex reads in words from a text file and inserts them
  16173. --   alphabetically into a Euphoria sequence that is being used
  16174. --   as a "tree". The tree data structure is created by nesting
  16175. --   sequences inside one another to whatever depth is required.
  16176. --   Looking up a word in a tree is generally faster than searching 
  16177. --   through a linear list, since unless the tree is very lop-sided,
  16178. --   we should have fewer comparisons to make.
  16179.  
  16180. without type_check
  16181.  
  16182. constant EOF = -1
  16183. constant TRUE = 1
  16184.  
  16185. constant STANDARD_IN = 0,
  16186.      STANDARD_OUT = 1,
  16187.      SCREEN = 2
  16188.  
  16189. constant NAME = 1,
  16190.      COUNT = 2,
  16191.      LEFT = 3,
  16192.      RIGHT = 4
  16193.  
  16194. function next_word()
  16195. -- read standard input to get next alphabetic string 
  16196.     integer c
  16197.     sequence word
  16198.  
  16199.     word = ""
  16200.     while TRUE do
  16201.     c = getc(STANDARD_IN)
  16202.     if (c >= 'A' and c <= 'Z') or
  16203.        (c >= 'a' and c <= 'z') then
  16204.         word &= c
  16205.     elsif length(word) > 0 then
  16206.         return word
  16207.     elsif c = EOF then
  16208.         return 0
  16209.     end if
  16210.     end while
  16211. end function
  16212.  
  16213. function insert(sequence node, sequence word)
  16214. -- Insert new word into tree or increment existing word count by 1.
  16215. -- Return modified node.
  16216. -- This is quite fast since internally Euphoria is copying
  16217. -- pointers to subtrees, *not* all the data as it might appear. 
  16218.     integer x
  16219.  
  16220.     if length(node) = 0 then
  16221.     -- couldn't find it - create new node
  16222.     node = {word, 1, {}, {}}
  16223.     else 
  16224.     x = compare(word, node[NAME])
  16225.     if x = 0 then
  16226.         node[COUNT] += 1                       -- found it, increment count 
  16227.     elsif x < 0 then
  16228.         node[LEFT] = insert(node[LEFT], word)  -- insert it on the left
  16229.     else
  16230.         node[RIGHT] = insert(node[RIGHT], word)-- insert it on the right
  16231.     end if
  16232.     end if
  16233.     return node
  16234. end function
  16235.  
  16236. procedure printTree(sequence node)
  16237. -- recursively print tree information
  16238. -- in alphabetical order
  16239.     if length(node) = 0 then
  16240.     return
  16241.     end if
  16242.     printTree(node[LEFT])
  16243.     printf(STANDARD_OUT, "%s:%d\n", {node[NAME], node[COUNT]})
  16244.     printTree(node[RIGHT])
  16245. end procedure
  16246.  
  16247. -- root of the whole tree
  16248. sequence root 
  16249. root = {}
  16250.  
  16251. procedure word_count()
  16252. -- build a binary tree containing words in standard input
  16253.     object word
  16254.  
  16255.     while TRUE do 
  16256.     word = next_word() 
  16257.     if atom(word) then
  16258.         exit
  16259.     end if
  16260.     root = insert(root, word)
  16261.     end while
  16262. end procedure
  16263.  
  16264. puts(SCREEN, "terminate typed input with: control-Z Enter\n")
  16265.  
  16266. atom t
  16267. t = time()         -- Time the table-building process only
  16268. word_count() 
  16269. t = time() -t      -- Stop timer
  16270.  
  16271. printTree(root)
  16272. printf(2, "\n%.2f seconds\n\n", t)
  16273.  
  16274. DSEARCH.EXW
  16275. 3321
  16276. -- search for a .DLL that contains a given routine
  16277. -- usage:  
  16278. --      exw dsearch [routine] 
  16279. --
  16280. -- If you don't supply a string on the command line you will be prompted 
  16281. -- for it. 
  16282.  
  16283.  
  16284. -- Some of the common WIN32 .DLLs. Feel free to add more.
  16285. sequence dll_list
  16286. dll_list = {
  16287.     "kernel32.dll",
  16288.     "user32.dll",
  16289.     "gdi32.dll",
  16290.     "winmm.dll",
  16291.     "comdlg32.dll",
  16292.     "comctl32.dll"
  16293. }
  16294.  
  16295. include file.e
  16296. include dll.e
  16297. include machine.e
  16298.  
  16299. constant KEYB = 0, SCREEN = 1
  16300.  
  16301. constant TRUE = 1, FALSE = 0
  16302.  
  16303. type boolean(integer x)
  16304.     return x = 0 or x = 1
  16305. end type
  16306.  
  16307. type c_routine(integer x)
  16308.     return x >= -1 and x <= 1000
  16309. end type
  16310.  
  16311. sequence cmd, orig_string
  16312.  
  16313. integer scanned, no_open
  16314. scanned = 0
  16315. no_open = 0
  16316.  
  16317. c_routine FreeLibrary, GetProcAddress
  16318.  
  16319. atom string_pointer
  16320. sequence routine_name
  16321.  
  16322. function scan(sequence file_name)
  16323. -- process an eligible file
  16324.     boolean found_in_file
  16325.     atom lib
  16326.     
  16327.     lib = open_dll(file_name)
  16328.     if lib = 0 then
  16329.     no_open += 1
  16330.     puts(SCREEN, file_name & ": Couldn't open.\n")
  16331.     return 0
  16332.     end if
  16333.     printf(SCREEN, "%s: ", {file_name})
  16334.     scanned += 1
  16335.     string_pointer = allocate(length(routine_name)+1)
  16336.     poke(string_pointer, routine_name & 0)
  16337.     found_in_file = FALSE
  16338.     if c_func(GetProcAddress, {lib, string_pointer}) then
  16339.     printf(SCREEN, "\n\n%s was FOUND in %s\n", {routine_name, file_name})
  16340.     found_in_file = TRUE
  16341.     end if
  16342.     free(string_pointer)
  16343.     if not c_func(FreeLibrary, {lib}) then
  16344.     puts(SCREEN, "\nFreeLibrary failed!\n")
  16345.     end if
  16346.     return found_in_file
  16347. end function
  16348.  
  16349. procedure CSetup()
  16350. -- set up C routines that we need:
  16351.     atom kernel32
  16352.     
  16353.     kernel32 = open_dll("kernel32.dll")
  16354.     if kernel32 = 0 then
  16355.     puts(SCREEN, "Can't open kernel32.dll!\n")
  16356.     abort(1)
  16357.     end if
  16358.     FreeLibrary = define_c_func(kernel32, "FreeLibrary", {C_POINTER}, C_INT)
  16359.     if FreeLibrary = -1 then
  16360.     puts(1, "Can't find FreeLibrary\n")
  16361.     abort(1)
  16362.     end if
  16363.     GetProcAddress = define_c_func(kernel32, "GetProcAddress", 
  16364.              {C_POINTER, C_POINTER}, C_INT)
  16365.     if GetProcAddress = -1 then
  16366.     puts(1, "Can't find GetProcAddress\n")
  16367.     abort(1)
  16368.     end if
  16369. end procedure
  16370.  
  16371. function delete_trailing_white(sequence name)
  16372. -- get rid of blanks, tabs, newlines at end of string
  16373.     while length(name) > 0 do
  16374.     if find(name[length(name)], "\n\r\t ") then
  16375.         name = name[1..length(name)-1]
  16376.     else
  16377.         exit
  16378.     end if
  16379.     end while
  16380.     return name
  16381. end function
  16382.  
  16383. CSetup()
  16384.  
  16385. cmd = command_line()   -- exw dsearch [string]
  16386.  
  16387. if length(cmd) >= 3 then
  16388.     orig_string = cmd[3]
  16389. else
  16390.     puts(SCREEN, "C function name:")
  16391.     orig_string = delete_trailing_white(gets(KEYB))
  16392.     puts(SCREEN, '\n')
  16393. end if
  16394.  
  16395. routine_name = orig_string
  16396.  
  16397. procedure locate(sequence name)
  16398.     routine_name = name
  16399.     puts(1, "Looking for " & routine_name & "\n ")
  16400.     for i = 1 to length(dll_list) do
  16401.     if scan(dll_list[i]) then
  16402.         if getc(0) then
  16403.         end if
  16404.         abort(1)
  16405.     end if
  16406.     end for
  16407.     puts(1, '\n')
  16408. end procedure
  16409.  
  16410. if length(routine_name) = 0 then
  16411.     abort(0)
  16412. end if
  16413.  
  16414. locate(orig_string)
  16415. locate(orig_string & "A")
  16416. locate(orig_string & "Ex")
  16417. locate(orig_string & "ExA")
  16418.  
  16419. puts(1, "\nCouldn't find " & orig_string & '\n')
  16420. puts(1, "Press Enter\n")
  16421.  
  16422. if getc(0) then
  16423. end if
  16424.  
  16425. EMAIL.EXW
  16426. 3442
  16427. -- Simple MAPI (Messaging API) Demo Program
  16428.  
  16429. -- Performs MapiLogon, MapiSendMail, MapiLogoff
  16430. -- Constants and structure declarations are from 
  16431. -- the file MAPI.H available from Microsoft
  16432.  
  16433. -- If you have Outlook Express you can make it your
  16434. -- "default Simple MAPI client" on the Tools/Options menu.
  16435.  
  16436. -- MS Exchange Inbox should work too.
  16437.  
  16438. include dll.e
  16439. include machine.e
  16440. include wildcard.e
  16441. include msgbox.e
  16442.  
  16443. without warning
  16444.  
  16445. constant MAPI_TO = 1,
  16446.      MAPI_LOGON_UI = 1,           -- display a logon user interface
  16447.      MAPI_FORCE_DOWNLOAD = #1000, -- force download of new messages 
  16448.                       -- when logging in to MAPI
  16449.      MAPI_USE_DEFAULT = #0040     -- use default profile
  16450.  
  16451. constant Title = "Euphoria E-Mail Demo"
  16452.  
  16453. integer MAPILogon, MAPILogoff, MAPISendMail
  16454. atom mapi_dll, session, error, message, recipient
  16455.  
  16456. mapi_dll = open_dll("mapi32.dll")
  16457. if mapi_dll = 0 then
  16458.     puts(1, "Couldn't find MAPI DLL\n")
  16459.     abort(1)
  16460. end if
  16461.  
  16462. MAPILogon = define_c_func(mapi_dll, "MAPILogon", 
  16463.            {C_LONG, C_POINTER, C_POINTER, C_LONG, C_LONG, C_POINTER}, 
  16464.            C_LONG)
  16465. if MAPILogon = -1 then
  16466.     puts(1, "Couldn't find MAPILogon\n")
  16467.     abort(1)
  16468. end if
  16469.  
  16470. MAPILogoff = define_c_func(mapi_dll, "MAPILogoff",
  16471.         {C_INT, C_INT, C_INT, C_INT},
  16472.         C_LONG)
  16473. if MAPILogoff = -1 then
  16474.     puts(1, "Couldn't find MapiLogoff\n")
  16475.     abort(1)
  16476. end if
  16477.  
  16478. MAPISendMail = define_c_func(mapi_dll, "MAPISendMail",
  16479.         {C_INT, C_INT, C_POINTER, C_INT, C_INT},
  16480.         C_LONG)
  16481. if MAPISendMail = -1 then
  16482.     puts(1, "Couldn't find MapiSendMail\n")
  16483.     abort(1)
  16484. end if
  16485.  
  16486. session = allocate(4)
  16487.  
  16488. integer yn
  16489.  
  16490. yn = message_box(
  16491.       "Would you like to send an e-mail message\nto the U.S. President?",
  16492.       Title, MB_YESNO)
  16493. if yn = IDNO then
  16494.     abort(0)
  16495. end if
  16496.  
  16497. error = c_func(MAPILogon, {0, 0, 0, MAPI_USE_DEFAULT, 0, session})
  16498.  
  16499. if error then
  16500.     error = message_box(sprintf("MAPILogon failed - code %d\n", error),
  16501.                    Title, MB_ICONWARNING)
  16502.     abort(error)
  16503. end if
  16504.  
  16505. session = peek4u(session) 
  16506.  
  16507. -- recipient structure:
  16508. constant RECIPCLASS = 4,
  16509.      NAME = 8,
  16510.      ADDRESS = 12
  16511.  
  16512. recipient = allocate(100)
  16513. mem_set(recipient, 0, 100)
  16514. poke4(recipient+RECIPCLASS, MAPI_TO)
  16515. poke4(recipient+NAME, allocate_string("Bill Clinton"))
  16516. poke4(recipient+ADDRESS, allocate_string("SMTP:president@whitehouse.gov"))
  16517.  
  16518. -- message structure offsets:
  16519. constant SUBJECT = 4,
  16520.      TEXT = 8,
  16521.      RECIPCOUNT = 32,
  16522.      RECIPIENTS = 36
  16523.  
  16524. message = allocate(100) 
  16525. mem_set(message, 0, 100)
  16526. poke4(message+SUBJECT, allocate_string("I'm programming in Euphoria " &
  16527.                 "and you can't stop me!"))
  16528. poke4(message+TEXT, allocate_string(
  16529.               "Hi Bill,\n\n" &
  16530.               "\tEuphoria is a GREAT programming language!\n\n" & 
  16531.               "\tPlease visit http://members.aol.com/FilesEu/\n"))
  16532. poke4(message+RECIPCOUNT, 1)
  16533. poke4(message+RECIPIENTS, recipient)
  16534.  
  16535. error = c_func(MAPISendMail, {session, 0, message, MAPI_LOGON_UI, 0})
  16536. if error then
  16537.     error = message_box(sprintf("MAPISendMail failed, code %d\n", error),
  16538.                Title, MB_ICONWARNING)
  16539.     abort(1)
  16540. end if
  16541.  
  16542. -- MAPILogoff may crash if your system isn't set up right for MAPI
  16543. -- error = c_func(MAPILogoff, {session, 0, 0, 0}) 
  16544. -- if error then
  16545. --  error = message_box(sprintf("MAPILogoff failed, code %d\n", error),
  16546. --                     Title, MB_ICONWARNING)
  16547. -- end if
  16548.  
  16549. error = message_box("Check your OUTBOX (or Sent Mail)",
  16550.            Title, MB_ICONINFORMATION)
  16551.  
  16552. WIN32.DOC
  16553. 1147
  16554.         
  16555.         DEMO Programs for the WIN32 Platform
  16556.         ------------------------------------
  16557.  
  16558.  These are very basic examples of how to call C routines in .DLL's and
  16559.  how to create simple windows. Bigger and nicer Windows demo programs are
  16560.  on the Archive page in the WIN32 section, and on the Recent User Contributions
  16561.  page. Most use David Cuny's Win32Lib package, also on the Euphoria Web site.
  16562.  
  16563.  Run each program using exw.exe.
  16564.  
  16565.  window.exw  - A simple example of making a Window
  16566.  
  16567.  email.exw   - A demo of the MAPI (Messaging API) subsystem of the WIN32 API
  16568.                You may have to set up Outlook Express as your 
  16569.                "default Simple MAPI client" on the Tools/Options menu.
  16570.                
  16571.  winwire.exw - A wire frame spinning E, inside a window (or full-screen if
  16572.                you edit a line in the file)
  16573.  
  16574.  dsearch.exw - A tool for finding out which .DLL contains the C function
  16575.                that you want to call
  16576.                
  16577.  
  16578.  For more information on WIN32 programming in Euphoria, see DOC\PLATFORM.DOC
  16579.  
  16580.  To make GUI programs in Euphoria, download David Cuny's excellent Win32Lib
  16581.  package.
  16582.  
  16583. WINDOW.EXW
  16584. 7490
  16585. -- A Standard Windows Window
  16586.  
  16587. include misc.e
  16588. include machine.e
  16589. include dll.e
  16590.  
  16591. constant cbSize = 0,
  16592.      style  = 4,
  16593.      lpfnWndProc = 8,
  16594.      cbClsExtra = 12,
  16595.      cbWndExtra = 16,
  16596.      hInstance  = 20,
  16597.      hIcon      = 24,
  16598.      hCursor    = 28,
  16599.      hbrBackground = 32,
  16600.      lpszMenuName  = 36,
  16601.      lpszClassName = 40,
  16602.      hIconSm = 44,
  16603.      SIZE_OF_WNDCLASS = 48
  16604.  
  16605. constant SIZE_OF_MESSAGE = 40
  16606.  
  16607. constant CS_HREDRAW = 2,
  16608.      CS_VREDRAW = 1
  16609.  
  16610. constant SW_SHOWNORMAL = 1
  16611.  
  16612. constant WM_CREATE = #01,
  16613.      WM_PAINT  = #0F,
  16614.      WM_DESTROY= #02
  16615.  
  16616. constant SND_FILENAME = #00020000,
  16617.      SND_ASYNC    = #00000001
  16618.      
  16619. constant DT_SINGLELINE = #0020,
  16620.      DT_CENTER     = #0001,
  16621.      DT_VCENTER    = #0004
  16622.      
  16623. function or_all(sequence s)
  16624. -- or together all elements of a sequence
  16625.     atom result
  16626.     
  16627.     result = 0
  16628.     for i = 1 to length(s) do
  16629.     result = or_bits(result, s[i])
  16630.     end for
  16631.     return result
  16632. end function
  16633.  
  16634. constant WS_OVERLAPPED  = #00000000,
  16635.      WS_CAPTION     = #00C00000,
  16636.      WS_SYSMENU     = #00080000,
  16637.      WS_THICKFRAME  = #00040000,
  16638.      WS_MINIMIZEBOX = #00020000,
  16639.      WS_MAXIMIZEBOX = #00010000 
  16640.  
  16641. constant IDC_ARROW = 32512,
  16642.      WHITE_BRUSH = 0,
  16643.      CW_USEDEFAULT = #80000000,
  16644.      WS_OVERLAPPEDWINDOW = or_all({WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU,
  16645.                        WS_THICKFRAME, WS_MINIMIZEBOX, 
  16646.                        WS_MAXIMIZEBOX})
  16647.  
  16648.      
  16649. integer LoadIcon, LoadCursor, GetStockObject, RegisterClassEx,
  16650.     CreateWindow, ShowWindow, UpdateWindow, GetMessage,
  16651.     TranslateMessage, DispatchMessage, PlaySound, BeginPaint,
  16652.     GetClientRect, DrawText, EndPaint, PostQuitMessage, DefWindowProc
  16653.  
  16654. procedure not_found(sequence name)
  16655.     puts(1, "Couldn't find " & name & '\n')
  16656.     abort(1)
  16657. end procedure
  16658.  
  16659. function link_c_func(atom dll, sequence name, sequence args, atom result)
  16660. -- dynamically link a C routine as a Euphoria function
  16661.     integer handle
  16662.  
  16663.     handle = define_c_func(dll, name, args, result)
  16664.     if handle = -1 then
  16665.     not_found(name)
  16666.     else
  16667.     return handle
  16668.     end if
  16669. end function
  16670.  
  16671. function link_c_proc(atom dll, sequence name, sequence args)
  16672. -- dynamically link a C routine as a Euphoria function
  16673.     integer handle
  16674.  
  16675.     handle = define_c_proc(dll, name, args)
  16676.     if handle = -1 then
  16677.     not_found(name)
  16678.     else
  16679.     return handle
  16680.     end if
  16681. end function
  16682.  
  16683. procedure link_dll_routines()
  16684. -- get handles to all dll routines that we need
  16685.     atom user32, gdi32, winmm
  16686.     
  16687.     user32 = open_dll("user32.dll")
  16688.     if user32 = NULL then
  16689.     not_found("user32.dll")
  16690.     end if
  16691.     gdi32 = open_dll("gdi32.dll")
  16692.     if gdi32 = NULL then
  16693.     not_found("gdi32.dll")
  16694.     end if
  16695.     winmm = open_dll("winmm.dll")
  16696.     if winmm = NULL then
  16697.     not_found("winmm.dll")
  16698.     end if
  16699.     
  16700.     LoadIcon = link_c_func(user32, "LoadIconA", {C_POINTER, C_INT}, C_INT)
  16701.     LoadCursor = link_c_func(user32, "LoadCursorA", {C_POINTER, C_INT}, C_INT)
  16702.     GetStockObject = link_c_func(gdi32, "GetStockObject", {C_INT}, C_INT)
  16703.     RegisterClassEx = link_c_func(user32, "RegisterClassExA", {C_POINTER}, C_INT)
  16704.     CreateWindow = link_c_func(user32, "CreateWindowExA", 
  16705.      {C_INT, C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT},
  16706.       C_INT)
  16707.     ShowWindow = link_c_proc(user32, "ShowWindow", {C_INT, C_INT})
  16708.     UpdateWindow = link_c_proc(user32, "UpdateWindow", {C_INT})
  16709.     GetMessage = link_c_func(user32, "GetMessageA", 
  16710.                  {C_INT, C_INT, C_INT, C_INT}, C_INT)
  16711.     TranslateMessage = link_c_proc(user32, "TranslateMessage", {C_INT})
  16712.     DispatchMessage = link_c_proc(user32, "DispatchMessageA", {C_INT})
  16713.     PlaySound = link_c_proc(winmm, "PlaySound", {C_INT, C_INT, C_INT})
  16714.     BeginPaint = link_c_func(user32, "BeginPaint", {C_INT, C_POINTER}, C_INT)
  16715.     GetClientRect = link_c_proc(user32, "GetClientRect", {C_INT, C_POINTER})
  16716.     DrawText = link_c_proc(user32, "DrawTextA", 
  16717.                {C_INT, C_INT, C_INT, C_INT, C_INT})
  16718.     EndPaint = link_c_proc(user32, "EndPaint", {C_INT, C_INT})
  16719.     PostQuitMessage = link_c_proc(user32, "PostQuitMessage", {C_INT})
  16720.     DefWindowProc = link_c_func(user32, "DefWindowProcA", 
  16721.                 {C_INT, C_INT, C_INT, C_INT}, C_INT)
  16722. end procedure
  16723.  
  16724. link_dll_routines()
  16725.  
  16726. atom wav_file, Euphoria
  16727. wav_file = allocate_string("\\Windows\\Media\\The Microsoft Sound.wav")
  16728. Euphoria = allocate_string("A Plain Vanilla Window using Euphoria!")
  16729.  
  16730. global function WndProc(atom hwnd, atom iMsg, atom wParam, atom lParam)
  16731. -- callback routine to handle Window class
  16732.     atom hdc
  16733.     atom ps
  16734.     atom rect
  16735.     
  16736.     ps = allocate(64)
  16737.     rect = allocate(16) 
  16738.     if iMsg = WM_CREATE then
  16739.     c_proc(PlaySound, {wav_file,
  16740.                NULL,
  16741.                or_bits(SND_FILENAME, SND_ASYNC)})
  16742.     return 0
  16743.     
  16744.     elsif iMsg = WM_PAINT then
  16745.     hdc = c_func(BeginPaint, {hwnd, ps})
  16746.     c_proc(GetClientRect, {hwnd, rect})
  16747.     c_proc(DrawText, {hdc, Euphoria, -1, rect, 
  16748.               or_all({DT_SINGLELINE, DT_CENTER, DT_VCENTER})})
  16749.     c_proc(EndPaint, {hwnd, ps})
  16750.     return 0
  16751.     
  16752.     elsif iMsg = WM_DESTROY then
  16753.     c_proc(PostQuitMessage, {0})
  16754.     return 0
  16755.     
  16756.     end if
  16757.     
  16758.     return c_func(DefWindowProc, {hwnd, iMsg, wParam, lParam})
  16759. end function
  16760.  
  16761. atom my_title
  16762. my_title = allocate_string("Euphoria for WIN32")
  16763.  
  16764. procedure WinMain()
  16765. -- main routine 
  16766.     atom szAppName
  16767.     atom hwnd
  16768.     atom msg
  16769.     atom wndclass
  16770.     atom WndProcAddress
  16771.     atom class
  16772.     integer id
  16773.     atom icon_handle
  16774.  
  16775.     wndclass = allocate(SIZE_OF_WNDCLASS)
  16776.     msg = allocate(SIZE_OF_MESSAGE)
  16777.     szAppName = allocate_string("HelloWin")
  16778.  
  16779.     id = routine_id("WndProc")
  16780.     if id = -1 then
  16781.     puts(1, "routine_id failed!\n")
  16782.     abort(1)
  16783.     end if
  16784.     WndProcAddress = call_back(id) -- get 32-bit address for callback
  16785.     
  16786.     poke4(wndclass + cbSize, SIZE_OF_WNDCLASS)
  16787.     poke4(wndclass + style, or_bits(CS_HREDRAW, CS_VREDRAW))
  16788.     poke4(wndclass + lpfnWndProc, WndProcAddress)
  16789.     poke4(wndclass + cbClsExtra, 0)
  16790.     poke4(wndclass + cbWndExtra, 0)
  16791.     poke4(wndclass + hInstance, 0) --hInstance
  16792.  
  16793.     icon_handle = c_func(LoadIcon, {instance(), allocate_string("exw")})
  16794.     poke4(wndclass + hIcon, icon_handle)
  16795.     poke4(wndclass + hIconSm, icon_handle)
  16796.     
  16797.     poke4(wndclass + hCursor, c_func(LoadCursor, {NULL, IDC_ARROW}))
  16798.     poke4(wndclass + hbrBackground, c_func(GetStockObject, {WHITE_BRUSH}))
  16799.     poke4(wndclass + lpszMenuName, NULL)
  16800.     poke4(wndclass + lpszClassName, szAppName)
  16801.  
  16802.     class = c_func(RegisterClassEx, {wndclass})
  16803.     if class = 0 then
  16804.     puts(1, "Couldn't register class\n")
  16805.     abort(1)
  16806.     end if
  16807.     hwnd = c_func(CreateWindow, {
  16808.             0,                       -- extended style
  16809.             szAppName,               -- window class name
  16810.             my_title,                -- window caption
  16811.             WS_OVERLAPPEDWINDOW,     -- window style
  16812.             CW_USEDEFAULT,           -- initial x position
  16813.             CW_USEDEFAULT,           -- initial y position
  16814.             CW_USEDEFAULT,           -- initial x size
  16815.             CW_USEDEFAULT,           -- initial y size
  16816.             NULL,                    -- parent window handle
  16817.             NULL,                    -- window menu handle
  16818.             0 ,                 --hInstance // program instance handle
  16819.             NULL})              -- creation parameters
  16820.     if hwnd = 0 then
  16821.     puts(1, "Couldn't CreateWindow\n")
  16822.     abort(1)
  16823.     end if
  16824.     c_proc(ShowWindow, {hwnd, SW_SHOWNORMAL})
  16825.     c_proc(UpdateWindow, {hwnd})
  16826.  
  16827.     while c_func(GetMessage, {msg, NULL, 0, 0}) do
  16828.     c_proc(TranslateMessage, {msg})
  16829.     c_proc(DispatchMessage, {msg})
  16830.     end while
  16831. end procedure
  16832.  
  16833. WinMain()
  16834.  
  16835. WINWIRE.EXW
  16836. 18703
  16837.         ----------------------------
  16838.         -- 3-D Wire Frame Picture --
  16839.         --  * * WIN32 Version * * --
  16840.         ----------------------------
  16841. -- Run in a window or in full screen.
  16842.  
  16843. -- In a window, just close the window to stop it.
  16844.  
  16845. -- When running in Full Screen, press any key to stop.
  16846. -- Make a full-screen DOS window to clear up your screen.
  16847.  
  16848. constant FULL_SCREEN = 0  -- 1 for full screen display
  16849.  
  16850.  
  16851. without type_check
  16852. include dll.e
  16853. include machine.e
  16854. include wildcard.e
  16855.  
  16856. without warning
  16857.  
  16858. constant X = 1, Y = 2, Z = 3
  16859.  
  16860. global constant BLACK = 0,
  16861.      BLUE  = 1,
  16862.      GREEN = 2,
  16863.      CYAN =  3,
  16864.      RED   = 4,
  16865.      MAGENTA = 5,
  16866.      BROWN = 6,
  16867.      WHITE = 7,
  16868.      GRAY  = 8,
  16869.      BRIGHT_BLUE = 9,
  16870.      BRIGHT_GREEN = 10,
  16871.      BRIGHT_CYAN = 11,
  16872.      BRIGHT_RED = 12,
  16873.      BRIGHT_MAGENTA = 13,
  16874.      YELLOW = 14,
  16875.      BRIGHT_WHITE = 15
  16876.  
  16877. global constant VC_COLOR = 1,
  16878.      VC_MODE  = 2,
  16879.      VC_LINES = 3,
  16880.      VC_COLUMNS = 4,
  16881.      VC_XPIXELS = 5,
  16882.      VC_YPIXELS = 6,
  16883.      VC_NCOLORS = 7,
  16884.      VC_PAGES = 8
  16885.  
  16886. constant BLACK_PEN = 7,
  16887.      WHITE_PEN = 6
  16888.  
  16889. constant PS_SOLID = 0
  16890.  
  16891. sequence vc -- video configuration
  16892.  
  16893. integer CreateDC, GetDC, MoveToEx, LineTo, CreatePen, SelectObject
  16894. integer GetStockObject
  16895. atom black_pen, white_pen, red_pen, green_pen, blue_pen
  16896. atom gdi_dll, user_dll, hdc
  16897. integer axis
  16898. atom sin_angle, cos_angle
  16899.  
  16900. integer LoadIcon, LoadCursor, RegisterClassEx,
  16901.     CreateWindow, ShowWindow, UpdateWindow, GetMessage,
  16902.     TranslateMessage, DispatchMessage, PlaySound, BeginPaint,
  16903.     GetClientRect, DrawText, EndPaint, PostQuitMessage, DefWindowProc,
  16904.     SetTimer, KillTimer, ReleaseDC
  16905.  
  16906. type point(sequence x)
  16907.     return length(x) = 3
  16908. end type
  16909.  
  16910. type matrix(sequence x)
  16911.     return length(x) = 4 and sequence(x[1])
  16912. end type
  16913.  
  16914. type vector(sequence x)
  16915.     return length(x) = 4 and atom(x[1])
  16916. end type
  16917.  
  16918.  
  16919. function product(sequence factor)
  16920. -- matrix multiply a number of 4-vectors/4x4 matrices
  16921. -- only the first one could be a vector
  16922.     sequence a, c
  16923.     matrix b
  16924.  
  16925.     a = factor[1]
  16926.     for f = 2 to length(factor) do
  16927.     b = factor[f]
  16928.     if atom(a[1]) then
  16929.         -- a is a vector
  16930.         c = repeat(0, 4)
  16931.         for j = 1 to 4 do
  16932.         c[j] = a[1] * b[1][j] +
  16933.                a[2] * b[2][j] +
  16934.                a[3] * b[3][j] +
  16935.                a[4] * b[4][j]
  16936.         end for
  16937.     else
  16938.         -- a is a matrix
  16939.         c = repeat(repeat(0, 4), 4)
  16940.         for i = 1 to 4 do
  16941.         for j = 1 to 4 do
  16942.             for k = 1 to 4 do
  16943.             c[i][j] += a[i][k] * b[k][j]
  16944.             end for
  16945.         end for
  16946.         end for
  16947.     end if
  16948.     a = c
  16949.     end for
  16950.     return c
  16951. end function
  16952.  
  16953. procedure not_found(sequence name)
  16954.     puts(1, "Couldn't find " & name & '\n')
  16955.     abort(1)
  16956. end procedure
  16957.  
  16958. function link_c_func(atom dll, sequence name, sequence args, atom result)
  16959. -- dynamically link a C routine as a Euphoria function
  16960.     integer handle
  16961.  
  16962.     handle = define_c_func(dll, name, args, result)
  16963.     if handle = -1 then
  16964.     not_found(name)
  16965.     else
  16966.     return handle
  16967.     end if
  16968. end function
  16969.  
  16970. function link_c_proc(atom dll, sequence name, sequence args)
  16971. -- dynamically link a C routine as a Euphoria procedure
  16972.     integer handle
  16973.  
  16974.     handle = define_c_proc(dll, name, args)
  16975.     if handle = -1 then
  16976.     not_found(name)
  16977.     else
  16978.     return handle
  16979.     end if
  16980. end function
  16981.  
  16982. procedure link_dll_routines()
  16983. -- get handles to all dll routines that we need
  16984.     atom user32, gdi32, winmm
  16985.     
  16986.     -- open the .DLL files
  16987.     user32 = open_dll("user32.dll")
  16988.     if user32 = NULL then
  16989.     not_found("user32.dll")
  16990.     end if
  16991.     
  16992.     gdi32 = open_dll("gdi32.dll")
  16993.     if gdi32 = NULL then
  16994.     not_found("gdi32.dll")
  16995.     end if
  16996.     
  16997.     winmm = open_dll("winmm.dll")
  16998.     if winmm = NULL then
  16999.     not_found("winmm.dll")
  17000.     end if
  17001.     
  17002.     -- link the C routines
  17003.     LoadIcon = link_c_func(user32, "LoadIconA", {C_POINTER, C_INT}, C_INT)
  17004.     LoadCursor = link_c_func(user32, "LoadCursorA", {C_POINTER, C_INT}, C_INT)
  17005.     GetStockObject = link_c_func(gdi32, "GetStockObject", {C_INT}, C_INT)
  17006.     RegisterClassEx = link_c_func(user32, "RegisterClassExA", {C_POINTER}, C_INT)
  17007.     CreateWindow = link_c_func(user32, "CreateWindowExA", 
  17008.     {C_INT, C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT},
  17009.      C_INT)
  17010.     ShowWindow = link_c_proc(user32, "ShowWindow", {C_INT, C_INT})
  17011.     UpdateWindow = link_c_proc(user32, "UpdateWindow", {C_INT})
  17012.     GetMessage = link_c_func(user32, "GetMessageA", 
  17013.           {C_INT, C_INT, C_INT, C_INT}, C_INT)
  17014.     TranslateMessage = link_c_proc(user32, "TranslateMessage", {C_INT})
  17015.     DispatchMessage = link_c_proc(user32, "DispatchMessageA", {C_INT})
  17016.     PlaySound = link_c_proc(winmm, "PlaySound", {C_INT, C_INT, C_INT})
  17017.     BeginPaint = link_c_func(user32, "BeginPaint", {C_INT, C_INT}, C_INT)
  17018.     GetClientRect = link_c_proc(user32, "GetClientRect", {C_INT, C_INT})
  17019.     DrawText = link_c_proc(user32, "DrawTextA", 
  17020.            {C_INT, C_INT, C_INT, C_INT, C_INT})
  17021.     EndPaint = link_c_proc(user32, "EndPaint", {C_INT, C_INT})
  17022.     PostQuitMessage = link_c_proc(user32, "PostQuitMessage", {C_INT})
  17023.     DefWindowProc = link_c_func(user32, "DefWindowProcA", 
  17024.       {C_INT, C_INT, C_INT, C_INT}, C_INT)
  17025.     SetTimer = link_c_proc(user32, "SetTimer", {C_INT, C_INT, C_INT, C_INT})
  17026.     KillTimer = link_c_proc(user32, "KillTimer", {C_INT, C_INT})
  17027.     GetDC = link_c_func(user32, "GetDC", {C_INT}, C_INT)
  17028.     ReleaseDC = link_c_proc(user32, "ReleaseDC", {C_INT, C_INT})
  17029.     CreateDC = link_c_func(gdi32, "CreateDCA", 
  17030.               {C_POINTER, C_POINTER, C_POINTER, C_POINTER},
  17031.               C_LONG)
  17032.  
  17033.     MoveToEx = link_c_func(gdi32, "MoveToEx", 
  17034.               {C_LONG, C_LONG, C_LONG, C_POINTER}, C_LONG)
  17035.  
  17036.     LineTo = link_c_func(gdi32, "LineTo", {C_LONG, C_LONG, C_LONG},
  17037.              C_LONG)
  17038.  
  17039.     SelectObject = link_c_func(gdi32, "SelectObject",
  17040.                    {C_LONG, C_LONG}, C_ULONG)
  17041.  
  17042.     CreatePen = link_c_func(gdi32, "CreatePen",
  17043.                    {C_LONG, C_LONG, C_LONG}, C_LONG)
  17044.  
  17045.     GetStockObject = link_c_func(gdi32, "GetStockObject", {C_LONG}, C_LONG)
  17046. end procedure
  17047.  
  17048. link_dll_routines()
  17049.  
  17050. procedure draw_line(integer color, sequence coords)
  17051. -- WIN32 line drawing routine
  17052.     atom ok
  17053.     
  17054.     if color = WHITE then
  17055.     ok = c_func(SelectObject, {hdc, white_pen})
  17056.     elsif color = RED or color = BRIGHT_RED then
  17057.     ok = c_func(SelectObject, {hdc, red_pen})
  17058.     elsif color = GREEN or color = BRIGHT_GREEN then
  17059.     ok = c_func(SelectObject, {hdc, green_pen})
  17060.     elsif color = BLUE or color = BRIGHT_BLUE then
  17061.     ok = c_func(SelectObject, {hdc, blue_pen})
  17062.     else
  17063.     ok = c_func(SelectObject, {hdc, black_pen})
  17064.     end if
  17065.     
  17066.     ok = c_func(MoveToEx, {hdc, coords[1][1], coords[1][2], NULL})
  17067.     if not ok then
  17068.     puts(1, "MoveToEx failed!\n")
  17069.     end if
  17070.     
  17071.     ok = c_func(LineTo, {hdc, coords[2][1], coords[2][2]})
  17072.     if not ok then
  17073.     puts(1, "LineTo failed!\n")
  17074.     end if
  17075. end procedure
  17076.  
  17077. procedure display(sequence old_coords, sequence coords)
  17078. -- erase the old lines, draw the new ones
  17079.     for i = 1 to length(old_coords) do
  17080.     draw_line(WHITE, old_coords[i][1..2])
  17081.     end for
  17082.     for i = 1 to length(coords) do
  17083.     draw_line(coords[i][3], coords[i][1..2])
  17084.     end for
  17085. end procedure
  17086.  
  17087. function view(point view_point)
  17088. -- compute initial view
  17089.     matrix t1, t2, t3, t4, n
  17090.     atom cos_theta, sin_theta, hyp, a_b
  17091.  
  17092.     -- change origin
  17093.     t1 = {{1, 0, 0, 0},
  17094.       {0, 1, 0, 0},
  17095.       {0, 0, 1, 0},
  17096.       -view_point & 1}
  17097.  
  17098.     -- get left-handed coordinate system
  17099.     t2 = {{-1, 0,  0, 0},
  17100.       { 0, 0, -1, 0},
  17101.       { 0, 1,  0, 0},
  17102.       { 0, 0,  0, 1}}
  17103.  
  17104.     -- rotate so Ze points properly
  17105.     hyp = sqrt(view_point[1] * view_point[1] + view_point[2] * view_point[2])
  17106.     sin_theta = view_point[1] / hyp
  17107.     cos_theta = view_point[2] / hyp
  17108.     t3 = {{cos_theta, 0, sin_theta, 0},
  17109.       {        0, 1,         0, 0},
  17110.       {-sin_theta,0, cos_theta, 0},
  17111.       {        0, 0,         0, 1}}
  17112.  
  17113.     -- rotate so Ze points at the origin (0, 0, 0)
  17114.     t4 = {{1, 0, 0, 0},
  17115.       {0, cos_theta, -sin_theta, 0},
  17116.       {0, sin_theta, cos_theta, 0},
  17117.       {0, 0, 0, 1}}
  17118.  
  17119.     a_b = 2
  17120.  
  17121.     n = {{a_b, 0, 0, 0},
  17122.      {0, a_b, 0, 0},
  17123.      {0, 0, 1, 0},
  17124.      {0, 0, 0, 1}}
  17125.  
  17126.     return product({t1, t2, t3, t4, n})
  17127. end function
  17128.  
  17129. function new_coords(sequence overall, sequence shape)
  17130. -- compute the screen coordinates from the 3-D coordinates
  17131.     sequence screen_coords, final
  17132.     point p
  17133.     atom x2, y2
  17134.  
  17135.     x2 = vc[VC_XPIXELS]/2
  17136.     y2 = vc[VC_YPIXELS]/2
  17137.     screen_coords = repeat({0, 0, 0}, length(shape))
  17138.     for i = 1 to length(shape) do
  17139.     for j = 1 to 2  do
  17140.         p = shape[i][j]
  17141.         final = product({p & 1, overall})
  17142.         screen_coords[i][j] = {x2*(final[X]/final[Z]+1),
  17143.                    y2*(final[Y]/final[Z]+1)}
  17144.     end for
  17145.     screen_coords[i][3] = shape[i][3]
  17146.     end for
  17147.     return screen_coords
  17148. end function
  17149.  
  17150. function x_rotate(point p)
  17151. -- compute x rotation of a point
  17152.     return {p[X],
  17153.         p[Y] * cos_angle + p[Z] * sin_angle,
  17154.         p[Z] * cos_angle - p[Y] * sin_angle}
  17155. end function
  17156.  
  17157. function y_rotate(point p)
  17158. -- compute y rotation of a point
  17159.     return {p[X] * cos_angle - p[Z] * sin_angle,
  17160.         p[Y],
  17161.         p[X] * sin_angle + p[Z] * cos_angle}
  17162. end function
  17163.  
  17164. function z_rotate(point p)
  17165. -- compute z rotation matrix
  17166.     return {p[X] * cos_angle + p[Y] * sin_angle,
  17167.         p[Y] * cos_angle - p[X] * sin_angle,
  17168.         p[Z]}
  17169. end function
  17170.  
  17171. function compute_rotate(integer axis, sequence shape)
  17172. -- rotate a shape
  17173.     for i = 1 to length(shape) do
  17174.     for j = 1 to 2 do
  17175.         if axis = X then
  17176.         shape[i][j] = x_rotate(shape[i][j])
  17177.         elsif axis = Y then
  17178.         shape[i][j] = y_rotate(shape[i][j])
  17179.         else
  17180.         shape[i][j] = z_rotate(shape[i][j])
  17181.         end if
  17182.     end for
  17183.     end for
  17184.     return shape
  17185. end function
  17186.  
  17187. -- lines for a block E
  17188. constant E = {
  17189. {{.2, 1.1, 2}, {.2, -.5, 2}, BLUE},
  17190. {{.2, -.5, 2}, {.2, -.5, -2}, YELLOW},
  17191. {{.2, -.5, -2}, {.2, 1.1, -2}, GREEN},
  17192. {{.2, 1.1, -2}, {.2, 1.2, -1.6}, BRIGHT_RED},
  17193. {{.2, 1.2, -1.6}, {.2, 1, -1.8}, BRIGHT_RED},
  17194. {{.2, 1, -1.8}, {.2, 0, -1.8}, MAGENTA},
  17195. {{.2, 0, -1.8}, {.2, 0, -.1}, BRIGHT_CYAN},
  17196. {{.2, 0, -.1}, {.2, .5, -.1}, BLUE},
  17197. {{.2, .5, -.1}, {.2, .6, -.2}, BLUE},
  17198. {{.2, .6, -.2}, {.2, .6, .2}, BLACK},
  17199. {{.2, .6, .2}, {.2, .5, .1}, BLUE},
  17200. {{.2, .5, .1}, {.2, 0, .1}, BRIGHT_BLUE},
  17201. {{.2, 0, .1}, {.2, 0, 1.8}, BRIGHT_GREEN},
  17202. {{.2, 0, 1.8}, {.2, 1, 1.8}, BRIGHT_CYAN},
  17203. {{.2, 1, 1.8}, {.2, 1.2, 1.6}, BRIGHT_CYAN},
  17204. {{.2, 1.2, 1.6}, {.2, 1.1, 2}, BRIGHT_RED},
  17205.  
  17206. -- opposite side:
  17207. {{-.2, 1.1, 2}, {-.2, -.5, 2}, BLUE},
  17208. {{-.2, -.5, 2}, {-.2, -.5, -2}, YELLOW},
  17209. {{-.2, -.5, -2}, {-.2, 1.1, -2}, GREEN},
  17210. {{-.2, 1.1, -2}, {-.2, 1.2, -1.6}, BRIGHT_RED},
  17211. {{-.2, 1.2, -1.6}, {-.2, 1, -1.8}, BRIGHT_RED},
  17212. {{-.2, 1, -1.8}, {-.2, 0, -1.8}, MAGENTA},
  17213. {{-.2, 0, -1.8}, {-.2, 0, -.1}, BRIGHT_CYAN},
  17214. {{-.2, 0, -.1}, {-.2, .5, -.1}, BLUE},
  17215. {{-.2, .5, -.1}, {-.2, .6, -.2}, BLUE},
  17216. {{-.2, .6, -.2}, {-.2, .6, .2}, BLACK},
  17217. {{-.2, .6, .2}, {-.2, .5, .1}, BLUE},
  17218. {{-.2, .5, .1}, {-.2, 0, .1}, BRIGHT_BLUE},
  17219. {{-.2, 0, .1}, {-.2, 0, 1.8}, BRIGHT_GREEN},
  17220. {{-.2, 0, 1.8}, {-.2, 1, 1.8}, BRIGHT_CYAN},
  17221. {{-.2, 1, 1.8}, {-.2, 1.2, 1.6}, BRIGHT_CYAN},
  17222. {{-.2, 1.2, 1.6}, {-.2, 1.1, 2}, BRIGHT_RED},
  17223.  
  17224. -- cross pieces:
  17225. {{.2, 1.1, 2}, {-.2, 1.1, 2}, BLUE},
  17226. {{.2, -.5, 2}, {-.2, -.5, 2}, BLUE},
  17227. {{.2, -.5, -2}, {-.2, -.5, -2}, GREEN},
  17228. {{.2, 1.1, -2}, {-.2, 1.1, -2}, GREEN},
  17229. {{.2, 1.2, -1.6}, {-.2, 1.2, -1.6}, BRIGHT_GREEN},
  17230. {{.2, .6, -.2}, {-.2, .6, -.2}, BLACK},
  17231. {{.2, .6, .2}, {-.2, .6, .2}, BLACK},
  17232. {{.2, 1.2, 1.6}, {-.2, 1.2, 1.6}, BRIGHT_GREEN}
  17233. }
  17234.  
  17235. black_pen = c_func(GetStockObject, {BLACK_PEN})
  17236. white_pen = c_func(GetStockObject, {WHITE_PEN})
  17237.  
  17238.   red_pen = c_func(CreatePen, {PS_SOLID, 1, 255})
  17239. green_pen = c_func(CreatePen, {PS_SOLID, 1, 255 * 256})
  17240.  blue_pen = c_func(CreatePen, {PS_SOLID, 1, 255 * 256 * 256})
  17241.  
  17242. sequence history, coords, overall
  17243. point view_point
  17244. integer spread, r
  17245. atom rot_speed
  17246. sequence shape
  17247.  
  17248. view_point = {6, 8, 7.5} / 2.2
  17249. overall = view(view_point)
  17250. rot_speed = 0.09
  17251. sin_angle = sin(rot_speed)
  17252. cos_angle = cos(rot_speed)
  17253. axis = Z
  17254. history = {}
  17255. spread = 0
  17256. shape = E
  17257.  
  17258. procedure spin()
  17259. -- spin a 3-D shape around on the screen in interesting ways
  17260. -- each call makes one slight movement
  17261.     coords = new_coords(overall, shape)
  17262.     if length(history) > spread then
  17263.     display(history[1], coords)
  17264.     history = history[2..length(history)]
  17265.     if length(history) > spread then
  17266.         display(history[1], {})
  17267.         history = history[2..length(history)]
  17268.     end if
  17269.     else
  17270.     display({}, coords)
  17271.     end if
  17272.     history = append(history, coords)
  17273.     
  17274.     r = rand(250)
  17275.     if r = 1 then
  17276.     axis = X
  17277.     elsif r = 2 then
  17278.     axis = Y
  17279.     elsif r = 3 then
  17280.     axis = Z
  17281.     elsif r = 4 then
  17282.     spread = 5 * rand(25)  -- leave behind many trailing wire images
  17283.     elsif r = 5 or r = 6 then
  17284.     spread = 0             -- reduce the images back to a sharp picture
  17285.     elsif r = 7 then
  17286.     if rand(2) = 1 then
  17287.         rot_speed = .04
  17288.         spread = 0
  17289.     else
  17290.         rot_speed = .02 * rand(10)
  17291.     end if
  17292.     sin_angle = sin(rot_speed)
  17293.     cos_angle = cos(rot_speed)
  17294.     end if
  17295.     shape = compute_rotate(axis, shape)
  17296. end procedure
  17297.  
  17298. constant cbSize = 0,
  17299.      style  = 4,
  17300.      lpfnWndProc = 8,
  17301.      cbClsExtra = 12,
  17302.      cbWndExtra = 16,
  17303.      hInstance  = 20,
  17304.      hIcon      = 24,
  17305.      hCursor    = 28,
  17306.      hbrBackground = 32,
  17307.      lpszMenuName  = 36,
  17308.      lpszClassName = 40,
  17309.      hIconSm = 44,
  17310.      SIZE_OF_WNDCLASS = 48 -- (to be safe) 48
  17311.  
  17312. constant SIZE_OF_MESSAGE = 40 -- (to be safe) 28
  17313.  
  17314. constant CS_HREDRAW = 2,
  17315.      CS_VREDRAW = 1
  17316.  
  17317. constant SW_SHOWNORMAL = 1
  17318.  
  17319. constant WM_CREATE = #0001,
  17320.      WM_PAINT  = #000F,
  17321.      WM_DESTROY= #0002,
  17322.      WM_TIMER  = #0113,
  17323.      WM_SIZE   = #0005
  17324.      
  17325. constant SND_FILENAME = #00020000,
  17326.      SND_ASYNC    = #00000001
  17327.      
  17328. constant DT_SINGLELINE = #0020,
  17329.      DT_CENTER     = #0001,
  17330.      DT_VCENTER    = #0004,
  17331.      DT_WORDBREAK  = #0010
  17332.  
  17333. function or_all(sequence s)
  17334. -- or together all elements of a sequence
  17335.     atom result
  17336.     
  17337.     result = 0
  17338.     for i = 1 to length(s) do
  17339.     result = or_bits(result, s[i])
  17340.     end for
  17341.     return result
  17342. end function
  17343.  
  17344. constant WS_OVERLAPPED  = #00000000,
  17345.      WS_CAPTION     = #00C00000,
  17346.      WS_SYSMENU     = #00080000,
  17347.      WS_THICKFRAME  = #00040000,
  17348.      WS_MINIMIZEBOX = #00020000,
  17349.      WS_MAXIMIZEBOX = #00010000 
  17350.  
  17351. constant IDI_APPLICATION = 32512, 
  17352.      IDC_ARROW = 32512, 
  17353.      WHITE_BRUSH = 0,
  17354.      CW_USEDEFAULT = #80000000,
  17355.      WS_OVERLAPPEDWINDOW = or_all({WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU,
  17356.                        WS_THICKFRAME, WS_MINIMIZEBOX, 
  17357.                        WS_MAXIMIZEBOX})
  17358.      
  17359. sequence big
  17360. atom ps, rect, wav, big_string
  17361. ps = allocate(64)
  17362. rect = allocate(16) 
  17363. wav = allocate_string("\\Windows\\Media\\Jungle Default.wav")
  17364. big = ""
  17365. for i = 1 to 300 do
  17366.     big &= " Resize This Window! "
  17367. end for
  17368. big_string = allocate_string(big)
  17369.  
  17370. global function WndProc(atom hwnd, atom iMsg, atom wParam, atom lParam)
  17371. -- callback routine to handle Window class
  17372.     
  17373.     if iMsg = WM_CREATE then
  17374.     return 0
  17375.     
  17376.     elsif iMsg = WM_PAINT then
  17377.     hdc = c_func(BeginPaint, {hwnd, ps})
  17378.     c_proc(GetClientRect, {hwnd, rect})
  17379.     c_proc(DrawText, {hdc, big_string, -1, rect, DT_WORDBREAK})
  17380.     c_proc(EndPaint, {hwnd, ps})
  17381.     c_proc(SetTimer, {hwnd, 1, 10, NULL})
  17382.     return 0
  17383.     
  17384.     elsif iMsg = WM_SIZE then
  17385.     c_proc(PlaySound, {wav,
  17386.                NULL,
  17387.                or_bits(SND_FILENAME, SND_ASYNC)})
  17388.     vc[VC_XPIXELS] = and_bits(lParam, #FFFF)
  17389.     vc[VC_YPIXELS] = and_bits(lParam/#10000, #FFFF)
  17390.     
  17391.     elsif iMsg = WM_TIMER then
  17392.     hdc = c_func(GetDC, {hwnd})
  17393.     -- make 5 iterations before giving control back to Windows
  17394.     for i = 1 to 5 do
  17395.         spin()
  17396.     end for
  17397.     c_proc(ReleaseDC, {hwnd, hdc})
  17398.     return 0
  17399.     
  17400.     elsif iMsg = WM_DESTROY then
  17401.     c_proc(PostQuitMessage, {0})
  17402.     c_proc(KillTimer, {hwnd, 1})
  17403.     return 0
  17404.     
  17405.     end if
  17406.     
  17407.     return c_func(DefWindowProc, {hwnd, iMsg, wParam, lParam})
  17408. end function
  17409.  
  17410. procedure WinMain()
  17411. -- main routine 
  17412.     atom szAppName
  17413.     atom hwnd
  17414.     atom msg
  17415.     atom wndclass
  17416.     atom WndProcAddress
  17417.     atom class
  17418.     integer id
  17419.     
  17420.     wndclass = allocate(SIZE_OF_WNDCLASS)
  17421.     msg = allocate(SIZE_OF_MESSAGE)
  17422.     szAppName = allocate_string("HelloWin")
  17423.     
  17424.     id = routine_id("WndProc")
  17425.     if id = -1 then
  17426.     puts(1, "routine_id failed!\n")
  17427.     abort(1)
  17428.     end if
  17429.     WndProcAddress = call_back(id) -- get 32-bit address for callback
  17430.     
  17431.     poke4(wndclass + cbSize, SIZE_OF_WNDCLASS)
  17432.     poke4(wndclass + style, or_bits(CS_HREDRAW, CS_VREDRAW))
  17433.     poke4(wndclass + lpfnWndProc, WndProcAddress)
  17434.     poke4(wndclass + cbClsExtra, 0)
  17435.     poke4(wndclass + cbWndExtra, 0)
  17436.     poke4(wndclass + hInstance, 0) --hInstance
  17437.     poke4(wndclass + hIcon, c_func(LoadIcon, {NULL, IDI_APPLICATION}))
  17438.     poke4(wndclass + hCursor, c_func(LoadCursor, {NULL, IDC_ARROW}))
  17439.     poke4(wndclass + hbrBackground, c_func(GetStockObject, {WHITE_BRUSH}))
  17440.     poke4(wndclass + lpszMenuName, NULL)
  17441.     poke4(wndclass + lpszClassName, szAppName)
  17442.     poke4(wndclass + hIconSm, c_func(LoadIcon, {NULL, IDI_APPLICATION}))
  17443.  
  17444.     class = c_func(RegisterClassEx, {wndclass})
  17445.     if class = 0 then
  17446.     puts(1, "Couldn't register class\n")
  17447.     abort(1)
  17448.     end if
  17449.     hwnd = c_func(CreateWindow, {
  17450.             0,                       -- extended style
  17451.             szAppName,               -- window class name
  17452.             allocate_string("Euphoria for WIN32"), -- window caption
  17453.             WS_OVERLAPPEDWINDOW,     -- window style
  17454.             CW_USEDEFAULT,           -- initial x position
  17455.             CW_USEDEFAULT,           -- initial y position
  17456.             CW_USEDEFAULT,           -- initial x size
  17457.             CW_USEDEFAULT,           -- initial y size
  17458.             NULL,                    -- parent window handle
  17459.             NULL,                    -- window menu handle
  17460.             0 ,                 --hInstance // program instance handle
  17461.             NULL})              -- creation parameters
  17462.     if hwnd = 0 then
  17463.     puts(1, "Couldn't CreateWindow\n")
  17464.     abort(1)
  17465.     end if
  17466.     c_proc(ShowWindow, {hwnd, SW_SHOWNORMAL})
  17467.     c_proc(UpdateWindow, {hwnd})
  17468.  
  17469.     while c_func(GetMessage, {msg, NULL, 0, 0}) do
  17470.     c_proc(TranslateMessage, {msg})
  17471.     c_proc(DispatchMessage, {msg})
  17472.     end while
  17473. end procedure
  17474.  
  17475. vc = {1, 257, 25, 80, 800, 600, 256, 1}
  17476.  
  17477. atom t
  17478.  
  17479. procedure FullMain()
  17480. -- Display graphics using the full screen
  17481.     puts(1, "\nPress any key to stop.\n")
  17482.     puts(1, "Make a full-screen DOS window\n")
  17483.     puts(1, "to clear the screen...\n")
  17484.     t = time()
  17485.     while time() < t + 4 do
  17486.     end while
  17487.     hdc = c_func(CreateDC, {allocate_string("DISPLAY"), NULL, NULL, NULL})
  17488.     if hdc = NULL then
  17489.     puts(1, "CreateDC failed!\n")
  17490.     abort(1)
  17491.     end if
  17492.     while get_key() = -1 do
  17493.     spin()
  17494.     end while
  17495.     clear_screen()
  17496. end procedure
  17497.  
  17498. -- execution starts here:
  17499. if FULL_SCREEN then
  17500.     FullMain()
  17501.     clear_screen()
  17502. else
  17503.     WinMain()
  17504. end if
  17505.  
  17506. BASIC.HTX
  17507. 2122
  17508. <_init_comment>
  17509. <html>
  17510. <head><title>An important message for all BASIC programmers...</title>
  17511. </head>
  17512. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  17513. <_width>
  17514. <_center><font face="Arial, Helvetica" color="#006633" size=+2>
  17515. <br>
  17516.             An important message for all BASIC programmers...
  17517. </font></_center>
  17518. <br>
  17519. <_center><font face="Arial, Helvetica" color="#FF0099" size=+1>
  17520.      13 Reasons Why You Are Going to Write Your Next Program in Euphoria!
  17521. </font></_center>
  17522. <p> 
  17523.  
  17524. <ul>
  17525. <li>
  17526.  because Euphoria programs run on DOS, Windows and Linux.
  17527. <p>
  17528. <li>
  17529.  because Euphoria is actually
  17530.  <font color="#CC0099"><_ba><i>simpler</i></_ba></font> than BASIC
  17531. <p>
  17532. <li>
  17533.  because Euphoria is
  17534.   <font color="#CC0099"><b><i>10 to 20 times faster</i></b></font> than
  17535.   Microsoft QBasic (see <font color="#5500FF"><b>demo\bench</b></font>)
  17536. <p>
  17537. <li>
  17538.  because QBasic limits the size of your program and data to 160K bytes
  17539. <p>
  17540. <li>
  17541.  because Euphoria checks for uninitialized variables - BASIC just quietly
  17542.   sets them to 0
  17543. <p>
  17544. <li>
  17545.  because Euphoria lets you say precisely what values may be stored in
  17546.   each variable
  17547. <p>
  17548. <li>
  17549.  because Euphoria has <font color="#CC0099"><b>true</b></font> dynamic
  17550.   storage allocation - you do not wipe out your data when you redimension
  17551.   an array
  17552. <p>
  17553. <li>
  17554.  because Euphoria is <font color="#CC0099"><b><i>more flexible</i></b></font>
  17555.   than BASIC - you can declare types for your variables or not; you can
  17556.   store objects of any size into an array (Euphoria sequence); you can
  17557.   have arrays of mixed type of data
  17558. <p>
  17559. <li>
  17560.  because Euphoria lets you perform operations on entire sequences
  17561. <p>
  17562. <li>
  17563.  because BASIC is an old "ad-hoc" language that carries 25 years of
  17564.   redundant, excess baggage along with it
  17565. <p>
  17566. <li>
  17567.  because there is no effective standard for BASIC across different machines
  17568.   and there probably never will be
  17569. <p>
  17570. <li>
  17571.  because QBasic provides no built-in functions for using a <b>mouse</b>
  17572. <p>
  17573. <li>
  17574.  because QBasic does not support <b>SVGA</b> graphics
  17575.  
  17576. </ul>
  17577.  
  17578. <p> 
  17579.  
  17580. </_width>
  17581. </body>
  17582. </html>
  17583.  
  17584. BIND.HTX
  17585. 14708
  17586. <_init_comment>
  17587. <html>
  17588. <head><title>Shrouding and Binding</title>
  17589. </head>
  17590. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  17591. <_width>
  17592. <_center><font face="Arial, Helvetica" color="#FF0099" size=+2>
  17593. <br>
  17594.                          Shrouding and Binding
  17595. </font></_center>
  17596. <_center><font face="Arial, Helvetica" color="#003366" size=+1>
  17597.                         (Complete Edition only)
  17598. </font></_center>
  17599. <p>
  17600.  
  17601. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  17602. <br>
  17603.  
  17604. <_dul>What is Shrouding and Binding?</_dul>
  17605.  
  17606. </font>
  17607. <p>
  17608.  In the Euphoria Complete Edition for DOS32+WIN32,
  17609.  <font color="#5500FF"><b>shroud.bat</b></font>,
  17610.  <font color="#5500FF"><b>bind.bat</b></font>,
  17611.  <font color="#5500FF"><b>bindw.bat</b></font> and
  17612.  <font color="#5500FF"><b>bind.ex</b></font> are in
  17613.  <font color="#5500FF"><b>euphoria\bin</b></font>. In the Complete Edition
  17614.  for Linux, you will find 
  17615.  <font color="#5500FF"><b>shroud</b></font>, 
  17616.  <font color="#5500FF"><b>bindu</b></font> and 
  17617.  <font color="#5500FF"><b>bind.ex</b></font> in 
  17618.  <font color="#5500FF"><b>euphoria/bin</b></font>.
  17619.  The documentation for
  17620.  these programs is given below.  
  17621. <p>
  17622. <a name=steps></a>
  17623.  The <font color="#5500FF"><b>shroud</b></font> command will prompt you for the name
  17624.  of your main Euphoria file, and the name of 
  17625.  the new <font color="#993333"><b>shrouded</b></font> file
  17626.  that you want to create. <font color="#993333"><b>Shrouding</b></font>
  17627.  does the following to your program:
  17628.  
  17629. <p>
  17630.  <table border=0 cellspacing=2 cellpadding=2>
  17631.  
  17632. <_4clist
  17633.   name="1."
  17634.   pos=10
  17635.   description="Your main file is combined with all of the
  17636.    <b>.e</b> files that it directly or indirectly includes. This makes a
  17637.    single Euphoria file with no include statements."
  17638. >
  17639.  
  17640. <_4clist
  17641.   name="2."
  17642.   pos=10
  17643.   description="All comments and blank lines are removed."
  17644. >
  17645.  
  17646. <_4clist
  17647.   name="3."
  17648.   pos=10
  17649.   description="All keywords are replaced by single-byte codes."
  17650. >
  17651.  
  17652. <_4clist
  17653.   name="4."
  17654.   pos=10
  17655.   description="All variable names and
  17656.    (<font color=\"#CC3366\"><b>optionally</b></font>) subroutine names are
  17657.    converted to short meaningless names chosen by the shroud program."
  17658. >
  17659.  
  17660. <_4clist
  17661.   name="5."
  17662.   pos=10
  17663.   description="<font color=\"#CC3366\"><b>(optional)</b></font> All strings
  17664.    are converted to sequences of ASCII codes so they can't be easily read."
  17665. >
  17666.  
  17667. <_4clist
  17668.   name="6."
  17669.   pos=10
  17670.   description="<font color=\"#CC3366\"><b>(optional)</b></font> The resulting
  17671.    shrouded file from steps 1 to 5 can be further
  17672.    <font color=\"#993333\"><b><i>\"scrambled\"</i></b></font> so it becomes
  17673.    completely unreadable and highly tamper-resistant. For an example of a 
  17674.    shrouded and scrambled file, have a
  17675.    look at <font color=\"#5500FF\"><b>bin\bind.ex</b></font>"
  17676. >
  17677.  
  17678. </table>
  17679.  
  17680. <p>
  17681.  <font color="#5500FF"><b>bind</b></font>
  17682.  (<font color="#5500FF"><b>bindw</b></font> or
  17683.  <font color="#5500FF"><b>bindu</b></font>) does the same thing as
  17684.  <font color="#5500FF"><b>shroud</b></font>. It then combines your
  17685.  shrouded, and possibly scrambled, file with the Public Domain Edition
  17686.  <font color="#993333"><b>ex.exe</b></font>,
  17687.  <font color="#993333"><b>exw.exe</b></font> or
  17688.  <font color="#993333"><b>exu</b></font> to make a
  17689.  <font color="#CC0099"><b>single, stand-alone executable</b></font> file that you
  17690.  can use and distribute. Each time your executable file is run, a 
  17691.  quick integrity check is performed to detect any tampering or corruption.
  17692.  
  17693. <p>
  17694.  <a href="bind.htm#steps">Step 5 above</a> goes beyond the typical <b>.exe</b>
  17695.  file produced by other languages, where you can easily read character strings
  17696.  in the <b>.exe</b>. <font color="#993333"><b>Shrouding</b></font> not only
  17697.  conceals your source code, it also combines it into a single, very compact 
  17698.  file.
  17699.  
  17700. <p>
  17701.  To further enhance security, <font color="#993333"><b>scrambling</b></font>
  17702.  is also provided. Only RDS has the knowledge required to descramble a
  17703.  program and we promise never to do so. If someone managed to descramble your
  17704.  program, they would only recover the shrouded version of the source
  17705.  (after steps 1 to 5), not the original source code. The comments, and the
  17706.  meaningful variable and routine names can 
  17707.  <font color="#CC0099"><_ba><i>never</i></_ba></font> be recovered.
  17708.  <font color="#006633"><_ba>Always keep a copy of your original source
  17709.  files.</_ba></font>
  17710.  
  17711. <p>
  17712.  
  17713. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  17714. <br>
  17715.  
  17716. <_dul>How to Shroud and Bind</_dul>
  17717.  
  17718. </font>
  17719. <p>
  17720.  Your program should at least be free of syntax errors before you
  17721.  <font color="#993333"><b>bind</b></font> or
  17722.  <font color="#993333"><b>shroud</b></font> it.
  17723.  If you are actively developing a program you'll find it is more
  17724.  convenient to run it in the normal way with
  17725.  <font color="#993333"><b>ex</b></font>
  17726.  (or <font color="#993333"><b>exw</b></font> or 
  17727.  <font color="#993333"><b>exu</b></font>), rather than binding it and
  17728.  running it as a <b>.exe</b> file. Error messages generated against shrouded
  17729.  code will be difficult to relate back to your original source, since the
  17730.  line numbering and symbol names will be very different.
  17731.  
  17732. <p>
  17733.  You can distribute a <font color="#993333"><b>shrouded/scrambled</b></font>
  17734.  <b>.e</b> include file that people can include in their programs 
  17735.  without seeing your
  17736.  source code. Symbols declared as <font color="#993333"><b>global</b></font>
  17737.  in your main <b>.e</b> file will not be
  17738.  renamed, so your users can access routines and variables with meaningful
  17739.  long names, while the rest of your file remains shrouded. Try to make the
  17740.  <font color="#993333"><b>global</b></font> names in your <b>.e</b> file at
  17741.  least 2 or 3 characters long to avoid conflicting with any short names
  17742.  already assigned by the <font color="#993333"><b>shrouder</b></font>. You'll
  17743.  be warned if there are any naming conflicts, and the
  17744.  <font color="#993333"><b>shrouder</b></font> will assign a new name. In this
  17745.  case you might want to choose a different (longer) name for the offending
  17746.  global symbol.
  17747.  
  17748. <p>
  17749.  In most cases you should simply type:
  17750. <pre>
  17751.         shroud
  17752. </pre>
  17753.  or:
  17754. <pre>
  17755.         bind
  17756. </pre>
  17757.  or:
  17758. <pre>
  17759.         bindw
  17760. </pre>
  17761.  or:
  17762. <pre>
  17763.         bindu
  17764. </pre>
  17765.  and you will be prompted for the source file name and other options.
  17766. <p>
  17767.  If you type:
  17768. <pre>
  17769.         shroud filename
  17770. </pre>
  17771.  or:
  17772. <pre>
  17773.         bind filename
  17774. </pre>
  17775.  or:
  17776. <pre>
  17777.         bindw filename
  17778. </pre>
  17779.  or:
  17780. <pre>
  17781.         bindu filename
  17782. </pre>
  17783.  It will be assumed that you want:
  17784. <pre>
  17785.         <font color="#003366">hide_strings:</font> <font color="#FF0000">NO</font>
  17786.         <font color="#003366">clear_routines:</font> <font color="#FF0000">NO</font>
  17787.         <font color="#003366">scramble:</font> <font color="#FF0000">NO</font>
  17788.         <font color="#003366">full_keywords:</font> <font color="#FF0000">NO</font>
  17789. </pre>
  17790. <p>
  17791.  <font color="#993333"><b>shroud</b></font> and
  17792.  <font color="#993333"><b>bind</b></font> can also be run non-interactively
  17793.  using <font color="#993333"><b>command-line</b></font> arguments.
  17794.  For example:
  17795. <pre>
  17796.         bind -scramble -clear_routines myprog
  17797. </pre>
  17798.  or
  17799. <pre>
  17800.         bindw -hide_strings myprog
  17801. </pre>
  17802.  
  17803.  This might be useful if you wish to create a <b>.bat</b> or shell 
  17804.  file to automatically
  17805.  <font color="#993333"><b>bind</b></font> or
  17806.  <font color="#993333"><b>shroud</b></font> your program. The full set of
  17807.  command-line options is described <a href="bind.htm#cl_options">below</a>.
  17808.  
  17809. <p>
  17810.  Only the Public Domain Edition interpreter files can be bound. Users of 
  17811.  the Euphoria Complete Edition for DOS32 + WIN32 will have
  17812.  <font color="#993333"><b>ex.exe</b></font> (Complete) and
  17813.  <font color="#993333"><b>pdex.exe</b></font> (Public Domain), as well as
  17814.  <font color="#993333"><b>exw.exe</b></font> (Complete) and
  17815.  <font color="#993333"><b>pdexw.exe</b></font> (Public Domain) in
  17816.  <font color="#5500FF"><b>euphoria\bin</b></font>.
  17817.  The <font color="#993333"><b>bind</b></font>
  17818.  (<font color="#993333"><b>bindw</b></font>) program will use the
  17819.  <font color="#993333"><b>pdex.exe</b></font>
  17820.  (<font color="#993333"><b>pdexw.exe</b></font>) files for binding.
  17821.  On Linux, you'll have
  17822.  <font color="#993333"><b>exu</b></font> (Complete) and
  17823.  <font color="#993333"><b>pdexu</b></font> (Public Domain), with
  17824.  <font color="#993333"><b>pdexu</b></font> used for binding.
  17825. <p>
  17826.  A one-line Euphoria program will result in an executable file as large as
  17827.  the interpreter you are binding with, but the size increases
  17828.  very slowly as you add to your program.
  17829.  <font color="#006633"><b>When bound, the entire Euphoria editor adds only
  17830.  20K to the size of the interpreter.</b></font> All three interpreters are
  17831.  compressed to reduce their size. <b>exw.exe</b> and <b>exu</b>
  17832.  are compressed using <b>UPX</b> (see http://upx.tsx.org). 
  17833.  <b>ex.exe</b> is compressed using a tool that comes with the CauseWay DOS
  17834.  extender. <b>ex.exe</b> is the largest of the three since it 
  17835.  includes a lot of pixel graphics routines, not part of <b>exw.exe</b> 
  17836.  or <b>exu</b>. Note: In some cases, a compressed executable will trigger a
  17837.  warning message from a virus scanner. This is simply because
  17838.  the executable file looks abnormal to the virus scanner. If demo\sanity.ex
  17839.  runs correctly, you can safely ignore these warnings. 
  17840.  Otherwise contact RDS.
  17841.  
  17842. <p>
  17843.  The first two arguments returned by the
  17844.  <font color="#006699"><b>command_line()</b></font> library routine will be
  17845.  slightly different when your program is bound. See
  17846.  <a href="lib_c_d.htm#command_line"><font color="#5500FF"><b>library.doc</b></font></a>
  17847.  for the details.
  17848.  
  17849. <p>
  17850.  A <b><font color="#993333">bound</font> executable</b> file
  17851.  <font color="#CC0099"><b><i>can</i></b></font> handle standard input and
  17852.  output redirection. e.g.
  17853. <pre>
  17854.         myprog.exe < file.in > file.out
  17855. </pre>
  17856.  
  17857.  If you were to write a small DOS <b>.bat</b> file <_bq>myprog.bat</_bq> that
  17858.  contained the line "<b>ex myprog.ex</b>" you would <i>not</i> be able to
  17859.  redirect input and output in the following manner:
  17860. <pre>
  17861.         myprog.bat < file.in > file.out     <font color="#FF0000">(doesn't work in DOS!)</font>
  17862. </pre>
  17863.  You <i>could</i> however use redirection on individual lines <i>within</i>
  17864.  the <b>.bat</b> file.
  17865.  
  17866. <p>
  17867. <a name=cl_options></a>
  17868. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  17869. <br>
  17870.  
  17871. <_dul>Summary of Options for Bind and Shroud</_dul>
  17872.  
  17873. </font>
  17874. <p>
  17875. <table border=0 cellspacing=2 cellpadding=2>
  17876.  
  17877.  <_2clist
  17878.   name="<font color=\"#003366\">Syntax:</font>"
  17879.   description="<font color=\"#003366\">
  17880.    bind <i>options</i> filename.ex<p>
  17881.    bindw <i>options</i> filename.exw<p>
  17882.    bindu <i>options</i> filename.exu<p>
  17883.    shroud <i>options</i> filename.ex<p>
  17884.    shroud <i>options</i> filename.exw<p>
  17885.    shroud <i>options</i> filename.exu<p>
  17886.    </font>"
  17887.  >
  17888.  
  17889. </table>
  17890.  
  17891. <p>
  17892. <font color="#006633"><b><_sul>where <i>options</i> can be:</_sul></b></font>
  17893. <p>
  17894. <table border=0 cellspacing=2 cellpadding=2>
  17895.  
  17896. <_4clist
  17897.   name="<font color=\"#006699\">-hide_strings</font>"
  17898.   pos=20
  17899.   description="Convert strings to sequences of ASCII codes. This provides
  17900.    better shrouding, but increases the size of the shrouded file."
  17901. >
  17902.  
  17903. <_4clist
  17904.   name="<font color=\"#006699\">-clear_routines</font>"
  17905.   pos=20
  17906.   description="All procedures, types and functions will retain their full
  17907.    name. This is needed if your program uses
  17908.    <font color=\"#006699\"><b>routine_id()</b></font>.
  17909.    <p>
  17910.    You will get warnings when routines from different included files happen
  17911.    to have the same name. The <font color=\"#993333\"><b>shrouder</b></font>
  17912.    will pick a new name, which should be fine, unless the original name is
  17913.    used in a call to <font color=\"#006699\">routine_id()</font>."
  17914. >
  17915.  
  17916. <_4clist
  17917.   name="<font color=\"#006699\">-scramble</font>"
  17918.   pos=20
  17919.   description="Make the shrouded code extremely difficult to read or tamper
  17920.    with. Your program might load a few percent slower when you use this
  17921.    option."
  17922. >
  17923.  
  17924. <_4clist
  17925.   name="<font color=\"#006699\">-icon <i>filename[.ico]</i></font>"
  17926.   pos=20
  17927.   description="When you bind a program, you can patch in your own 
  17928.   customized icon, overwriting the one in <b>exw.exe</b>. 
  17929.   <b>exw.exe</b> contains a 32x32 icon using 256 colors. It resembles 
  17930.   an <b>E)</b> shape. Windows will display this shape beside exw.exe,
  17931.   and beside your bound program, in file listings. You can also 
  17932.   load this icon as a resource, using the name \"exw\" 
  17933.   (see euphoria\demo\win32\window.exw for an example). 
  17934.   When you bind your program, you can substitute your own 32x32 256-color 
  17935.   icon file of size 2238 bytes or less. Other dimensions may also work
  17936.   as long as the file is 2238 bytes or less. The file must contain
  17937.   a single icon image (Windows will create a smaller or larger image
  17938.   as necessary). The default <b>E)</b> 
  17939.   icon file, euphoria.ico, is included in the Complete Edition.
  17940.   You can bind it, or distribute it separately, with or without 
  17941.   your changes."
  17942. >
  17943.  
  17944. <_4clist
  17945.   name="<font color=\"#006699\">-full_keywords</font>"
  17946.   pos=20
  17947.   description="The shrouded code will contain full keywords rather than
  17948.    byte codes. This option is rarely used and you won't be prompted for it
  17949.    interactively. Only <font color=\"#5500FF\"><b>shroud</b></font>
  17950.    supports this option."
  17951. >
  17952.  
  17953. </table>
  17954.  
  17955. <p>
  17956.  When a shrouded or bound program has an error, the error report will refer
  17957.  to the shrouded code, not the original source code. Before shipping a
  17958.  <font color="#993333"><b>shrouded</b></font> or
  17959.  <font color="#993333"><b>bound</b></font> file to your users, it might
  17960.  be useful to run <br>
  17961.  <b>shroud -full_keywords</b> to get a semi-readable shrouded file that
  17962.  matches line for line, and symbol for symbol, with what you are shipping.
  17963.  Also select <b>-hide_strings</b>, if that's what you did in the one you are
  17964.  shipping. It will help you to interpret error messages that users report.
  17965.  It is not possible to <font color="#993333"><b>bind</b></font> the full,
  17966.  clear source of your program.
  17967.  
  17968. <p>
  17969.  You can <font color="#993333"><b>shroud</b></font> or 
  17970.  <font color="#993333"><b>bind</b></font> a program that
  17971.  <i>includes a <font color="#993333"><b>shrouded</b></font> file</i>
  17972.  (presumably from someone else). To include a
  17973.  <font color="#993333"><_ba><i>scrambled</i></_ba></font> file, you
  17974.  <font color="#CC0099"><b><i>must</i></b></font> choose the <b>-scramble</b>
  17975.  option. i.e. the level of security of the scrambled file cannot be downgraded.
  17976.  
  17977. <p> 
  17978.  
  17979. </_width>
  17980. </body>
  17981. </html>
  17982. C.HTX
  17983. 4910
  17984. <_init_comment>
  17985. <html>
  17986. <head><title>An important message for all C/C++ programmers...</title>
  17987. </head>
  17988. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  17989. <_width>
  17990. <_center><font face="Arial, Helvetica" color="#006633" size=+2>
  17991. <br>
  17992.             An important message for all C/C++ programmers...
  17993. </font></_center>
  17994. <br>
  17995. <_center><font face="Arial, Helvetica" color="#FF0099" size=+1>
  17996.      26 Reasons Why You Are Going to Write Your Next Program in Euphoria! 
  17997. </font></_center>
  17998. <p> 
  17999.  
  18000. <ul>
  18001. <li>
  18002.  because you are tired of having to re-invent dynamic storage allocation 
  18003.   for each program that you write
  18004. <p>
  18005. <li>
  18006.  because you want to break free, once and for all, from 64K and  
  18007.   640K memory limits
  18008. <p>
  18009. <li>
  18010.  because you'd like to forget about near pointers and far pointers, and the 
  18011.   small, medium, compact, large and huge memory models
  18012. <p>
  18013. <li>
  18014.  because you have spent too many frustrating hours tracking down malloc 
  18015.   arena corruption bugs 
  18016. <p>
  18017. <li>
  18018.  because you were once plagued for several days by an on-again/off-again
  18019.   "flaky" bug that eventually was traced to an uninitialized variable
  18020. <p>
  18021. <li>
  18022.  because no matter how hard you try to eliminate them, there is always 
  18023.   one more storage "leak"
  18024. <p>
  18025. <li>
  18026.  because you are tired of having the machine "lock up", or your program
  18027.   come crashing down in flames with no indication of what the error was
  18028. <p>
  18029. <li>
  18030.  because you know that
  18031.   <font color="#006633"><b>subscript checking</b></font> would have
  18032.   saved you from hours of debugging
  18033. <p>
  18034. <li>
  18035.  because your program should not be allowed to overwrite random areas in 
  18036.   memory via "wild" pointers
  18037. <p>
  18038. <li>
  18039.  because you know it would be bad to overflow your fixed-size stack area
  18040.   but you have no idea of how close you are
  18041. <p>
  18042. <li>
  18043.  because one time you had this weird bug, where you called a function,
  18044.   that didn't actually return a value, but instead fell off the end
  18045.   and some random garbage was "returned"
  18046. <p>
  18047. <li>
  18048.  because you wish that library routines would stop you from passing
  18049.   in bad arguments, rather than just setting "errno" or whatever
  18050.   (who looks at errno after every call?)
  18051. <p>
  18052. <li>
  18053.  because you would like to "recompile the world" in a fraction of a second
  18054.   rather than several minutes -- you can work much faster with a cycle of
  18055.   edit/run rather than edit/compile/link/run.
  18056. <p>
  18057. <li>
  18058.  because <i>The C++ Programming Language</i> 3rd Ed. by Bjarne Stroustrup is
  18059.  911 very dense pages, (and doesn't even discuss 
  18060.  platform-specific programming for DOS, Windows, Linux or any other system).
  18061. <p>
  18062. <li>
  18063.  because you have been programming in C/C++ for a long time now, but there
  18064.   are still a lot of weird features in the language that you don't feel
  18065.   confident about using
  18066. <p>
  18067. <li>
  18068.  because portability is not as easy to achieve as it should be
  18069. <p>
  18070. <li>
  18071.  because you know the range of legitimate values for each of your variables,
  18072.   but you have no way of enforcing this at runtime  
  18073. <p>
  18074. <li>
  18075.  because you would like to pass variable numbers of arguments, but
  18076.   you are put off by the complicated way of doing it in C
  18077. <p>
  18078. <li>
  18079.  because you would like a <font color="#CC0099"><b><i>clean way</i></b></font>
  18080.   of returning multiple values from a function
  18081. <p>
  18082. <li>
  18083.  because you want an integrated
  18084.   <font color="#006633"><b>full-screen source-level debugger</b></font>
  18085.   that is so easy to use that you don't have to search through the manual
  18086.   each time, (or give up and recompile with printf statements)
  18087. <p>
  18088. <li>
  18089.  because you hate it when your program starts working just because you
  18090.   added a debug print statement or compiled with the debug option
  18091. <p>
  18092. <li>
  18093.  because you would like a reliable, accurate
  18094.   <font color="#006633"><b>statement-level profile</b></font> to
  18095.   understand the internal dynamics of your program, and to boost performance
  18096. <p>
  18097. <li>
  18098.  because few of your programs have to squeeze every cycle of performance out
  18099.   of your machine. The speed difference between Euphoria and C/C++ is not as 
  18100.   great as you might think. Try some benchmark tests. We bet you'll be 
  18101.   surprised!
  18102. <p>
  18103. <li>
  18104.  because you'd rather not clutter up your hard disk with <b>.</b>obj and
  18105.   <b>.</b>exe files
  18106. <p>
  18107. <li>
  18108.  because you'd rather be running your program, than wading through several 
  18109.   hundred pages of documentation to decide what compiler and linker options 
  18110.   you need
  18111. <p>
  18112. <li>
  18113.  because your C/C++ package has 57 different routines for memory allocation, 
  18114.   and 67 different routines for manipulating strings and blocks of memory.
  18115.   How many of these routines does Euphoria need?
  18116.   <b>Answer: <font color="#CC0099">zero</font>.</b>
  18117.   <font color="#006633"><b>In Euphoria, memory allocation happens
  18118.   automatically and strings are manipulated just like any other
  18119.   sequences.</b></font>
  18120.  
  18121. </ul>
  18122.  
  18123. <p> 
  18124.  
  18125. </_width>
  18126. </body>
  18127. </html>
  18128.  
  18129. COMBINE.EX
  18130. 01108
  18131. sequence ref_files, lib_files
  18132. ref_files = {
  18133. "refman.doc",
  18134. "refman_1.doc",
  18135. "refman_2.doc",
  18136. "refman_3.doc"
  18137. }
  18138. lib_files = {
  18139. "library.doc",
  18140. "lib_a_b.doc",
  18141. "lib_c_d.doc",
  18142. "lib_e_g.doc",
  18143. "lib_h_o.doc",
  18144. "lib_p_r.doc",
  18145. "lib_s_t.doc",
  18146. "lib_u_z.doc"
  18147. }
  18148. function try_open(sequence filename, sequence mode)
  18149. integer fn
  18150. fn = open(filename, mode)
  18151. if fn != -1 then
  18152. return fn
  18153. end if
  18154. puts(1, "\nCouldn't open " & filename &'\n')
  18155. abort(1)
  18156. end function
  18157. integer fn, ref_out, lib_out
  18158. object line
  18159. ref_out = try_open("\\euphoria\\doc\\refman.doc", "w")
  18160. puts(ref_out, 
  18161. "[To view this manual with your Web browser, double-click on html\\refman.htm]\n\n")
  18162. for i = 1 to length(ref_files) do
  18163. fn = try_open(ref_files[i], "r")
  18164. while 1 do
  18165. line = gets(fn)
  18166. if atom(line) then
  18167. exit
  18168. end if
  18169. puts(ref_out, line)
  18170. end while
  18171. close(fn)
  18172. end for
  18173. close(ref_out)
  18174. lib_out = open("\\euphoria\\doc\\library.doc", "w")
  18175. for i = 1 to length(lib_files) do
  18176. fn = open(lib_files[i], "r")
  18177. while 1 do
  18178. line = gets(fn)
  18179. if atom(line) then
  18180. exit
  18181. end if
  18182. puts(lib_out, line)
  18183. end while
  18184. close(fn)
  18185. end for
  18186. close(lib_out)
  18187. DOC.EX
  18188. 03453
  18189. without warning
  18190. include docgen.e   
  18191. include html.e     
  18192. include text.e     
  18193. include \euphoria\include\wildcard.e  
  18194. with warning
  18195. function param_list(object text)
  18196. integer i, value_part
  18197. sequence word, list
  18198. if atom(text) then
  18199. return {}
  18200. end if
  18201. list = {}
  18202. i = 1
  18203. value_part = FALSE
  18204. while TRUE do
  18205. while whitespace(text[i]) do
  18206. i = i + 1
  18207. end while
  18208. if text[i] = '>' then
  18209. exit
  18210. end if
  18211. if text[i] = '=' then
  18212. i = i + 1   
  18213. value_part = TRUE
  18214. while whitespace(text[i]) do
  18215. i = i + 1
  18216. end while
  18217. end if
  18218. if text[i] = '"' then
  18219. word = ""
  18220. i = i + 1
  18221. while text[i] != '"' and i < length(text) do
  18222. if text[i] = '\\' then
  18223. if text[i + 1] = '"' then
  18224. word = word & text[i + 1]
  18225. else
  18226. word = word & text[i] & text[i + 1]
  18227. end if
  18228. i = i + 2
  18229. else
  18230. word = word & text[i]
  18231. i = i + 1
  18232. end if
  18233. end while
  18234. if text[i] = '"' then
  18235. i = i + 1
  18236. end if
  18237. else 
  18238. word = ""
  18239. while not whitespace(text[i]) and text[i] != '=' and 
  18240. text[i] != '>' do
  18241. word = word & text[i]
  18242. i = i + 1
  18243. end while
  18244. end if
  18245. if value_part then
  18246. list[length(list)] = {list[length(list)], word}
  18247. value_part = FALSE
  18248. else
  18249. list = append(list, word)
  18250. end if
  18251. end while
  18252. return list
  18253. end function
  18254. procedure tag(sequence name, object param, object raw)
  18255. integer r
  18256. r = find(name, handler_name)
  18257. if r = 0 then
  18258. r = find("_default", handler_name)
  18259. if r = 0 then
  18260. quit("Need a default handler")
  18261. end if
  18262. end if
  18263. if equal(name, "!--") then
  18264. call_proc(handler_id[r], {raw, ""})
  18265. else
  18266. call_proc(handler_id[r], {raw, param_list(param)})
  18267. end if
  18268. end procedure
  18269. procedure scan()
  18270. integer c, inDQuote
  18271. sequence raw, name, param
  18272. while TRUE do
  18273. c = getc(in_file)
  18274. if c = EOF then
  18275. exit
  18276. elsif c = '<' then
  18277. c = getc(in_file)
  18278. if whitespace(c) or c = '=' then
  18279. tag("_literal", '<', '<')
  18280. tag("_literal", c, c)
  18281. else
  18282. raw = "<"
  18283. name = ""
  18284. while not whitespace(c) and c != '>' and c != EOF do
  18285. name = name & c
  18286. c = getc(in_file)
  18287. end while
  18288. name = lower(name)
  18289. raw = raw & name
  18290. param = ""
  18291. inDQuote = FALSE
  18292. while not inDQuote and c != '>' and c != EOF do
  18293. if c = '"' then
  18294. inDQuote = TRUE
  18295. param = param & c
  18296. c = getc(in_file)
  18297. while inDQuote and c != EOF do
  18298. if c = '"' then
  18299. inDQuote = FALSE
  18300. elsif c = '\\' then  
  18301. param = param & c
  18302. c = getc(in_file) 
  18303. end if
  18304. param = param & c   
  18305. c = getc(in_file)   
  18306. end while
  18307. else
  18308. param = param & c
  18309. c = getc(in_file)
  18310. end if
  18311. end while
  18312. if inDQuote then       
  18313. quit("double quote never closed") 
  18314. elsif c = '>' then
  18315. param = param & '>'
  18316. raw = raw & param 
  18317. tag(name, param, raw)
  18318. elsif c = EOF then
  18319. quit("premature EOF")
  18320. end if
  18321. end if
  18322. else
  18323. tag("_literal", c, c)
  18324. end if
  18325. end while
  18326. end procedure
  18327. procedure main()
  18328. sequence cl, cl4
  18329. sequence in_name, out_name
  18330. integer p
  18331. cl = command_line()
  18332. if length(cl) <= 3 then
  18333. quit("usage: ex doc filename option\n\n" &
  18334. "         where option may be one of\n" &
  18335. "               RTF or HTML or PLAIN")
  18336. end if
  18337. cl4 = upper(cl[4])
  18338. if equal(cl4, "RTF") then
  18339. abort(1)
  18340. elsif equal(cl4, "HTML") then
  18341. html_init()
  18342. else         
  18343. text_init()
  18344. end if
  18345. in_name = upper(cl[3])
  18346. if not match(".HTX", in_name) then
  18347. quit("must be a .htx file")
  18348. end if
  18349. in_file = open(in_name, "r")
  18350. if in_file = -1 then
  18351. quit("couldn't open " & in_name)
  18352. end if
  18353. p = find('.', in_name)
  18354. out_name = in_name[1..p] & out_type
  18355. out_file = open(out_name, "w")
  18356. if out_file = -1 then
  18357. quit("couldn't open " & out_name)
  18358. end if
  18359. scan()
  18360. if equal(cl4, "PLAIN") then
  18361. text_end()
  18362. end if
  18363. close(in_file)
  18364. close(out_file)
  18365. end procedure
  18366. main()
  18367. DOCALL.BAT
  18368. 1953
  18369. echo creating REFMAN.HTM
  18370. ex doc refman.htx html
  18371. ex doc refman_1.htx html
  18372. ex doc refman_2.htx html
  18373. ex doc refman_3.htx html
  18374.  
  18375. echo creating REFMAN.DOC
  18376. ex doc refman.htx plain
  18377. ex doc refman_1.htx plain
  18378. ex doc refman_2.htx plain
  18379. ex doc refman_3.htx plain
  18380.  
  18381. echo creating LIBRARY.HTM
  18382. ex doc library.htx html
  18383. ex doc lib_A_B.HTX html
  18384. ex doc lib_C_D.HTX html
  18385. ex doc lib_E_G.HTX html
  18386. ex doc lib_H_O.HTX html
  18387. ex doc lib_P_R.HTX html
  18388. ex doc lib_S_T.HTX html
  18389. ex doc lib_U_Z.HTX html
  18390.  
  18391. echo creating LIBRARY.DOC
  18392. ex doc library.htx plain
  18393. ex doc lib_A_B.HTX plain
  18394. ex doc lib_C_D.HTX plain
  18395. ex doc lib_E_G.HTX plain
  18396. ex doc lib_H_O.HTX plain
  18397. ex doc lib_P_R.HTX plain
  18398. ex doc lib_S_T.HTX plain
  18399. ex doc lib_U_Z.HTX plain
  18400.  
  18401. ex combine
  18402. del refman*.doc
  18403. del lib*.doc
  18404.  
  18405. echo creating additional HTM files
  18406. ex doc readme.htx html
  18407. ex doc install.htx html
  18408. ex doc platform.htx html
  18409. ex doc ed.htx html
  18410. ex doc c.htx html
  18411. ex doc basic.htx html
  18412. ex doc relnotes.htx html
  18413. ex doc perform.htx html
  18414. ex doc bind.htx html
  18415. ex doc web.htx html
  18416. ex doc trouble.htx html
  18417. ex doc platform.htx html
  18418. ex doc overview.htx html
  18419. ex doc what2do.htx html
  18420. ex doc register.htx html
  18421.  
  18422. echo creating additional DOC files
  18423. ex doc readme.htx plain
  18424. ex doc install.htx plain
  18425. ex doc platform.htx plain
  18426. ex doc ed.htx plain
  18427. ex doc c.htx plain
  18428. ex doc basic.htx plain
  18429. ex doc relnotes.htx plain
  18430. ex doc perform.htx plain
  18431. ex doc bind.htx plain
  18432. ex doc web.htx plain
  18433. ex doc trouble.htx plain
  18434. ex doc platform.htx plain
  18435. ex doc overview.htx plain
  18436. ex doc what2do.htx plain
  18437. ex doc register.htx plain
  18438.  
  18439. move register.doc \euphoria\register > NUL
  18440.  
  18441. copy *.htm \euphoria\html > NUL
  18442. copy *.doc \euphoria\doc > NUL
  18443.  
  18444. del *.htm
  18445. del *.doc
  18446.  
  18447. move \euphoria\doc\readme.doc \euphoria > NUL
  18448. move \euphoria\html\readme.htm \euphoria > NUL
  18449.  
  18450. if exist \euphoria\htx\docall.bat goto done
  18451.  
  18452. del *.htx
  18453. del doc.ex
  18454. del html.e
  18455. del text.e
  18456. del docgen.e
  18457. del combine.ex
  18458.  
  18459. :done
  18460.  
  18461. DOCGEN.E
  18462. 01217
  18463. include \euphoria\include\get.e
  18464. global constant SCREEN = 1
  18465. global constant TRUE = 1, FALSE = 0, EOF = -1
  18466. global sequence out_type
  18467. global integer inPre, inEuCode, inTable
  18468. inPre    = FALSE
  18469. inEuCode = FALSE
  18470. inTable  = FALSE   
  18471. global integer in_file, out_file
  18472. global procedure quit(sequence msg)
  18473. puts(SCREEN, "ABORTED: " & msg & '\n')
  18474. abort(1)
  18475. end procedure
  18476. global function whitespace(integer c)
  18477. return find(c, " \n\t\r")
  18478. end function
  18479. global function all_white(sequence s)
  18480. for i = 1 to length(s) do
  18481. if not whitespace(s[i]) then
  18482. return FALSE
  18483. end if
  18484. end for
  18485. return TRUE
  18486. end function
  18487. global function pval(sequence pname, sequence plist)
  18488. for i = 1 to length(plist) do
  18489. if atom(plist[i][1]) then
  18490. if compare(pname, plist[i]) = 0 then
  18491. return TRUE
  18492. end if
  18493. else
  18494. if compare(pname, plist[i][1]) = 0 then
  18495. return plist[i][2]
  18496. end if
  18497. end if
  18498. end for
  18499. return FALSE
  18500. end function
  18501. global sequence handler_name, handler_id
  18502. handler_name = {}
  18503. handler_id = {}
  18504. global procedure add_handler(sequence tag_name, integer routine)
  18505. handler_name = prepend(handler_name, tag_name)
  18506. handler_id = prepend(handler_id, routine)
  18507. end procedure
  18508. global procedure write(object text)
  18509. puts(out_file, text)
  18510. end procedure
  18511. ED.HTX
  18512. 18180
  18513. <_init_comment>
  18514. <html>
  18515. <head><title>The Euphoria Editor</title>
  18516. </head>
  18517. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  18518. <_width>
  18519. <_center><font face="Arial, Helvetica" color="#FF0099" size=+2>
  18520. <br>
  18521.                           The Euphoria Editor
  18522. </font></_center>
  18523.  
  18524. <p> <br>
  18525. <b><font face="Arial, Helvetica" color="#003366">
  18526.  usage 1:   ed filename<br>
  18527.  usage 2:   ed
  18528. </font></b>
  18529.  
  18530. <p>
  18531. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  18532. <br>
  18533.  
  18534. <_sul>Summary</_sul>
  18535.  
  18536. </font>
  18537. <p>
  18538.  After any error, just type <font color="#993333"><_bq>ed</_bq></font>, and
  18539.  you'll be placed in the editor, at the line and column where the error was
  18540.  detected. The error message will be at the top of your screen.
  18541. <p>
  18542.  Euphoria-related files are
  18543.  displayed in color. Other text files are in mono. You'll know that you have
  18544.  misspelled something when the color does not change as you expect.
  18545.  Keywords are blue. Names of routines that are built in to the interpreter
  18546.  appear in magenta. Strings are
  18547.  green, comments are red, most other text is black. Balanced brackets (on the
  18548.  same line) have the same color. <b><font color="#006633">You can change
  18549.  these colors as well as several other parameters
  18550.  of</font> <font color="#993333">ed</font><font color="#006633">.</font></b>
  18551.  See "user-modifiable parameters" near the top of
  18552.  <font color="#5500FF"><b>ed.ex</b></font>.
  18553. <p>
  18554.  The arrow keys move the cursor left, right, up or down. Most other characters
  18555.  are immediately inserted into the file.
  18556. <p>
  18557.  In Windows, you can "associate" various types of files with
  18558.  <font color="#5500FF"><b>ed.bat</b></font>. You will then be put into
  18559.  <font color="#993333"><b>ed</b></font> when you <b>double-click</b>
  18560.  on these types of files - e.g. <b>.e</b>, <b>.pro</b>, <b>.doc</b> etc.
  18561.  Main Euphoria files ending in <b>.ex</b> (<b>.exw</b>) might better be
  18562.  associated with <font color="#993333"><_bq>ex.exe</_bq></font>
  18563.  (<font color="#993333"><_bq>exw.exe</_bq></font>).
  18564. <p>
  18565.  <font color="#993333"><b>ed</b></font> is a
  18566.  <font color="#CC0099"><b>multi-file/multi-window</b></font> editor.
  18567.  <b>Esc c</b> will split your screen so you can view and edit up to 10 files
  18568.  simultaneously, with cutting and pasting between them. You can also use
  18569.  multiple edit windows to view and edit different parts of a single file. 
  18570.  
  18571. <p>
  18572.  
  18573. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  18574. <br>
  18575.  
  18576. <_sul>Special Keys</_sul>
  18577. </font>
  18578.  
  18579. <P>Some keys do not work in a Linux text console, and some keys
  18580. do not work in an xterm under X windows. Alternate keys have been
  18581. provided.
  18582.  
  18583. <p>
  18584.  
  18585. <table border=0 cellspacing=2 cellpadding=2>
  18586.  
  18587. <_3clist
  18588.   name="<font color=\"#006699\">Delete</font>"
  18589.   pos=22
  18590.   description="Delete the current character above the cursor."
  18591.  >
  18592.  
  18593. <_3clist
  18594.   name="<font color=\"#006699\">Backspace</font>"
  18595.   pos=22
  18596.   description="Move the cursor to the left and delete a character."
  18597.  >
  18598.  
  18599. <_3clist
  18600.   name="<font color=\"#006699\">control-Delete</font>"
  18601.   pos=22
  18602.   description="Delete the current line. (<b>control-Delete</b> is not
  18603.    available on all systems.)"
  18604.  >
  18605.  
  18606. <_3clist
  18607.   name="<font color=\"#006699\">control-d</font>"
  18608.   pos=22
  18609.   description="Delete the current line. (same as <b>control-Delete</b>)"
  18610.  >
  18611.  
  18612. <_3clist
  18613.   name="<font color=\"#006699\">Insert</font>"
  18614.   pos=22
  18615.   description="Re-insert the preceding series of <b>Deletes</b> or
  18616.    <b>control-Deletes</b> before the current character or current line."
  18617.  >
  18618.  
  18619. <_3clist
  18620.   name="<font color=\"#006699\">control-arrow-left</font>"
  18621.   pos=26
  18622.   description="Move to the start of the previous word. On Linux use
  18623.    <b>control-L</b>."
  18624.  >
  18625.  
  18626. <_3clist
  18627.   name="<font color=\"#006699\">control-arrow-right</font>"
  18628.   pos=26
  18629.   description="Move to the start of the next word. On Linux use 
  18630.     <b>control-R</b>."
  18631.  >
  18632.  
  18633. <_3clist
  18634.   name="<font color=\"#006699\">Home</font>"
  18635.   pos=22
  18636.   description="Move to the beginning of the current line."
  18637.  >
  18638.  
  18639. <_3clist
  18640.   name="<font color=\"#006699\">End</font>"
  18641.   pos=22
  18642.   description="Move to the end of the current line."
  18643.  >
  18644.  
  18645. <_3clist
  18646.   name="<font color=\"#006699\">control-Home</font>"
  18647.   pos=22
  18648.   description="Move to the beginning of the file. On Linux use
  18649.   <b>control-T</b> (i.e. Top)"
  18650.  >
  18651.  
  18652. <_3clist
  18653.   name="<font color=\"#006699\">control-End</font>"
  18654.   pos=22
  18655.   description="Move to the end of the file. On Linux use <b>control-B</b>, 
  18656.   (i.e. Bottom)"
  18657.  >
  18658.  
  18659. <_3clist
  18660.   name="<font color=\"#006699\">Page Up</font>"
  18661.   pos=22
  18662.   description="Move up one screen. In a Linux xterm use <b>control-U</b>"
  18663.  >
  18664.  
  18665. <_3clist
  18666.   name="<font color=\"#006699\">Page Down</font>"
  18667.   pos=22
  18668.   description="Move down one screen. In a Linux xterm use <b>control-P</b>"
  18669.  >
  18670.  
  18671. <_3clist
  18672.   name="<font color=\"#006699\">F1 ... F10</font>"
  18673.   pos=22
  18674.   description="Select a new current window. The windows are numbered from top
  18675.    to bottom, with the top window on the screen being <b>F1</b>."
  18676.  >
  18677.  
  18678. <_3clist
  18679.   name="<font color=\"#006699\">F12</font>"
  18680.   pos=22
  18681.   description="This is a special
  18682.    <font color=\"#CC0099\"><b>customizable command</b></font>. It is set up
  18683.    to insert a Euphoria comment mark \"--\" at the start of the current line.
  18684.    You can easily <font color=\"#006633\"><b>change it to perform any series
  18685.    of key strokes that you like</b></font>, simply by redefining
  18686.    constant CUSTOM_KEYSTROKES near the top of
  18687.    <font color=\"#5500FF\"><b>ed.ex</b></font>."
  18688.  >
  18689.  
  18690. </table>
  18691.  
  18692.  
  18693. <p>
  18694.  
  18695. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  18696. <br>
  18697.  
  18698. <_sul>Escape Commands</_sul>
  18699.  
  18700. </font>
  18701. <p>
  18702.  Press and release the <font color="#006699"><b>Esc</b></font> key, then
  18703.  press one of the following keys:
  18704.  
  18705. <p>
  18706. <table border=0 cellspacing=2 cellpadding=2>
  18707.  
  18708. <_3clist
  18709.   name="<font color=\"#006699\">h</font>"
  18710.   pos=8
  18711.   description="Get help text for the editor, or Euphoria. The screen is split
  18712.    so you can view your program and the help text at the same time."
  18713.  >
  18714.  
  18715. <_3clist
  18716.   name="<font color=\"#006699\">c</font>"
  18717.   pos=8
  18718.   description="\"Clone\" the current window, i.e. make a new edit window that
  18719.    is initially viewing the same file at the same position as the current
  18720.    window. The sizes of all windows are adjusted to make room for the new
  18721.    window. You might want to use <b>Esc l</b> to get more lines on the screen.
  18722.    Each window that you create can be scrolled independently and each has its
  18723.    own menu bar. The changes that you make to a file will initially appear
  18724.    only in the current window. When you press an <b>F-key</b> to select a new
  18725.    window, any changes will appear there as well. You can use <b>Esc n</b> to
  18726.    read a new file into any window."
  18727.  >
  18728.  
  18729. <_3clist
  18730.   name="<font color=\"#006699\">q</font>"
  18731.   pos=8
  18732.   description="Quit (delete) the current window and leave the editor if there
  18733.    are no more windows. You'll be warned if this is the last window used for
  18734.    editing a modified file. Any remaining windows are given more space."
  18735.  >
  18736.  
  18737. <_3clist
  18738.   name="<font color=\"#006699\">s</font>"
  18739.   pos=8
  18740.   description="Save the file being edited in the current window, then quit the
  18741.    current window as <b>Esc q</b> above."
  18742.  >
  18743.  
  18744. <_3clist
  18745.   name="<font color=\"#006699\">w</font>"
  18746.   pos=8
  18747.   description="Save the file but do not quit the window."
  18748.  >
  18749.  
  18750. <_3clist
  18751.   name="<font color=\"#006699\">e</font>"
  18752.   pos=8
  18753.   description="Save the file, and then execute it with
  18754.    <font color=\"#993333\"><b>ex</b></font>,
  18755.    <font color=\"#993333\"><b>exw</b></font> or
  18756.    <font color=\"#993333\"><b>exu</b></font>. When the program finishes
  18757.    execution you'll hear a beep. Hit <b>Enter</b> to return to the editor.
  18758.    This operation may not work if you are very low on extended memory. You
  18759.    can't supply any
  18760.    <font color=\"#993333\"><b>command-line arguments</b></font> to the
  18761.    program."
  18762.  >
  18763.  
  18764. <_3clist
  18765.   name="<font color=\"#006699\">d</font>"
  18766.   pos=8
  18767.   description="Run an operating system command. After the beep, hit <b>Enter</b> to return
  18768.    to the editor. You could also use this command to edit another file and
  18769.    then return, but <b>Esc c</b> is probably more convenient."
  18770.  >
  18771.  
  18772. <_3clist
  18773.   name="<font color=\"#006699\">n</font>"
  18774.   pos=8
  18775.   description="Start editing a new file in the current window. Deleted
  18776.    lines/chars and search strings are available for use in the new file.
  18777.    You must type in the path to the new file. Alternatively, you can drag a
  18778.    file name from a Windows file manager window into the MS-DOS window for
  18779.    <font color=\"#993333\"><b>ed</b></font>. This will type the full path for
  18780.    you."
  18781.  >
  18782.  
  18783. <_3clist
  18784.   name="<font color=\"#006699\">f</font>"
  18785.   pos=8
  18786.   description="Find the next occurrence of a string in the current window.
  18787.    When you type in a new string there is an option to \"match case\" or not.
  18788.    Press <b>y</b> if you require upper/lower case to match. Keep hitting
  18789.    <b>Enter</b> to find subsequent occurrences. Any other key stops the
  18790.    search. To search from the beginning, press <b>control-Home</b> before
  18791.    <b>Esc f</b>. The default string to search for, if you don't type anything,
  18792.    is shown in double quotes."
  18793.  >
  18794.  
  18795. <_3clist
  18796.   name="<font color=\"#006699\">r</font>"
  18797.   pos=8
  18798.   description="Globally replace one string by another. Operates like
  18799.   <b>Esc f</b> command. Keep hitting <b>Enter</b> to continue replacing.
  18800.   Be careful -- <i>there is no way to skip over a possible replacement.</i>"
  18801.  >
  18802.  
  18803. <_3clist
  18804.   name="<font color=\"#006699\">l</font>"
  18805.   pos=8
  18806.   description="Change the number of lines displayed on the screen. Only
  18807.    certain values are allowed, depending on your video card. Many cards will
  18808.    allow 25, 28, 43 and 50 lines. <p>In a Linux text console you're stuck 
  18809.    with the number of lines available (usually 25). In a Linux xterm
  18810.    window, <b>ed</b> will use the number of lines initially available when
  18811.    ed is started up. Changing the size of the window will have no effect
  18812.    after ed is started."
  18813.  >
  18814.  
  18815. <_3clist
  18816.   name="<font color=\"#006699\">m</font>"
  18817.   pos=8
  18818.   description="Show the modifications that you've made so far. The current
  18819.    edit buffer is saved as <font color=\"#993333\"><b>editbuff.tmp</b></font>,
  18820.    and is compared with the file on disk using the DOS <b>fc</b> command,
  18821.    or the Linux <b>diff</b> command.
  18822.    <b>Esc m</b> is very useful when you want to quit the editor, but you
  18823.    can't remember what changes you made, or whether it's ok to save them.
  18824.    It's also useful when you make an editing mistake and you want to see what
  18825.    the original text looked like. When you quit the editor, you will be given
  18826.    a chance to delete <font color=\"#993333\"><b>editbuff.tmp</b></font>."
  18827.  >
  18828.  
  18829. <_3clist
  18830.   name="<font color=\"#006699\"><i>ddd</i></font>"
  18831.   pos=8
  18832.   description="Move to line number <i>ddd</i>. e.g. <b>Esc 1023 Enter</b>
  18833.    would move to line 1023 in the file."
  18834.  >
  18835.  
  18836. <_3clist
  18837.   name="<font color=\"#006699\">CR</font>"
  18838.   pos=8
  18839.   description="<b>Esc Carriage-Return</b>, i.e. <b>Esc Enter</b>, will
  18840.    tell you the name of the current file, as well as the line and character
  18841.    position you are on, and whether the file has been modified since the last
  18842.    save. If you press <b>Esc</b> and then change your mind, it is harmless
  18843.    to just hit <b>Enter</b> so you can go back to editing."
  18844.  >
  18845.  
  18846. </table>
  18847.  
  18848. <p>
  18849.  
  18850. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  18851. <br>
  18852.  
  18853. <_sul>Recalling Previous Strings</_sul>
  18854.  
  18855. </font>
  18856. <p>
  18857. The <b>Esc n</b>, <b>Esc d</b>, <b>Esc r</b> and <b>Esc f</b> commands
  18858. prompt you to enter a string. You can recall and edit these strings
  18859. just as you would at the DOS or Linux command line. Type up-arrow or
  18860. down-arrow to cycle through strings that you previously entered for
  18861. a given command, then use left-arrow, right-arrow and the delete key to
  18862. edit the strings. Press Enter to submit the string.
  18863.  
  18864. <p>
  18865.  
  18866. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  18867. <br>
  18868.  
  18869. <_sul>Cutting and Pasting</_sul>
  18870.  
  18871. </font>
  18872. <p>
  18873.  When you <font color="#006699"><b>control-Delete</b></font> 
  18874.  (or <font color="#006699"><b>control-D</b></font>)
  18875.  a series of
  18876.  consecutive lines, or <font color="#006699"><b>Delete</b></font> a series
  18877.  of consecutive characters, you create a "kill-buffer" containing what you
  18878.  just deleted. This kill-buffer can be re-inserted by moving the cursor and
  18879.  then pressing <font color="#006699"><b>Insert</b></font>.
  18880. <p>
  18881.  A new kill-buffer is started, and the old buffer is lost, each time you move
  18882.  away and start deleting somewhere else. For example, cut a series of
  18883.  <_ba><i>lines</i></_ba> with
  18884.  <font color="#006699"><b>control-Delete</b></font>. Then move the
  18885.  cursor to where you want to paste the lines and press
  18886.  <font color="#006699"><b>Insert</b></font>. If you want to copy the lines,
  18887.  without destroying the original text, first
  18888.  <font color="#006699"><b>control-Delete</b></font> them, then immediately
  18889.  press <font color="#006699"><b>Insert</b></font> to re-insert them. Then
  18890.  move somewhere else and press <font color="#006699"><b>Insert</b></font> to
  18891.  insert them again, as many times as you like. You can also
  18892.  <font color="#006699"><b>Delete</b></font> a series of individual
  18893.  <_ba><i>characters</i></_ba>, move the cursor, and then paste the deleted
  18894.  characters somewhere else. Immediately press
  18895.  <font color="#006699"><b>Insert</b></font> after deleting if you want to
  18896.  copy without removing the original characters.
  18897. <p>
  18898.  Once you have a kill-buffer, you can type
  18899.  <font color="#006699"><b>Esc n</b></font> to read in a new file, or you can
  18900.  press an <font color="#006699"><b>F-key</b></font> to select a new edit
  18901.  window. You can then insert your kill-buffer.
  18902.  
  18903. <p>
  18904.  
  18905. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  18906. <br>
  18907.  
  18908. <_sul>Use of Tabs</_sul>
  18909.  
  18910. </font>
  18911. <p>
  18912.  The standard <i>tab</i> width is 8 spaces. The editor assumes
  18913.  tab=8 for most files. However, it is more convenient when editing a
  18914.  program for a tab to equal the amount of space that you like to indent.
  18915.  Therefore you will find that tabs are set to 4 when you edit Euphoria files
  18916.  (or .c, or .h or .bas files). The editor converts from tab=8 to tab=4 when
  18917.  reading your <i>program</i> file, and converts back to tab=8 when you save
  18918.  the file. Thus your file remains compatible with the tab=8 world, e.g.
  18919.  MS-DOS PRINT, EDIT, etc. <font color="#006633"><b>If you would like to
  18920.  choose a different number of spaces to indent</b></font>, change the line
  18921.  at the top of <font color="#5500FF"><b>ed.ex</b></font> that says "constant
  18922.  PROG_INDENT = 4".
  18923.  
  18924. <p>
  18925.  
  18926. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  18927. <br>
  18928.  
  18929. <_sul>Long Lines</_sul>
  18930.  
  18931. </font>
  18932. <p>
  18933.  Lines that extend beyond the right edge of the screen are marked with an 
  18934.  <i>inverse video</i> character in the 80th column. This warns you that
  18935.  there is more text "out there" that you can't see. You can move the cursor
  18936.  beyond the 80th column. The screen will scroll left or right so the cursor
  18937.  position is always visible.
  18938.  
  18939. <p>
  18940.  
  18941. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  18942. <br>
  18943.  
  18944. <_sul>Maximum File Size</_sul>
  18945.  
  18946. </font>
  18947. <p>
  18948.  Like any Euphoria program, <font color="#993333"><b>ed</b></font> can use
  18949.  extended memory. It will edit files that are
  18950.  <font color="#CC0099"><b><i>much</i></b></font> larger than what
  18951.  MS-DOS EDIT or Windows Notepad can handle.
  18952.  With a huge file, inserting or deleting a line near the beginning of the file
  18953.  might take several seconds, due to intense swapping activity. Other 
  18954.  operations should be reasonably quick.
  18955.  
  18956. <p>
  18957.  
  18958. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  18959. <br>
  18960.  
  18961. <_sul>Non-text Files</_sul>
  18962.  
  18963. </font>
  18964. <p>
  18965.  <font color="#993333"><b>ed</b></font> is designed for editing pure text
  18966.  files, although you can use it to view other files. As
  18967.  <font color="#993333"><b>ed</b></font> reads in a file, it replaces certain
  18968.  non-printable characters (less than ASCII 14) with ASCII 254 - small square.
  18969.  <i>If you try to save a non-text file you will be warned about this.</i>
  18970.  (MS-DOS EDIT will quietly corrupt a non-text file - do not save!).
  18971.  Since <font color="#993333"><b>ed</b></font> opens all files as "text" files,
  18972.  the <b>control-z</b> character (26) will appear to be the <i>end of the
  18973.  file</i>.
  18974.  
  18975. <p>
  18976.  
  18977. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  18978. <br>
  18979.  
  18980. <_sul>Windows 95/98 Long Filenames</_sul>
  18981.  
  18982. </font>
  18983. <p>
  18984.  You can edit <i>existing</i> files that have pathnames with long names in
  18985.  them, and the full file name will be preserved. However in this release
  18986.  <font color="#993333"><b>ed</b></font> will not create
  18987.  <_ba><i>new</i></_ba> files with long names. The name will be
  18988.  truncated to the standard DOS 8.3 length.
  18989.  
  18990. <p>
  18991.  
  18992. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  18993. <br>
  18994. <_sul>Line Terminator</_sul>
  18995.  
  18996. </font>
  18997. <p>
  18998.  The end-of-line terminator on Linux is simply <b>\n</b>. On DOS
  18999.  and Windows, text files have lines ending with <b>\r\n</b>.
  19000.  If you copy a DOS or Windows file to Linux and try to modify it,
  19001.  <b>ed</b> will give you a choice of either keeping the <b>\r\n</b> terminators,
  19002.  or saving the file with <b>\n</b> terminators.
  19003.  
  19004. <p>
  19005.  
  19006. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  19007. <br>
  19008.  
  19009. <_sul>Source Code</_sul>
  19010.  
  19011. </font>
  19012. <p>
  19013.  The complete source code to this editor is in
  19014.  <font color="#5500FF"><b>bin\ed.ex</b></font> and
  19015.  <font color="#5500FF"><b>bin\syncolor.e</b></font>. 
  19016.  You are welcome to make improvements. There is a section at the top of
  19017.  <font color="#5500FF"><b>ed.ex</b></font> containing "user-modifiable"
  19018.  configuration parameters that you can adjust. The colors and the cursor
  19019.  size may need adjusting for some operating environments.
  19020.  
  19021. <p>
  19022.  
  19023. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  19024. <br>
  19025.  
  19026. <_sul>Platform</_sul>
  19027.  
  19028. </font>
  19029. <p>
  19030.  <font color="#993333"><b>ed</b></font> runs best with
  19031.  <font color="#993333"><b>ex.exe</b></font> or
  19032.  <font color="#993333"><b>exu</b></font>, 
  19033.  but will also run with
  19034.  <font color="#993333"><b>exw.exe</b></font>.
  19035.  
  19036. <p> 
  19037.  
  19038. </_width>
  19039. </body>
  19040. </html>
  19041.  
  19042. HTML.E
  19043. 11758
  19044. include \euphoria\include\wildcard.e
  19045. global constant NORMAL_COLOR  = #330033,
  19046. COMMENT_COLOR = #FF0055,
  19047. KEYWORD_COLOR = #0000FF,
  19048. BUILTIN_COLOR = #FF00FF,
  19049. STRING_COLOR  = #00A033,
  19050. BRACKET_COLOR = {NORMAL_COLOR, #993333,
  19051. #0000FF, #5500FF, #00FF00}
  19052. include \euphoria\bin\keywords.e
  19053. include \euphoria\bin\syncolor.e
  19054. constant YEAR_DELIMITER = 90, SINCE_YEAR = 1900
  19055. integer blank
  19056. blank = FALSE
  19057. sequence line, colorLine                
  19058. integer firstLine, in2clist, in3clist   
  19059. procedure tag_init_comment(sequence raw_text, sequence plist)
  19060. write("<!-- GENERATED BY A EUPHORIA PROGRAM. DO NOT EDIT! -->\n\n")
  19061. end procedure
  19062. procedure tag_width(sequence raw_text, sequence plist)
  19063. write("<table width=90% border=0><tr><td>\n")
  19064. end procedure
  19065. procedure tag_end_width(sequence raw_text, sequence plist)
  19066. write("</td></tr></table>\n")
  19067. end procedure
  19068. procedure tag_literal(integer raw_text, sequence param_list)
  19069. integer color
  19070. sequence text
  19071. if inEuCode then
  19072. line = line & raw_text
  19073. if raw_text = '\n' then
  19074. if firstLine then
  19075. if inTable then
  19076. if in2clist then
  19077. write("<tr><td></td><td>\n")
  19078. elsif in3clist then
  19079. write("<tr><td></td><td></td><td>\n")
  19080. else
  19081. write("<tr><td></td><td></td><td></td><td>\n")
  19082. end if
  19083. end if
  19084. firstLine = FALSE
  19085. write("<pre>")
  19086. if all_white(line) then
  19087. line = ""
  19088. return
  19089. end if
  19090. end if
  19091. colorLine = SyntaxColor(line)
  19092. for i = 1 to length(colorLine) do
  19093. color = colorLine[i][1]
  19094. text  = colorLine[i][2]
  19095. write("<font color=\"#" & sprintf("%06x", color) & "\">")
  19096. write(text & "</font>")
  19097. end for
  19098. write("\n")
  19099. line = ""
  19100. end if
  19101. else
  19102. if not inPre then
  19103. if blank and raw_text = ' ' then
  19104. return
  19105. end if
  19106. blank = raw_text = ' '
  19107. end if
  19108. write(raw_text)
  19109. end if
  19110. end procedure
  19111. procedure tag_dul(sequence raw_text, sequence param_list)
  19112. end procedure
  19113. procedure tag_end_dul(sequence raw_text, sequence param_list)
  19114. end procedure
  19115. procedure tag_sul(sequence raw_text, sequence param_list)
  19116. end procedure
  19117. procedure tag_end_sul(sequence raw_text, sequence param_list)
  19118. end procedure
  19119. procedure tag_comment(sequence raw_text, sequence param_list)
  19120. end procedure
  19121. procedure tag_default(sequence raw_text, sequence param_list)
  19122. write(raw_text)
  19123. end procedure
  19124. function recent(sequence the_date)
  19125. sequence f3
  19126. integer month_num, i, j
  19127. sequence current_date
  19128. f3 = lower(the_date[1..3])
  19129. month_num = find(f3, {"jan", "feb", "mar", "apr", "may", "jun",
  19130. "jul", "aug", "sep", "oct", "nov", "dec"})
  19131. i = find('/', the_date)
  19132. f3 = value(the_date[i + 1..i + 2])
  19133. if month_num = 0 or i = 0 or f3[1] != GET_SUCCESS then
  19134. quit("bad date")
  19135. end if
  19136. i = f3[2]
  19137. if i > YEAR_DELIMITER then
  19138. i = (SINCE_YEAR + i) * 12 + month_num
  19139. else
  19140. i = (2000 + i) * 12 + month_num      
  19141. end if
  19142. current_date = date()
  19143. j = (current_date[1] + SINCE_YEAR) * 12 + current_date[2]
  19144. if j - i <= 1 then
  19145. return TRUE
  19146. else
  19147. return FALSE
  19148. end if
  19149. end function
  19150. procedure tag_recent(sequence raw_text, sequence plist)    
  19151. sequence the_date
  19152. integer recent_update
  19153. object result
  19154. write("<tr><td></td><td valign=top rowspan=3>")
  19155. write("<img width=32 height=32 src=\"f" & pval("color", plist))
  19156. write(".gif\"></td><td>\n<a href=\"" & pval("href", plist) & "\">")
  19157. write("<font face=\"Arial\" size=2>")
  19158. write("<b>" & pval("title", plist) & "</b></font></a></td>\n")
  19159. write("<td align=right><font face=\"Arial\" size=2>")
  19160. write(pval("size", plist) & "K</font></td>\n")
  19161. write("<td align=right><font face=\"Arial\" size=2>")
  19162. the_date = pval("date", plist)
  19163. if not equal(0, pval("updated", plist)) then
  19164. recent_update = recent(the_date)
  19165. if recent_update then
  19166. write("<font color=\"#0066CC\">updated </font>")
  19167. else 
  19168. write("updated ")
  19169. end if
  19170. end if
  19171. write(the_date)
  19172. write("</font></td>\n")
  19173. write("<td></td><td>")
  19174. result = pval("money", plist)
  19175. if sequence(result) and length(result) != 0 then
  19176. write("<img src=\"happy.gif\" width=17 height=17 align=top>" &
  19177. "<font face=\"Arial\" size=2> " & result & "</font>\n") 
  19178. end if
  19179. write("</td>")
  19180. if equal(TRUE, pval("stamped", plist)) then
  19181. write("<td align=right><img src=\"stamp.gif\" width=51 height=17>" &
  19182. "</td>")
  19183. else
  19184. write("<td></td>")
  19185. end if
  19186. write("</tr>\n")
  19187. write("<tr><td></td><td colspan=6 height=6>")
  19188. write("<img height=1 width=565 src=\"l.gif\"></td></tr>\n") 
  19189. write("<tr><td></td><td colspan=6><font face=\"Arial\" size=2>")
  19190. write("<b>" & pval("name", plist) & "</b>\n")     -- '\n' meaningful
  19191. write(pval("description", plist) & '\n')          -- '\n' meaningful
  19192. result = pval("update_description", plist) 
  19193. if sequence(result) and length(result) != 0 then
  19194. write(result)
  19195. end if
  19196. write("</font></td></tr>")
  19197. write("<tr><td colspan=8><font size=5> </font></td></tr>\n")
  19198. end procedure
  19199. procedure tag_archive(sequence raw_text, sequence plist)    
  19200. object result
  19201. integer updated
  19202. if equal("red", pval("color", plist)) then
  19203. write("<tr bgcolor=\"#FFCCCC\">")
  19204. else
  19205. write("<tr bgcolor=\"#CCCCFF\">")
  19206. end if
  19207. write("<td><font face=\"Arial\" size=2>\n" &
  19208. " <a href=\"" & pval("href", plist) & "\">")
  19209. write("<b>" & pval("title", plist) & "</b></a></font></td>\n")
  19210. write("<td align=right><font face=\"Arial\" size=2>" &
  19211. pval("size", plist) & "K</font></td>")
  19212. write("<td align=center><font face=\"Arial\" size=2><b>" &
  19213. pval("name", plist) & "</b></font></td>\n")
  19214. result = pval("date", plist)
  19215. updated = FALSE
  19216. if sequence(result) and length(result) > 0 then
  19217. write("<td><font face=\"Arial\" size=2>")
  19218. if not equal(0, pval("updated", plist)) then
  19219. updated = TRUE
  19220. if recent(result) then
  19221. write("<font color=\"#5500FF\">updated</font> " & result)
  19222. else
  19223. write("updated " & result)
  19224. end if
  19225. else
  19226. write(result)
  19227. end if
  19228. write("</font></td>\n")
  19229. else
  19230. write("<td> </td>")
  19231. end if
  19232. result = pval("money", plist)
  19233. if (atom(result) or length(result) = 0) and
  19234. equal(FALSE, pval("stamped", plist)) then
  19235. write("<td colspan=2> </td></tr>\n")  -- this way saves some bytes
  19236. else
  19237. if sequence(result) and length(result) > 0 then
  19238. write("<td><img src=\"happy.gif\" width=17 height=17>" &
  19239. "<font face=\"Arial\" size=2> " &
  19240. result & "</font></td>")
  19241. else
  19242. write("<td> </td>")
  19243. end if
  19244. if equal(TRUE, pval("stamped", plist)) then
  19245. write("<td align=right><img src=\"stamp.gif\" width=51 height=17>" &
  19246. "</td></tr>\n")
  19247. else
  19248. write("<td> </td></tr>\n")
  19249. end if
  19250. end if
  19251. write("<tr><td colspan=6><font face=\"Arial\" size=2>" &
  19252. pval("description", plist) & "\n")                 -- '\n' meaningful
  19253. if updated then
  19254. result = pval("update_description", plist) 
  19255. if sequence(result) and length(result) != 0 then
  19256. write("Update: " & result)
  19257. end if
  19258. end if
  19259. write("</font></td></tr>")
  19260. write("<tr><td colspan=6> </td></tr>\n")
  19261. end procedure
  19262. procedure common3_4clist(sequence raw_text, sequence plist)
  19263. object temp
  19264. in2clist = FALSE
  19265. temp = pval("href", plist)
  19266. if sequence(temp) and length(temp) > 0 then
  19267. write("<a href=\"" & temp & "\">")
  19268. write("<b>" & pval("name", plist) & "</b></a></td>\n")
  19269. else
  19270. write("<b>" & pval("name", plist) & "</b></td>\n")
  19271. end if
  19272. if in3clist then
  19273. write("<td width=10 align=center valign=top>-</td>")
  19274. else
  19275. temp = pval("col3", plist)
  19276. if sequence(temp) then
  19277. write("<td align=center valign=top>" & temp & "</td>")
  19278. else
  19279. write("<td width=10 align=center valign=top>-</td>")
  19280. end if
  19281. end if
  19282. write("\n<td>" & pval("description", plist) & "</td></tr>\n")
  19283. end procedure
  19284. procedure tag_4clist(sequence raw_text, sequence plist)    
  19285. in3clist = FALSE
  19286. write("<tr><td width=24 nowrap></td><td valign=top>")
  19287. common3_4clist(raw_text, plist)
  19288. end procedure
  19289. procedure tag_3clist(sequence raw_text, sequence plist)    
  19290. in3clist = TRUE
  19291. write("<tr><td valign=top>")
  19292. common3_4clist(raw_text, plist)
  19293. end procedure
  19294. procedure tag_2clist(sequence raw_text, sequence plist)    
  19295. in2clist = TRUE
  19296. in3clist = FALSE
  19297. write("<tr><td valign=top>")
  19298. write("<b>" & pval("name", plist) & "</b></td>\n")
  19299. write("<td>" & pval("description", plist) & "\n")
  19300. write("</td></tr>\n")
  19301. end procedure
  19302. procedure tag_routine(sequence raw_text, sequence plist)    
  19303. sequence name       
  19304. name = pval("name", plist)
  19305. write("<a name=" & name & "></a><font color=\"#006633\" size=+2><br>\n")
  19306. write("<center><b>" & name & "</b></center>\n")
  19307. write("</font><p>\n")
  19308. end procedure
  19309. procedure tag_table(sequence raw_text, sequence plist)
  19310. inTable = TRUE
  19311. in2clist = FALSE
  19312. in3clist = FALSE
  19313. write(raw_text)
  19314. end procedure
  19315. procedure tag_end_table(sequence raw_text, sequence plist)
  19316. inTable = FALSE
  19317. write(raw_text)
  19318. end procedure
  19319. procedure tag_pre(sequence raw_text, sequence plist)
  19320. inPre = TRUE
  19321. write(raw_text)
  19322. end procedure
  19323. procedure tag_end_pre(sequence raw_text, sequence plist)
  19324. inPre = FALSE
  19325. blank = FALSE
  19326. write(raw_text)
  19327. end procedure
  19328. procedure tag_eucode(sequence raw_text, sequence plist)
  19329. inEuCode = TRUE
  19330. firstLine = TRUE
  19331. line = ""
  19332. end procedure
  19333. procedure tag_end_eucode(sequence raw_text, sequence plist)
  19334. inEuCode = FALSE
  19335. blank = FALSE
  19336. write("</pre>")
  19337. if inTable then
  19338. write("</td></tr>\n")
  19339. end if          
  19340. end procedure
  19341. procedure tag_center(sequence raw_text, sequence plist)
  19342. write("<center>")
  19343. end procedure
  19344. procedure tag_end_center(sequence raw_text, sequence plist)
  19345. write("</center>")
  19346. end procedure
  19347. procedure tag_bq(sequence raw_text, sequence plist)
  19348. write("<b>")
  19349. end procedure
  19350. procedure tag_end_bq(sequence raw_text, sequence plist)
  19351. write("</b>")
  19352. end procedure
  19353. procedure tag_bsq(sequence raw_text, sequence plist)
  19354. write("<b>")
  19355. end procedure
  19356. procedure tag_end_bsq(sequence raw_text, sequence plist)
  19357. write("</b>")
  19358. end procedure
  19359. procedure tag_ba(sequence raw_text, sequence plist)
  19360. write("<b>")
  19361. end procedure
  19362. procedure tag_end_ba(sequence raw_text, sequence plist)
  19363. write("</b>")
  19364. end procedure
  19365. procedure tag_continue(sequence raw_text, sequence plist)
  19366. object temp
  19367. write("<p> <p><center>\n")
  19368. write("<font color=\"#006633\" face=\"Arial, Helvetica\" size=+1>" &
  19369. "... continue \n")
  19370. temp = pval("href", plist)
  19371. if sequence(temp) and not equal(temp, "") then
  19372. write("<a href=\"" & temp & "\">" &
  19373. pval("name", plist) & "</a></font>\n</center>\n<p> \n")
  19374. else
  19375. quit("no href data given in <_continue> tag")
  19376. end if
  19377. end procedure
  19378. global procedure html_init()
  19379. add_handler("_recent",  routine_id("tag_recent"))
  19380. add_handler("_archive", routine_id("tag_archive"))
  19381. add_handler("_init_comment", routine_id("tag_init_comment"))
  19382. add_handler("_width",   routine_id("tag_width"))
  19383. add_handler("/_width",  routine_id("tag_end_width"))
  19384. add_handler("_continue",routine_id("tag_continue"))
  19385. add_handler("_bsq",     routine_id("tag_bsq"))
  19386. add_handler("/_bsq",    routine_id("tag_end_bsq"))
  19387. add_handler("!--",      routine_id("tag_comment"))
  19388. add_handler("_center",  routine_id("tag_center"))
  19389. add_handler("/_center", routine_id("tag_end_center"))
  19390. add_handler("pre",      routine_id("tag_pre"))
  19391. add_handler("/pre",     routine_id("tag_end_pre"))
  19392. add_handler("_dul",     routine_id("tag_dul"))
  19393. add_handler("/_dul",    routine_id("tag_end_dul"))
  19394. add_handler("_sul",     routine_id("tag_sul"))
  19395. add_handler("/_sul",    routine_id("tag_end_sul"))
  19396. add_handler("_bq",      routine_id("tag_bq"))
  19397. add_handler("/_bq",     routine_id("tag_end_bq"))
  19398. add_handler("_ba",      routine_id("tag_ba"))
  19399. add_handler("/_ba",     routine_id("tag_end_ba"))
  19400. add_handler("_routine", routine_id("tag_routine"))
  19401. add_handler("table",    routine_id("tag_table"))
  19402. add_handler("/table",   routine_id("tag_end_table"))
  19403. add_handler("_eucode",  routine_id("tag_eucode"))
  19404. add_handler("/_eucode", routine_id("tag_end_eucode"))
  19405. add_handler("_4clist",  routine_id("tag_4clist"))
  19406. add_handler("_3clist",  routine_id("tag_3clist"))
  19407. add_handler("_2clist",  routine_id("tag_2clist"))
  19408. add_handler("_default", routine_id("tag_default"))
  19409. add_handler("_literal", routine_id("tag_literal"))
  19410. out_type = "htm"
  19411. init_class()     
  19412. end procedure
  19413. INSTALL.HTX
  19414. 5844
  19415. <_init_comment>
  19416. <html>
  19417. <head><title>How to Install Euphoria</title>
  19418. </head>
  19419. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  19420. <_width>
  19421. <_center><font face="Arial, Helvetica" color="#FF0099" size=+2>
  19422. <br>
  19423.                         How to Install Euphoria on DOS/Windows
  19424. </font></_center>
  19425.  
  19426. <p> <br>
  19427. <font face="Arial, Helvetica" color="#003366">
  19428. <b><_sul>To install Euphoria you need:</_sul></b></font>
  19429.  
  19430. <ul>
  19431. <li>
  19432.      a 386 or higher PC
  19433. <p>
  19434. <li>
  19435.      at least 640K of memory
  19436. <p>
  19437. <li>
  19438.      5 Mb of free hard disk space
  19439. </ul>
  19440.  
  19441. <p>
  19442.  
  19443. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  19444. <br>
  19445.  
  19446. <_dul>The Install Procedure</_dul>
  19447.  
  19448. </font>
  19449. <pre>
  19450.      1. <b>cd</b> into the directory containing the Euphoria files
  19451.  
  19452.      2. type: 
  19453.               <font color="#993333"><b>install</b></font>
  19454. </pre>
  19455.  
  19456.  If you have downloaded Euphoria and pkunzip'd in (say) <b>c:\tmp</b> you
  19457.  would type:
  19458. <pre>
  19459.      cd c:\tmp
  19460.      install
  19461. </pre>
  19462.  
  19463.  If you happen to have unzipped into <b>C:\EUPHORIA</b>, that's fine,
  19464.  <b>cd</b> into it and type: <font color="#993333"><b>install</b></font>
  19465. <p>
  19466.  You can also install under <font color="#CC3366"><b>Windows</b></font> by
  19467.  double-clicking on <font color="#5500FF"><b>install.bat</b></font>
  19468. <p>
  19469.  You will be asked which drive to put the
  19470.  <font color="#993333"><b>EUPHORIA directory</b></font> on. Later you will
  19471.  be asked to approve any changes to your <b>autoexec.bat</b> file. Finally,
  19472.  <_ba>you need to shut down and restart (soft-reboot) your computer</_ba> 
  19473.  so the new <b>autoexec.bat</b> will take effect.
  19474. <p>
  19475.  After installing, see <font color="#5500FF"><b>doc\what2do.doc</b></font>
  19476.  (or <a href="what2do.htm"><b>html\what2do.htm</b></a>) for ideas on how
  19477.  to use this package. You should also read
  19478.  <font color="#5500FF"><b>readme.doc</b></font> (or
  19479.  <font color="#006699"><b>readme.htm</b></font>) if you haven't done so
  19480.  already.
  19481. <p>
  19482. <table border=0 cellspacing=2 cellpadding=2>
  19483.  
  19484. <_2clist
  19485.   name=""
  19486.   pos=16
  19487.   description="<font face = \"Comic Sans MS\" color=\"#006633\">
  19488.    <b>Enjoy!</b></font>"
  19489.  >
  19490.  
  19491. </table>
  19492.  
  19493. <p>
  19494.  
  19495. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  19496.  
  19497. <_dul>How to Uninstall Euphoria</_dul>
  19498.  
  19499. </font>
  19500.  
  19501. <pre>
  19502.      1. delete the EUPHORIA directory
  19503.      
  19504.      2. remove the 2 references to "EUPHORIA" from your autoexec.bat file
  19505. </pre>
  19506.  
  19507. <p> 
  19508. <hr>
  19509.  
  19510. <br>
  19511. <font face="Arial, Helvetica" color="#003366">
  19512. <b><_sul>If you have problems installing ...</_sul></b></font>
  19513.  
  19514. <ul>
  19515. <li>
  19516.    If the install appeared to run ok, did you remember to shut down
  19517.    and restart your computer?
  19518. <p>
  19519. <li>
  19520.    If a failure happens during the install, shut down any large applications
  19521.    that you have running, and try it again.
  19522. <p>
  19523. <li>
  19524.    Try installing under plain DOS, outside of Windows. 
  19525. <p>
  19526. <li>
  19527.    Disable or cut back programs such as SMARTDRV that may be consuming
  19528.    large amounts of extended memory.
  19529. <p>
  19530. <li>
  19531.    Try typing:
  19532. <pre>
  19533.            SET CAUSEWAY=LOWMEM:80
  19534. </pre>
  19535.    before you run <font color="#5500FF"><b>install.bat</b></font>
  19536. <p>
  19537. <li>
  19538.    There are several possible reasons why the
  19539.    <font color="#993333"><b>install</b></font> program will decide not
  19540.    to edit your <b>autoexec.bat</b> file. If this
  19541.    happens you should follow the manual procedure described
  19542.    <a href="install.htm#manual">below</a>.
  19543. <p>
  19544. <li>
  19545.    If your system does not use an <b>autoexec.bat</b> file (e.g. Windows NT
  19546.    and possibly Windows 95) then set the EUDIR and PATH variables in whatever
  19547.    way your system allows. If you have an <b>autoexec.bat</b> file, but it
  19548.    doesn't contain a PATH command, you will have to create one that includes 
  19549.    <font color="#5500FF"><b>C:\EUPHORIA\BIN</b></font>.
  19550. <p>
  19551. <li>
  19552.    If you have less than 20 megabytes of free disk space, free up a 
  19553.    few megabytes, and run <font color="#5500FF"><b>install.bat</b></font>
  19554.    again.
  19555.  
  19556. </ul>
  19557.  
  19558. <p>
  19559.  If you need help installing Euphoria, send e-mail to:
  19560.  <a href="mailto:rds@attcanada.net"><b>rds@attcanada.net</b></a>
  19561.  
  19562. <p>
  19563.  Be sure to describe your machine configuration: memory, free extended memory,
  19564.  operating system, etc.
  19565.  
  19566. <p> <br>
  19567. <a name=manual></a>
  19568. <font face="Arial, Helvetica" color="#003366">
  19569. <b><_sul>How to manually edit autoexec.bat</_sul></b></font>
  19570.  
  19571. <p>
  19572.  In some cases the <font color="#993333"><b>install</b></font> program will
  19573.  not be able to modify your <b>autoexec.bat</b> file for you automatically,
  19574.  and you will have to do the job yourself using a text editor.
  19575.  
  19576. <p>
  19577. <table border=0 cellspacing=2 cellpadding=2>
  19578.  
  19579. <_4clist
  19580.   name="1."
  19581.   pos=8
  19582.   description="In the file <b>c:\autoexec.bat</b> add
  19583.    <b>C:\EUPHORIA\BIN</b> to the list of directories in your PATH command.
  19584.    You might use the MS-DOS EDIT command, Windows Notepad or any other text
  19585.    editor to do this. e.g."
  19586. >
  19587.  
  19588. <_eucode>
  19589.         edit c:\autoexec.bat
  19590. </_eucode>
  19591.  
  19592. <_4clist
  19593.   col3=""
  19594.   name=""
  19595.   pos=8
  19596.   description="(Although Euphoria is not fully installed at this point, you
  19597.    could type:"
  19598. >
  19599.  
  19600. <_eucode>
  19601.         cd c:\euphoria\bin
  19602.         ed c:\autoexec.bat
  19603. </_eucode>
  19604.  
  19605. <_4clist
  19606.   col3=""
  19607.   name=""
  19608.   pos=8
  19609.   description="to edit using the Euphoria editor. See
  19610.    <font color=\"#5500FF\"><b>doc\ed.doc</b></font>)"
  19611. >
  19612.  
  19613. <_4clist
  19614.   name="2."
  19615.   pos=8
  19616.   description="In the same <b>autoexec.bat</b> file add a new line:"
  19617. >
  19618.  
  19619. <_eucode>
  19620.         SET EUDIR=C:\EUPHORIA
  19621. </_eucode>
  19622.  
  19623. <_4clist
  19624.   col3=""
  19625.   name=""
  19626.   pos=8
  19627.   description="The EUDIR environment variable indicates the full path to
  19628.    the main Euphoria directory."
  19629. >
  19630.  
  19631. <_4clist
  19632.   name="3."
  19633.   pos=8
  19634.   description="Reboot (restart) your machine. This will define your new
  19635.    PATH and EUDIR environment variables."
  19636. >
  19637.  
  19638. </table>
  19639.  
  19640. <p> 
  19641.  
  19642. </_width>
  19643. </body>
  19644. </html>
  19645.  
  19646. LIBRARY.HTX
  19647. 33495
  19648. <_init_comment>
  19649. <html>
  19650. <head><title>Euphoria v2.2 Reference Manual Part II - Section 1 and 2</title>
  19651. </head>
  19652. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  19653. <_width>
  19654. <_center><font color="#006633" size=+2><b>
  19655. <br>
  19656.                        Part II - Library Routines
  19657. </b></font></_center>
  19658.  
  19659. <_center><font color="#FF0099" size=+2>
  19660. <br>
  19661.                             1. Introduction
  19662. </font></_center>
  19663. <p> <br>
  19664.  
  19665.  A large number of library routines are provided. Some are built right into
  19666.  the interpreter, <font color="#993333"><b>ex.exe</b></font> or
  19667.  <font color="#993333"><b>exw.exe</b></font>.
  19668.  Others are written in Euphoria and you
  19669.  must include one of the <b>.e</b> files in
  19670.  <font color="#5500FF"><b>euphoria\include</b></font> to use them. Where this
  19671.  is the case, the appropriate include file is noted in the "Syntax" part of
  19672.  the description. Of course an include file need only be included once in your
  19673.  program. The editor displays in magenta those routines that are built into
  19674.  the interpreter, and require no include file. You can override the definition
  19675.  of these built-in routines by defining your own routine with the same name.
  19676.  You will get a suppressible warning if you do this.
  19677.  
  19678. <p>
  19679.  To indicate what kind of <font color="#993333"><b>object</b></font> may
  19680.  be passed in and returned, the following prefixes are used:
  19681.  
  19682. <p>
  19683. <center><table border=0 cellspacing=2 cellpadding=2>
  19684.  
  19685. <_3clist
  19686.   name="x"
  19687.   pos=10
  19688.   description="a general <a href=\"refman_2.htm#1\">object</a>
  19689.      (atom or sequence)"
  19690. >
  19691.  
  19692. <_3clist
  19693.   name="s"
  19694.   pos=10
  19695.   description="a <a href=\"refman_2.htm#1\">sequence</a>"
  19696. >
  19697.  
  19698. <_3clist
  19699.   name="a"
  19700.   pos=10
  19701.   description="an <a href=\"refman_2.htm#1\">atom</a>"
  19702. >
  19703.  
  19704. <_3clist
  19705.   name="i"
  19706.   pos=10
  19707.   description="an <a href=\"refman_2.htm#integer\">integer</a>"
  19708. >
  19709.  
  19710. <_3clist
  19711.   name="fn"
  19712.   pos=10
  19713.   description="an <a href=\"refman_2.htm#integer\">integer</a> used
  19714.      as a file number"
  19715. >
  19716.  
  19717. <_3clist
  19718.   name="st"
  19719.   pos=10
  19720.   description="a <a href=\"refman_2.htm#11\">string sequence</a>,
  19721.      or <a href=\"refman_2.htm#char\">single-character atom</a>"
  19722. >
  19723.  
  19724. </table></center>
  19725.  
  19726. <p>
  19727.  Some routines are only available on one or two of the three platforms. 
  19728.  This is noted
  19729.  with "Platform: <font color="#CC3366"><b>DOS32</b></font>" or
  19730.  "Platform: <font color="#CC3366"><b>WIN32</b></font>" or
  19731.  "Platform: <font color="#CC3366"><b>Linux</b></font>" 
  19732.  in the description
  19733.  of the routine, and with (<font color="#CC3366"><b>DOS32</b></font>) or
  19734.  (<font color="#CC3366"><b>WIN32</b></font>) or
  19735.  (<font color="#CC3366"><b>Linux</b></font>) 
  19736.  in some other places.
  19737.  
  19738. <p>
  19739.  A run-time error message will usually result if an illegal argument value
  19740.  is passed to any of these routines.
  19741.  
  19742. <p>
  19743. <hr>
  19744. <a name=2></a>
  19745. <_center><font color="#FF0099" size=+2>
  19746. <br>
  19747.                     2. Routines by Application Area
  19748. </font></_center>
  19749. <p>
  19750.  
  19751. <a name=predefined></a>
  19752. <font color="#FF0099" size=+1>
  19753. <br>
  19754.  
  19755. <_dul>2.1 Predefined Types</_dul>
  19756.  
  19757. </font>
  19758. <p>
  19759.  
  19760.       As well as declaring variables with these types, you can also call them
  19761.       just like ordinary functions, in order to test if a value is a certain
  19762.       type.
  19763.  
  19764. <p>
  19765. <table border=0 cellspacing=2 cellpadding=2>
  19766.  
  19767. <_3clist
  19768.   href="lib_h_o.htm#integer"
  19769.   name="integer"
  19770.   description="test if an object is an integer"
  19771. >
  19772.  
  19773. <_3clist
  19774.   href="lib_a_b.htm#atom"
  19775.   name="atom"
  19776.   description="test if an object is an atom"
  19777. >
  19778.  
  19779. <_3clist
  19780.   href="lib_s_t.htm#sequence"
  19781.   name="sequence"
  19782.   description="test if an object is a sequence"
  19783. >
  19784.  
  19785. <_3clist
  19786.   href="lib_h_o.htm#object"
  19787.   name="object"
  19788.   description="test if an object is an object (always true)"
  19789. >
  19790.  
  19791. </table>
  19792.  
  19793. <p>
  19794. <hr>
  19795.  
  19796. <a name=seq_manip></a>
  19797. <font color="#FF0099" size=+1>
  19798. <br>
  19799.  
  19800. <_dul>2.2 Sequence Manipulation</_dul>
  19801.  
  19802. </font>
  19803. <p>
  19804.  
  19805. <table border=0 cellspacing=2 cellpadding=2>
  19806.  
  19807. <_3clist
  19808.   href="lib_h_o.htm#length"
  19809.   name="length"
  19810.   description="return the length of a sequence"
  19811. >
  19812.  
  19813. <_3clist
  19814.   href="lib_p_r.htm#repeat"
  19815.   name="repeat"
  19816.   description="repeat an object n times to form a sequence of length n"
  19817. >
  19818.  
  19819. <_3clist
  19820.   href="lib_p_r.htm#reverse"
  19821.   name="reverse"
  19822.   description="reverse a sequence"
  19823. >
  19824.  
  19825. <_3clist
  19826.   href="lib_a_b.htm#append"
  19827.   name="append"
  19828.   description="add a new element to the end of a sequence"
  19829. >
  19830.  
  19831. <_3clist
  19832.   href="lib_p_r.htm#prepend"
  19833.   name="prepend"
  19834.   description="add a new element to the beginning of a sequence"
  19835. >
  19836.  
  19837. </table>
  19838.  
  19839. <p>
  19840. <hr>
  19841.  
  19842. <a name=srch_srt></a>
  19843. <font color="#FF0099" size=+1>
  19844. <br>
  19845.  
  19846. <_dul>2.3 Searching and Sorting</_dul>
  19847.  
  19848. </font>
  19849. <p>
  19850.  
  19851. <table border=0 cellspacing=2 cellpadding=2>
  19852.  
  19853. <_3clist
  19854.   href="lib_c_d.htm#compare"
  19855.   name="compare"
  19856.   description="compare two objects"
  19857. >
  19858.  
  19859. <_3clist
  19860.   href="lib_e_g.htm#equal"
  19861.   name="equal"
  19862.   description="test if two objects are identical"
  19863. >
  19864.  
  19865. <_3clist
  19866.   href="lib_e_g.htm#find"
  19867.   name="find"
  19868.   description="find an object in a sequence"
  19869. >
  19870.  
  19871. <_3clist
  19872.   href="lib_h_o.htm#match"
  19873.   name="match"
  19874.   description="find a sequence as a slice of another sequence"
  19875. >
  19876.  
  19877. <_3clist
  19878.   href="lib_s_t.htm#sort"
  19879.   name="sort"
  19880.   description="sort the elements of a sequence into ascending order"
  19881. >
  19882.  
  19883. <_3clist
  19884.   href="lib_c_d.htm#custom_sort"
  19885.   name="custom_sort"
  19886.   description="sort the elements of a sequence based on a compare
  19887.      function that you supply"
  19888. >
  19889.  
  19890. </table>
  19891.  
  19892. <p>
  19893. <hr>
  19894.  
  19895. <a name=pattern_m></a>
  19896. <font color="#FF0099" size=+1>
  19897. <br>
  19898.  
  19899. <_dul>2.4 Pattern Matching</_dul>
  19900.  
  19901. </font>
  19902. <p>
  19903.  
  19904. <table border=0 cellspacing=2 cellpadding=2>
  19905.  
  19906. <_3clist
  19907.   href="lib_h_o.htm#lower"
  19908.   name="lower"
  19909.   description="convert an atom or sequence to lower case"
  19910. >
  19911.  
  19912. <_3clist
  19913.   href="lib_u_z.htm#upper"
  19914.   name="upper"
  19915.   description="convert an atom or sequence to upper case"
  19916. >
  19917.  
  19918. <_3clist
  19919.   href="lib_u_z.htm#wildcard_match"
  19920.   name="wildcard_match"
  19921.   description="match a pattern containing ? and * wildcards"
  19922. >
  19923.  
  19924. <_3clist
  19925.   href="lib_u_z.htm#wildcard_file"
  19926.   name="wildcard_file"
  19927.   description="match a file name against a wildcard specification"
  19928. >
  19929.  
  19930. </table>
  19931.  
  19932. <p>
  19933. <hr>
  19934.  
  19935. <a name=math></a>
  19936. <font color="#FF0099" size=+1>
  19937. <br>
  19938.  
  19939. <_dul>2.5 Math</_dul>
  19940.  
  19941. </font>
  19942. <p>
  19943.       These routines can be applied to individual atoms or to sequences of
  19944.       values. See <a href="refman_2.htm#26">Part I - Core Language -
  19945.       Operations on Sequences</a>.
  19946.  
  19947. <p>
  19948. <table border=0 cellspacing=2 cellpadding=2>
  19949.  
  19950. <_3clist
  19951.   href="lib_s_t.htm#sqrt"
  19952.   name="sqrt"
  19953.   description="calculate the square root of an object"
  19954. >
  19955.  
  19956. <_3clist
  19957.   href="lib_p_r.htm#rand"
  19958.   name="rand"
  19959.   description="generate random numbers"
  19960. >
  19961.  
  19962. <_3clist
  19963.   href="lib_s_t.htm#sin"
  19964.   name="sin"
  19965.   description="calculate the sine of an angle"
  19966. >
  19967.  
  19968. <_3clist
  19969.   href="lib_a_b.htm#arcsin"
  19970.   name="arcsin"
  19971.   description="calculate the angle with a given sine"
  19972. >
  19973.  
  19974. <_3clist
  19975.   href="lib_c_d.htm#cos"
  19976.   name="cos"
  19977.   description="calculate the cosine of an angle"
  19978. >
  19979.  
  19980. <_3clist
  19981.   href="lib_a_b.htm#arccos"
  19982.   name="arccos"
  19983.   description="calculate the angle with a given cosine"
  19984. >
  19985.  
  19986. <_3clist
  19987.   href="lib_s_t.htm#tan"
  19988.   name="tan"
  19989.   description="calculate the tangent of an angle"
  19990. >
  19991.  
  19992. <_3clist
  19993.   href="lib_a_b.htm#arctan"
  19994.   name="arctan"
  19995.   description="calculate the arc tangent of a number"
  19996. >
  19997.  
  19998. <_3clist
  19999.   href="lib_h_o.htm#log"
  20000.   name="log"
  20001.   description="calculate the natural logarithm"
  20002. >
  20003.  
  20004. <_3clist
  20005.   href="lib_e_g.htm#floor"
  20006.   name="floor"
  20007.   description="round down to the nearest integer"
  20008. >
  20009.  
  20010. <_3clist
  20011.   href="lib_p_r.htm#remainder"
  20012.   name="remainder"
  20013.   description="calculate the remainder when a number is divided by another"
  20014. >
  20015.  
  20016. <_3clist
  20017.   href="lib_p_r.htm#power"
  20018.   name="power"
  20019.   description="calculate a number raised to a power"
  20020. >
  20021.  
  20022. <_3clist
  20023.   href="lib_p_r.htm#PI"
  20024.   name="PI"
  20025.   description="the mathematical value PI (3.14159...)"
  20026. >
  20027.  
  20028. </table>
  20029.  
  20030. <p>
  20031. <hr>
  20032.  
  20033. <a name=bitw_logic></a>
  20034. <font color="#FF0099" size=+1>
  20035. <br>
  20036.  
  20037. <_dul>2.6 Bitwise Logical Operations</_dul>
  20038.  
  20039. </font>
  20040. <p>
  20041.  
  20042.       These routines treat numbers as collections of binary bits,
  20043.       and logical operations are performed on corresponding
  20044.       bits in the binary representation of the numbers. There are
  20045.       no routines for shifting bits left or right, but you can
  20046.       achieve the same effect by multiplying or dividing by
  20047.       powers of 2.
  20048.  
  20049. <p>
  20050. <table border=0 cellspacing=2 cellpadding=2>
  20051.  
  20052. <_3clist
  20053.   href="lib_a_b.htm#and_bits"
  20054.   name="and_bits"
  20055.   description="perform logical AND on corresponding bits"
  20056. >
  20057.  
  20058. <_3clist
  20059.   href="lib_h_o.htm#or_bits"
  20060.   name="or_bits"
  20061.   description="perform logical OR on corresponding bits"
  20062. >
  20063.  
  20064. <_3clist
  20065.   href="lib_u_z.htm#xor_bits"
  20066.   name="xor_bits"
  20067.   description="perform logical XOR on corresponding bits"
  20068. >
  20069.  
  20070. <_3clist
  20071.   href="lib_h_o.htm#not_bits"
  20072.   name="not_bits"
  20073.   description="perform logical NOT on all bits"
  20074. >
  20075.  
  20076. </table>
  20077.  
  20078. <p>
  20079. <hr>
  20080.  
  20081. <a name=i_o></a>
  20082. <font color="#FF0099" size=+1>
  20083. <br>
  20084.  
  20085. <_dul>2.7 File and Device I/O</_dul>
  20086.  
  20087. </font>
  20088. <p>
  20089.  
  20090.       To do input or output on a file or device you must first open the file
  20091.       or device, then use the routines below to read or write to it, then close
  20092.       the file or device. <a href="lib_h-o.htm#open">open()</a> will give you
  20093.       a file number to use as the first argument of the other I/O routines.
  20094.       Certain files/devices are opened for you automatically (as text files):
  20095. <dl>
  20096. <dl>
  20097. <dt>
  20098.              0 - standard input
  20099. <dt>
  20100.              1 - standard output
  20101. <dt>
  20102.              2 - standard error
  20103. </dl>
  20104. </dl>
  20105.  
  20106.       Unless you redirect them on the 
  20107.       <a href="refman_1.htm#3">command-line</a>, standard input comes from
  20108.       the keyboard, standard output and standard error go to the screen. When
  20109.       you write something to the screen it is written immediately without
  20110.       buffering. If you write to a file, your characters are put into a buffer
  20111.       until there are enough of them to write out efficiently. When you 
  20112.       <a href=lib_c_d.htm#close>close()</a>
  20113.       or <a href=lib_e_g.htm#flush>flush()</a> the file or device, any 
  20114.       remaining characters are written out. 
  20115.       Input from
  20116.       files is also buffered. When your program terminates, any files that are
  20117.       still open will be closed for you automatically.
  20118.  
  20119. <dl>
  20120. <dt>
  20121.  <b><font color="#006633"><_sul>Note:</_sul></font></b>
  20122.  
  20123. <dd>
  20124.       If a program (written in Euphoria or any other language) has a
  20125.       file open for writing, and you are forced to reboot your computer for
  20126.       any reason, you should immediately run <b>scandisk</b> to repair any
  20127.       damage to the file system that may have occurred.
  20128. </dl>
  20129.  
  20130. <table border=0 cellspacing=2 cellpadding=2>
  20131.  
  20132. <_3clist
  20133.   href="lib_h_o.htm#open"
  20134.   name="open"
  20135.   description="open a file or device"
  20136. >
  20137.  
  20138. <_3clist
  20139.   href="lib_c_d.htm#close"
  20140.   name="close"
  20141.   description="close a file or device"
  20142. >
  20143.  
  20144. <_3clist
  20145.   href="lib_e_g.htm#flush"
  20146.   name="flush"
  20147.   description="flush out buffered data to a file or device"
  20148. >
  20149.  
  20150. <_3clist
  20151.   href="lib_h_o.htm#lock_file"
  20152.   name="lock_file"
  20153.   description="lock a file or device"
  20154. >
  20155.  
  20156. <_3clist
  20157.   href="lib_u_z.htm#unlock_file"
  20158.   name="unlock_file"
  20159.   description="unlock a file or device"
  20160. >
  20161.  
  20162. <_3clist
  20163.   href="lib_p_r.htm#print"
  20164.   name="print"
  20165.   description="<a name=print></a>print a Euphoria
  20166.      object with {,,} to show the structure"
  20167. >
  20168.  
  20169. <_3clist
  20170.   href="lib_a_b.htm#?"
  20171.   name="? x"
  20172.   description="<a name=questn></a>shorthand for print(1, x)"
  20173. >
  20174.  
  20175. <_3clist
  20176.   href="lib_s_t.htm#sprint"
  20177.   name="sprint"
  20178.   description="return a printed Euphoria object as a string sequence"
  20179. >
  20180.  
  20181. <_3clist
  20182.   href="lib_p_r.htm#printf"
  20183.   name="printf"
  20184.   description="formatted print to a file or device"
  20185. >
  20186.  
  20187. <_3clist
  20188.   href="lib_s_t.htm#sprintf"
  20189.   name="sprintf"
  20190.   description="formatted print returned as a string sequence"
  20191. >
  20192.  
  20193. <_3clist
  20194.   href="lib_p_r.htm#puts"
  20195.   name="puts"
  20196.   description="output a string sequence to a file or device"
  20197. >
  20198.  
  20199. <_3clist
  20200.   href="lib_e_g.htm#getc"
  20201.   name="getc"
  20202.   description="read the next character from a file or device"
  20203. >
  20204.  
  20205. <_3clist
  20206.   href="lib_e_g.htm#gets"
  20207.   name="gets"
  20208.   description="<a name=gets></a>read the next line from a file or device"
  20209. >
  20210.  
  20211. <_3clist
  20212.   href="lib_e_g.htm#get_bytes"
  20213.   name="get_bytes"
  20214.   description="<a name=get_bytes></a>read the next n bytes
  20215.      from a file or device"
  20216. >
  20217.  
  20218. <_3clist
  20219.   href="lib_p_r.htm#prompt_string"
  20220.   name="prompt_string"
  20221.   description="prompt the user to enter a string"
  20222. >
  20223.  
  20224. <_3clist
  20225.   href="lib_e_g.htm#get_key"
  20226.   name="get_key"
  20227.   description="<a name=get_key></a>check for key
  20228.      pressed by the user, don't wait"
  20229. >
  20230.  
  20231. <_3clist
  20232.   href="lib_u_z.htm#wait_key"
  20233.   name="wait_key"
  20234.   description="wait for user to press a key"
  20235. >
  20236.  
  20237. <_3clist
  20238.   href="lib_e_g.htm#get"
  20239.   name="get"
  20240.   description="read the representation of any Euphoria object from a file"
  20241. >
  20242.  
  20243. <_3clist
  20244.   href="lib_p_r.htm#prompt_number"
  20245.   name="prompt_number"
  20246.   description="prompt the user to enter a number"
  20247. >
  20248.  
  20249. <_3clist
  20250.   href="lib_u_z.htm#value"
  20251.   name="value"
  20252.   description="read the representation of any Euphoria object from a string"
  20253. >
  20254.  
  20255. <_3clist
  20256.   href="lib_s_t.htm#seek"
  20257.   name="seek"
  20258.   description="move to any byte position within an open file"
  20259. >
  20260.  
  20261. <_3clist
  20262.   href="lib_u_z.htm#where"
  20263.   name="where"
  20264.   description="report the current byte position in an open file"
  20265. >
  20266.  
  20267. <_3clist
  20268.   href="lib_c_d.htm#current_dir"
  20269.   name="current_dir"
  20270.   description="return the name of the current directory"
  20271. >
  20272.  
  20273. <_3clist
  20274.   href="lib_c_d.htm#chdir"
  20275.   name="chdir"
  20276.   description="change to a new current directory"
  20277. >
  20278.  
  20279. <_3clist
  20280.   href="lib_c_d.htm#dir"
  20281.   name="dir"
  20282.   description="return complete info on all files in a directory"
  20283. >
  20284.  
  20285. <_3clist
  20286.   href="lib_u_z.htm#walk_dir"
  20287.   name="walk_dir"
  20288.   description="recursively walk through all files in a directory"
  20289. >
  20290.  
  20291. <_3clist
  20292.   href="lib_a_b.htm#allow_break"
  20293.   name="allow_break"
  20294.   description="allow control-c/control-Break to terminate your program or not"
  20295. >
  20296.  
  20297. <_3clist
  20298.   href="lib_c_d.htm#check_break"
  20299.   name="check_break"
  20300.   description="check if user has pressed control-c or control-Break"
  20301. >
  20302.  
  20303. </table>
  20304.  
  20305. <p>
  20306. <hr>
  20307.  
  20308. <a name=mouse_spt></a>
  20309. <font color="#FF0099" size=+1>
  20310. <br>
  20311.  
  20312. <_dul>2.8 Mouse Support (DOS32 and Linux)</_dul>
  20313.  
  20314. </font>
  20315. <p>
  20316.  
  20317. <table border=0 cellspacing=2 cellpadding=2>
  20318.  
  20319. <_3clist
  20320.   href="lib_e_g.htm#get_mouse"
  20321.   name="get_mouse"
  20322.   description="return mouse \"events\" (clicks, movements)"
  20323. >
  20324.  
  20325. <_3clist
  20326.   href="lib_h_o.htm#mouse_events"
  20327.   name="mouse_events"
  20328.   description="select mouse events to watch for"
  20329. >
  20330.  
  20331. <_3clist
  20332.   href="lib_h_o.htm#mouse_pointer"
  20333.   name="mouse_pointer"
  20334.   description="display or hide the mouse pointer"
  20335. >
  20336.  
  20337. </table>
  20338.  
  20339. <p>
  20340. <hr>
  20341.  
  20342. <a name=op_sys></a>
  20343. <font color="#FF0099" size=+1>
  20344. <br>
  20345.  
  20346. <_dul>2.9 Operating System</_dul>
  20347.  
  20348. </font>
  20349. <p>
  20350.  
  20351. <table border=0 cellspacing=2 cellpadding=2>
  20352.  
  20353. <_3clist
  20354.   href="lib_s_t.htm#time"
  20355.   name="time"
  20356.   description="number of seconds since a fixed point in the past"
  20357. >
  20358.  
  20359. <_3clist
  20360.   href="lib_s_t.htm#tick_rate"
  20361.   name="tick_rate"
  20362.   description="set the number of clock ticks per second (DOS32)"
  20363. >
  20364.  
  20365. <_3clist
  20366.   href="lib_c_d.htm#date"
  20367.   name="date"
  20368.   description="current year, month, day, hour, minute, second etc."
  20369. >
  20370.  
  20371. <_3clist
  20372.   href="lib_c_d.htm#command_line"
  20373.   name="command_line"
  20374.   description="command-line used to run this program"
  20375. >
  20376.  
  20377. <_3clist
  20378.   href="lib_e_g.htm#getenv"
  20379.   name="getenv"
  20380.   description="get value of an environment variable"
  20381. >
  20382.  
  20383. <_3clist
  20384.   href="lib_s_t.htm#system"
  20385.   name="system"
  20386.   description="execute an operating system command line"
  20387. >
  20388.  
  20389. <_3clist
  20390.   href="lib_s_t.htm#system_exec"
  20391.   name="system_exec"
  20392.   description="execute a program and get its exit code"
  20393. >
  20394.  
  20395. <_3clist
  20396.   href="lib_a_b.htm#abort"
  20397.   name="abort"
  20398.   description="terminate execution"
  20399. >
  20400.  
  20401. <_3clist
  20402.   href="lib_s_t.htm#sleep"
  20403.   name="sleep"
  20404.   description="suspend execution for a period of time"
  20405. >
  20406.  
  20407. <_3clist
  20408.   href="lib_p_r.htm#platform"
  20409.   name="platform"
  20410.   description="find out which operating system are we running on"
  20411. >
  20412.  
  20413. </table>
  20414.  
  20415. <p>
  20416. <hr>
  20417.  
  20418. <a name=machine_dep></a>
  20419. <font color="#FF0099" size=+1>
  20420. <br>
  20421.  
  20422. <_dul>2.10 Special Machine-Dependent Routines</_dul>
  20423.  
  20424. </font>
  20425. <p>
  20426.  
  20427. <table border=0 cellspacing=2 cellpadding=2>
  20428.  
  20429. <_3clist
  20430.   href="lib_h_o.htm#machine_func"
  20431.   name="machine_func"
  20432.   description="specialized internal operations with a return value"
  20433. >
  20434.  
  20435. <_3clist
  20436.   href="lib_h_o.htm#machine_proc"
  20437.   name="machine_proc"
  20438.   description="specialized internal operations with no return value"
  20439. >
  20440.  
  20441. </table>
  20442.  
  20443. <p>
  20444. <hr>
  20445.  
  20446. <a name=debugging></a>
  20447. <font color="#FF0099" size=+1>
  20448. <br>
  20449.  
  20450. <_dul>2.11 Debugging</_dul>
  20451.  
  20452. </font>
  20453. <p>
  20454.  
  20455. <table border=0 cellspacing=2 cellpadding=2>
  20456.  
  20457. <_3clist
  20458.   href="lib_s_t.htm#trace"
  20459.   name="trace"
  20460.   description="dynamically turns tracing on or off"
  20461. >
  20462.  
  20463. <_3clist
  20464.   href="lib_p_r.htm#profile"
  20465.   name="profile"
  20466.   description="dynamically turns profiling on or off"
  20467. >
  20468.  
  20469. </table>
  20470.  
  20471. <p>
  20472. <hr>
  20473.  
  20474. <a name=gr_sound></a>
  20475. <font color="#FF0099" size=+1>
  20476. <br>
  20477.  
  20478. <_dul>2.12 Graphics & Sound</_dul>
  20479.  
  20480. </font>
  20481. <p>
  20482.  
  20483.       The following routines let you display information on the screen. The
  20484.       PC screen can be placed into one of many graphics modes. See the top
  20485.       of <font color="#5500FF"><b>include\graphics.e</b></font> for a
  20486.       description of the modes. <b>There are two basic types of graphics mode
  20487.       available.</b> <font color="#993333"><_bq>Text</_bq> <b>modes</b></font>
  20488.       divide the screen up into lines, where each line has a certain number
  20489.       of characters.
  20490.       <font color="#993333"><_bq>Pixel-graphics</_bq> <b>modes</b></font>
  20491.       divide the screen up into many rows of dots, or "pixels". Each pixel
  20492.       can be a different color. In text modes you can display text only,
  20493.       with the choice of a foreground and a background
  20494.       color for each character. In pixel-graphics modes you can display lines,
  20495.       circles, dots, and also text.
  20496.  
  20497. <p>
  20498.       For DOS32 we've included a routine for making sounds on your PC speaker.
  20499.       To make more sophisticated sounds, get the <b>Sound Blaster</b> library
  20500.       developed by <b>Jacques Deschenes</b>. It's available on the
  20501.       <a href="http://www.RapidEuphoria.com">Euphoria Web page</a>.
  20502.  
  20503. <p>
  20504.       <_sul><font color="#006633"><b>The following routines work in all
  20505.       text and pixel-graphics modes:</b></font></_sul>
  20506.  
  20507. <p>
  20508. <table border=0 cellspacing=2 cellpadding=2>
  20509.  
  20510. <_3clist
  20511.   href="lib_c_d.htm#clear_screen"
  20512.   name="clear_screen"
  20513.   pos=22
  20514.   description="clear the screen"
  20515. >
  20516.  
  20517. <_3clist
  20518.   href="lib_p_r.htm#position"
  20519.   name="position"
  20520.   pos=22
  20521.   description="set cursor line and column"
  20522. >
  20523.  
  20524. <_3clist
  20525.   href="lib_e_g.htm#get_position"
  20526.   name="get_position"
  20527.   pos=22
  20528.   description="return cursor line and column"
  20529. >
  20530.  
  20531. <_3clist
  20532.   href="lib_e_g.htm#graphics_mode"
  20533.   name="graphics_mode"
  20534.   pos=22
  20535.   description="select a new pixel-graphics or text mode (DOS32)"
  20536. >
  20537.  
  20538. <_3clist
  20539.   href="lib_u_z.htm#video_config"
  20540.   name="video_config"
  20541.   pos=22
  20542.   description="return parameters of current mode"
  20543. >
  20544.  
  20545. <_3clist
  20546.   href="lib_s_t.htm#scroll"
  20547.   name="scroll"
  20548.   pos=22
  20549.   description="scroll text up or down"
  20550. >
  20551.  
  20552. <_3clist
  20553.   href="lib_u_z.htm#wrap"
  20554.   name="wrap"
  20555.   pos=22
  20556.   description="control line wrap at right edge of screen"
  20557. >
  20558.  
  20559. <_3clist
  20560.   href="lib_s_t.htm#text_color"
  20561.   name="text_color"
  20562.   pos=22
  20563.   description="set foreground text color"
  20564. >
  20565.  
  20566. <_3clist
  20567.   href="lib_a_b.htm#bk_color"
  20568.   name="bk_color"
  20569.   pos=22
  20570.   description="set background color"
  20571. >
  20572.  
  20573. <_3clist
  20574.   href="lib_p_r.htm#palette"
  20575.   name="palette"
  20576.   pos=22
  20577.   description="change color for one color number (DOS32)"
  20578. >
  20579.  
  20580. <_3clist
  20581.   href="lib_a_b.htm#all_palette"
  20582.   name="all_palette"
  20583.   pos=22
  20584.   description="change color for all color numbers (DOS32)"
  20585. >
  20586.  
  20587. <_3clist
  20588.   href="lib_e_g.htm#get_all_palette"
  20589.   name="get_all_palette"
  20590.   pos=22
  20591.   description="get the palette values for all colors (DOS32)"
  20592. >
  20593.  
  20594. <_3clist
  20595.   href="lib_p_r.htm#read_bitmap"
  20596.   name="read_bitmap"
  20597.   pos=22
  20598.   description="read a bitmap (.bmp) file and return a palette and
  20599.      a 2-d sequence of pixels"
  20600. >
  20601.  
  20602. <_3clist
  20603.   href="lib_s_t.htm#save_bitmap"
  20604.   name="save_bitmap"
  20605.   pos=22
  20606.   description="create a bitmap (.bmp) file, given a palette and a
  20607.      2-d sequence of pixels"
  20608. >
  20609.  
  20610. <_3clist
  20611.   href="lib_e_g.htm#get_active_page"
  20612.   name="get_active_page"
  20613.   pos=22
  20614.   description="return the page currently being written to (DOS32)"
  20615. >
  20616.  
  20617. <_3clist
  20618.   href="lib_s_t.htm#set_active_page"
  20619.   name="set_active_page"
  20620.   pos=22
  20621.   description="change the page currently being written to (DOS32)"
  20622. >
  20623.  
  20624. <_3clist
  20625.   href="lib_e_g.htm#get_display_page"
  20626.   name="get_display_page"
  20627.   pos=22
  20628.   description="return the page currently being displayed (DOS32)"
  20629. >
  20630.  
  20631. <_3clist
  20632.   href="lib_s_t.htm#set_display_page"
  20633.   name="set_display_page"
  20634.   pos=22
  20635.   description="change the page currently being displayed (DOS32)"
  20636. >
  20637.  
  20638. <_3clist
  20639.   href="lib_s_t.htm#sound"
  20640.   name="sound"
  20641.   pos=22
  20642.   description="make a sound on the PC speaker (DOS32)"
  20643. >
  20644.  
  20645. </table>
  20646.  
  20647. <p>
  20648.       <_sul><font color="#006633"><b>The following routines work in text
  20649.       modes only:</b></font></_sul>
  20650.  
  20651. <p>
  20652. <table border=0 cellspacing=2 cellpadding=2>
  20653.  
  20654. <_3clist
  20655.   href="lib_c_d.htm#cursor"
  20656.   name="cursor"
  20657.   pos=24
  20658.   description="select cursor shape"
  20659. >
  20660.  
  20661. <_3clist
  20662.   href="lib_s_t.htm#text_rows"
  20663.   name="text_rows"
  20664.   pos=24
  20665.   description="set number of lines on text screen"
  20666. >
  20667.  
  20668. <_3clist
  20669.   href="lib_e_g.htm#get_screen_char"
  20670.   name="get_screen_char"
  20671.   pos=24
  20672.   description="get one character from the screen"
  20673. >
  20674.  
  20675. <_3clist
  20676.   href="lib_p_r.htm#put_screen_char"
  20677.   name="put_screen_char"
  20678.   pos=24
  20679.   description="put one or more characters on the screen"
  20680. >
  20681.  
  20682. <_3clist
  20683.   href="lib_s_t.htm#save_text_image"
  20684.   name="save_text_image"
  20685.   pos=24
  20686.   description="save a rectangular region from a text screen (DOS32)"
  20687. >
  20688.  
  20689. <_3clist
  20690.   href="lib_c_d.htm#display_text_image"
  20691.   name="display_text_image"
  20692.   pos=24
  20693.   description="display an image on the text screen (DOS32)"
  20694. >
  20695.  
  20696. </table>
  20697.  
  20698. <p>
  20699.       <_sul><font color="#006633"><b>The following routines work in
  20700.       pixel-graphics modes only (DOS32):</b></font></_sul>
  20701.  
  20702. <p>
  20703. <table border=0 cellspacing=2 cellpadding=2>
  20704.  
  20705. <_3clist
  20706.   href="lib_p_r.htm#pixel"
  20707.   name="pixel"
  20708.   description="set color of a pixel or set of pixels"
  20709. >
  20710.  
  20711. <_3clist
  20712.   href="lib_e_g.htm#get_pixel"
  20713.   name="get_pixel"
  20714.   description="read color of a pixel or set of pixels"
  20715. >
  20716.  
  20717. <_3clist
  20718.   href="lib_c_d.htm#draw_line"
  20719.   name="draw_line"
  20720.   description="connect a series of graphics points with a line"
  20721. >
  20722.  
  20723. <_3clist
  20724.   href="lib_p_r.htm#polygon"
  20725.   name="polygon"
  20726.   description="draw an n-sided figure"
  20727. >
  20728.  
  20729. <_3clist
  20730.   href="lib_e_g.htm#ellipse"
  20731.   name="ellipse"
  20732.   description="draw an ellipse or circle"
  20733. >
  20734.  
  20735. <_3clist
  20736.   href="lib_s_t.htm#save_screen"
  20737.   name="save_screen"
  20738.   description="save the screen to a bitmap (.bmp) file"
  20739. >
  20740.  
  20741. <_3clist
  20742.   href="lib_s_t.htm#save_image"
  20743.   name="save_image"
  20744.   description="save a rectangular region from a pixel-graphics screen"
  20745. >
  20746.  
  20747. <_3clist
  20748.   href="lib_c_d.htm#display_image"
  20749.   name="display_image"
  20750.   description="display an image on the pixel-graphics screen"
  20751. >
  20752.  
  20753. </table>
  20754.  
  20755. <p>
  20756. <hr>
  20757.  
  20758. <a name=m_level_i></a>
  20759. <font color="#FF0099" size=+1>
  20760. <br>
  20761.  
  20762. <_dul>2.13 Machine Level Interface</_dul>
  20763.  
  20764. </font>
  20765. <p>
  20766.  
  20767.       We've grouped here a number of routines that you can use to access your
  20768.       machine at a low-level. With this low-level machine interface you can
  20769.       read and write to memory. You can also set up your own 386+ machine
  20770.       language routines and call them.
  20771.  
  20772. <p>
  20773.       Some of the routines listed below are unsafe, in the sense that Euphoria
  20774.       can't protect you if you use them incorrectly. You could crash your
  20775.       program or even your system. Under DOS32, if you reference a bad memory
  20776.       address it will often be safely caught by the CauseWay DOS extender, and
  20777.       you'll get an error message on the screen plus a dump of machine-level
  20778.       information in the file <font color="#993333"><b>cw.err</b></font>.
  20779.       Under WIN32, the operating system will usually pop up a termination box 
  20780.       giving a diagnostic message plus register information. Under Linux
  20781.       you'll typically get a segmentation violation.
  20782.  
  20783. <dl>
  20784. <dt>
  20785. <a name=safe></a>
  20786. <b><font color="#006633"><_sul>Note:</_sul></font></b>
  20787.  
  20788. <dd>
  20789.       To assist programmers in debugging code involving these unsafe routines,
  20790.       we have supplied <font color="#5500FF"><b>safe.e</b></font>, an
  20791.       alternative to <font color="#5500FF"><b>machine.e</b></font>. If you copy
  20792.       <font color="#5500FF"><b>include\safe.e</b></font> into the directory
  20793.       containing your program, and you rename <font color="#5500FF">
  20794.       <b>safe.e</b></font> as <font color="#5500FF"><b>machine.e</b></font> 
  20795.       in that directory, your program will run using safer 
  20796.       (but slower) versions of these low-level
  20797.       routines. <font color="#5500FF"><b>safe.e</b></font> can catch many
  20798.       errors, such as poking into a bad memory location.
  20799.       See the comments at the top of safe.e for complete instructions on
  20800.       how to use it.
  20801. </dl>
  20802.  
  20803. <p>
  20804.       These machine-level-interface routines are important because they
  20805.       allow Euphoria programmers
  20806.       to access low-level features of the hardware and operating system.
  20807.       For some applications this is essential.
  20808.  
  20809. <p>
  20810.       Machine code routines can be written by hand, or taken from the
  20811.       disassembled output of a compiler for C or some other language.
  20812.       Pete Eberlein has written a "mini-assembler" for use with Euphoria.
  20813.       See the <a href="http://www.RapidEuphoria.com/">Archive</a>.
  20814.       Remember that your machine code will be running in 32-bit protected
  20815.       mode. See <font color="#5500FF"><b>demo\dos32\callmach.ex</b></font>
  20816.       for an example.
  20817.  
  20818. <p>
  20819. <table border=0 cellspacing=2 cellpadding=2>
  20820.  
  20821. <_3clist
  20822.   href="lib_p_r.htm#peek"
  20823.   name="peek"
  20824.   description="read one or more bytes from memory"
  20825. >
  20826.  
  20827. <_3clist
  20828.   href="lib_p_r.htm#peek4s"
  20829.   name="peek4s"
  20830.   description="read 4-byte signed values from memory"
  20831. >
  20832.  
  20833. <_3clist
  20834.   href="lib_p_r.htm#peek4u"
  20835.   name="peek4u"
  20836.   description="read 4-byte unsigned values from memory"
  20837. >
  20838.  
  20839. <_3clist
  20840.   href="lib_p_r.htm#poke"
  20841.   name="poke"
  20842.   description="write one or more bytes to memory"
  20843. >
  20844.  
  20845. <_3clist
  20846.   href="lib_p_r.htm#poke4"
  20847.   name="poke4"
  20848.   description="write 4-byte values into memory"
  20849. >
  20850.  
  20851. <_3clist
  20852.   href="lib_h_o.htm#mem_copy"
  20853.   name="mem_copy"
  20854.   description="copy a block of memory"
  20855. >
  20856.  
  20857. <_3clist
  20858.   href="lib_h_o.htm#mem_set"
  20859.   name="mem_set"
  20860.   description="set a block of memory to a value"
  20861. >
  20862.  
  20863. <_3clist
  20864.   href="lib_c_d.htm#call"
  20865.   name="call"
  20866.   description="call a machine language routine"
  20867. >
  20868.  
  20869. <_3clist
  20870.   href="lib_c_d.htm#dos_interrupt"
  20871.   name="dos_interrupt"
  20872.   description="call a DOS software interrupt routine (DOS32)"
  20873. >
  20874.  
  20875. <_3clist
  20876.   href="lib_a_b.htm#allocate"
  20877.   name="allocate"
  20878.   description="allocate a block of memory"
  20879. >
  20880.  
  20881. <_3clist
  20882.   href="lib_e_g.htm#free"
  20883.   name="free"
  20884.   description="deallocate a block of memory"
  20885. >
  20886.  
  20887. <_3clist
  20888.   href="lib_a_b.htm#allocate_low"
  20889.   name="allocate_low"
  20890.   description="allocate a block of low memory (address less than 1Mb) (DOS32)"
  20891. >
  20892.  
  20893. <_3clist
  20894.   href="lib_e_g.htm#free_low"
  20895.   name="free_low"
  20896.   description="free a block allocated with allocate_low (DOS32)"
  20897. >
  20898.  
  20899. <_3clist
  20900.   href="lib_a_b.htm#allocate_string"
  20901.   name="allocate_string"
  20902.   description="allocate a string of characters with 0 terminator"
  20903. >
  20904.  
  20905. <_3clist
  20906.   href="lib_p_r.htm#register_block"
  20907.   name="register_block"
  20908.   description="register an externally-allocated block of memory"
  20909. >
  20910.  
  20911. <_3clist
  20912.   href="lib_u_z.htm#unregister_block"
  20913.   name="unregister_block"
  20914.   description="unregister an externally-allocated block of memory"
  20915. >
  20916.  
  20917. <_3clist
  20918.   href="lib_e_g.htm#get_vector"
  20919.   name="get_vector"
  20920.   description="return address of interrupt handler (DOS32)"
  20921. >
  20922.  
  20923. <_3clist
  20924.   href="lib_s_t.htm#set_vector"
  20925.   name="set_vector"
  20926.   description="set address of interrupt handler (DOS32)"
  20927. >
  20928.  
  20929. <_3clist
  20930.   href="lib_h_o.htm#lock_memory"
  20931.   name="lock_memory"
  20932.   description="ensure that a region of memory will never be swapped out (DOS32)"
  20933. >
  20934.  
  20935. <_3clist
  20936.   href="lib_h_o.htm#int_to_bytes"
  20937.   name="int_to_bytes"
  20938.   description="convert an integer to 4 bytes"
  20939. >
  20940.  
  20941. <_3clist
  20942.   href="lib_a_b.htm#bytes_to_int"
  20943.   name="bytes_to_int"
  20944.   description="convert 4 bytes to an integer"
  20945. >
  20946.  
  20947. <_3clist
  20948.   href="lib_h_o.htm#int_to_bits"
  20949.   name="int_to_bits"
  20950.   description="convert an integer to a sequence of bits"
  20951. >
  20952.  
  20953. <_3clist
  20954.   href="lib_a_b.htm#bits_to_int"
  20955.   name="bits_to_int"
  20956.   description="convert a sequence of bits to an integer"
  20957. >
  20958.  
  20959. <_3clist
  20960.   href="lib_a_b.htm#atom_to_float64"
  20961.   name="atom_to_float64"
  20962.   description="convert an atom, to a sequence of 8 bytes in IEEE 64-bit
  20963.      floating-point format"
  20964. >
  20965.  
  20966. <_3clist
  20967.   href="lib_a_b.htm#atom_to_float32"
  20968.   name="atom_to_float32"
  20969.   description="convert an atom, to a sequence of 4 bytes in IEEE 32-bit
  20970.      floating-point format"
  20971. >
  20972.  
  20973. <_3clist
  20974.   href="lib_e_g.htm#float64_to_atom"
  20975.   name="float64_to_atom"
  20976.   description="convert a sequence of 8 bytes in IEEE 64-bit floating-point
  20977.      format, to an atom"
  20978. >
  20979.  
  20980. <_3clist
  20981.   href="lib_e_g.htm#float32_to_atom"
  20982.   name="float32_to_atom"
  20983.   description="convert a sequence of 4 bytes in IEEE 32-bit floating-point
  20984.      format, to an atom"
  20985. >
  20986.  
  20987. <_3clist
  20988.   href="lib_s_t.htm#set_rand"
  20989.   name="set_rand"
  20990.   description="set the random number generator so it will generate a
  20991.      repeatable series of random numbers"
  20992. >
  20993.  
  20994. <_3clist
  20995.   href="lib_u_z.htm#use_vesa"
  20996.   name="use_vesa"
  20997.   description="force the use of the VESA graphics standard (DOS32)"
  20998. >
  20999.  
  21000. <_3clist
  21001.   href="lib_c_d.htm#crash_file"
  21002.   name="crash_file"
  21003.   description="specify the file for writing error diagnostics 
  21004.      if Euphoria detects an error in your program."
  21005. >
  21006.  
  21007. <_3clist
  21008.   href="lib_c_d.htm#crash_message"
  21009.   name="crash_message"
  21010.   description="specify a message to be printed if Euphoria detects an error
  21011.      in your program"
  21012. >
  21013.  
  21014. </table>
  21015.  
  21016. <p>
  21017. <hr>
  21018.  
  21019. <a name=dyn_call></a>
  21020. <font color="#FF0099" size=+1>
  21021. <br>
  21022.  
  21023. <_dul>2.14 Dynamic Calls</_dul>
  21024.  
  21025. </font>
  21026. <p>
  21027.  
  21028.       These routines let you call Euphoria procedures and functions using a
  21029.       unique integer known as a
  21030.       <font color="#993333"><b>routine identifier</b></font>, rather than by
  21031.       specifying the name of the routine.
  21032.  
  21033. <p>
  21034. <table border=0 cellspacing=2 cellpadding=2>
  21035.  
  21036. <_3clist
  21037.   href="lib_p_r.htm#routine_id"
  21038.   name="routine_id"
  21039.   description="get a unique identifying number for a Euphoria routine"
  21040. >
  21041.  
  21042. <_3clist
  21043.   href="lib_c_d.htm#call_proc"
  21044.   name="call_proc"
  21045.   description="call a Euphoria procedure using a routine id"
  21046. >
  21047.  
  21048. <_3clist
  21049.   href="lib_c_d.htm#call_func"
  21050.   name="call_func"
  21051.   description="call a Euphoria function using a routine id"
  21052. >
  21053.  
  21054. </table>
  21055.  
  21056. <p>
  21057. <hr>
  21058.  
  21059. <a name=call_c_func></a>
  21060. <font color="#FF0099" size=+1>
  21061. <br>
  21062.  
  21063. <_dul>2.15 Calling C Functions (WIN32 and Linux)</_dul>
  21064.  
  21065. </font>
  21066. <p>
  21067.  
  21068.  See
  21069.  <a href="platform.htm#win32plat"><font color="#5500FF"><b>platform.doc</b>
  21070.  </font></a> for a description of WIN32 and Linux programming in Euphoria.
  21071.  
  21072. <p>
  21073. <table border=0 cellspacing=2 cellpadding=2>
  21074.  
  21075. <_3clist
  21076.   href="lib_h_o.htm#open_dll"
  21077.   name="open_dll"
  21078.   description="open a Windows dynamic link library (.dll file) 
  21079.   or Linux shared library (.so file)"
  21080. >
  21081.  
  21082. <_3clist
  21083.   href="lib_c_d.htm#define_c_proc"
  21084.   name="define_c_proc"
  21085.   description="define a C function that is VOID (no value returned), or
  21086.      whose value your program will ignore"
  21087. >
  21088.  
  21089. <_3clist
  21090.   href="lib_c_d.htm#define_c_func"
  21091.   name="define_c_func"
  21092.   description="define a C function that returns a value that your program
  21093.      will use"
  21094. >
  21095.  
  21096. <_3clist
  21097.   href="lib_c_d.htm#define_c_var"
  21098.   name="define_c_var"
  21099.   description="get the memory address of a C variable."
  21100. >
  21101.  
  21102. <_3clist
  21103.   href="lib_c_d.htm#c_proc"
  21104.   name="c_proc"
  21105.   description="call a C function, ignoring any return value"
  21106. >
  21107.  
  21108. <_3clist
  21109.   href="lib_c_d.htm#c_func"
  21110.   name="c_func"
  21111.   description="call a C function and get the return value"
  21112. >
  21113.  
  21114. <_3clist
  21115.   href="lib_c_d.htm#call_back"
  21116.   name="call_back"
  21117.   description="get a 32-bit machine address for a Euphoria routine for use
  21118.      as a call-back address"
  21119. >
  21120.  
  21121. <_3clist
  21122.   href="lib_h_o.htm#message_box"
  21123.   name="message_box"
  21124.   description="pop up a small window to get a Yes/No/Cancel response from
  21125.      the user"
  21126. >
  21127.  
  21128. <_3clist
  21129.   href="lib_e_g.htm#free_console"
  21130.   name="free_console"
  21131.   description="delete the console text window"
  21132. >
  21133.  
  21134. <_3clist
  21135.   href="lib_h_o.htm#instance"
  21136.   name="instance"
  21137.   description="get the instance handle for the current program"
  21138. >
  21139.  
  21140. </table>
  21141.  
  21142. <_continue
  21143.   href="lib_a_b.htm"
  21144.   name="3. Alphabetical Listing of all Routines, From A to B"
  21145. >
  21146.  
  21147. </_width>
  21148. </body>
  21149. </html>
  21150. LIB_A_B.HTX
  21151. 22548
  21152. <_init_comment>
  21153. <html>
  21154. <head><title>Euphoria v2.2 Reference Manual Part II - Section 3</title>
  21155. </head>
  21156. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  21157.  
  21158. <_center><font color="#FF0099" size=+2>
  21159. <br>
  21160.                 3. Alphabetical Listing of all Routines
  21161. </font></_center>
  21162. <p> <br>
  21163.  
  21164. <_routine name="?">
  21165. <table border=0 cellspacing=2 cellpadding=2>
  21166.  
  21167.  
  21168.  <_2clist
  21169.   name="Syntax:"
  21170.   description="<font face = \"Arial, Helvetica\"> ? x
  21171. </font>"
  21172.  >
  21173.  <_2clist
  21174.   name="Description:"
  21175.   description=
  21176. "This is just a shorthand way of saying: <b>print(1, x)</b> -
  21177.  i.e. printing the value of an expression to the standard output."
  21178.  >
  21179. <_2clist
  21180.   name="Example:"
  21181.   description=""
  21182.  >
  21183. <_eucode>
  21184. ? {1, 2} + {3, 4}  -- will display {4, 6}
  21185.  
  21186. </_eucode>
  21187. <_2clist
  21188.   name="Comments:"
  21189.   description=
  21190. " ? differs slightly from print() since it will add new-lines to
  21191.  make the output more readable on your screen or wherever you
  21192.  have directed standard output.
  21193.  "
  21194.  >
  21195. <_2clist
  21196.   name="See Also:"
  21197.   description="<a href=\"lib_p_r.htm#print\">print</a>"
  21198.  >
  21199. </table>
  21200.  
  21201.  
  21202. <_routine name="abort">
  21203. <table border=0 cellspacing=2 cellpadding=2>
  21204.  
  21205.  
  21206.  <_2clist
  21207.   name="Syntax:"
  21208.   description="<font face = \"Arial, Helvetica\"> abort(i)
  21209. </font>"
  21210.  >
  21211.  <_2clist
  21212.   name="Description:"
  21213.   description=
  21214. "  Abort execution of the program. The argument i is a small integer
  21215.  status value to be returned to the operating system. A value of 0
  21216.  generally indicates successful completion of the program. Other
  21217.  values can indicate various kinds of errors. DOS batch (.bat)
  21218.  programs can read this value using the errorlevel feature.
  21219.  A Euphoria program can read this value using system_exec()."
  21220.  >
  21221. <_2clist
  21222.   name="Comments:"
  21223.   description=
  21224. " abort() is useful when a program is many levels deep in
  21225.  subroutine calls, and execution must end immediately, perhaps
  21226.  due to a severe error that has been detected.
  21227. <P>
  21228. If you don't use abort(), <font color=\"#993333\"><b>ex.exe/exw.exe/exu</b></font>
  21229.  will normally return
  21230.  an exit status code of 0. If your program fails with a
  21231.  Euphoria-detected compile-time or run-time error then a
  21232.  code of 1 is returned.
  21233.  "
  21234.  >
  21235. <_2clist
  21236.   name="Example:"
  21237.   description=""
  21238.  >
  21239. <_eucode>
  21240. if x = 0 then
  21241.     puts(ERR, "can't divide by 0 !!!\n")
  21242.     abort(1)
  21243. else
  21244.     z = y / x
  21245. end if
  21246.  
  21247. </_eucode>
  21248. <_2clist
  21249.   name="See Also:"
  21250.   description="<a href=\"lib_c_d.htm#crash_message\">crash_message</a>,
  21251. <a href=\"lib_s_t.htm#system_exec\">system_exec</a>"
  21252.  >
  21253. </table>
  21254.  
  21255.  
  21256. <_routine name="all_palette">
  21257. <table border=0 cellspacing=2 cellpadding=2>
  21258.  
  21259.  
  21260.  <_2clist
  21261.   name="Platform:"
  21262.   description="<font color=\"#CC3366\"><b> DOS32</b></font>"
  21263.  >
  21264.  
  21265.  <_2clist
  21266.   name="Syntax:"
  21267.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  21268.  all_palette(s)
  21269. </font>"
  21270.  >
  21271.  <_2clist
  21272.   name="Description:"
  21273.   description=
  21274. "  Specify new color intensities for the entire set of colors in the
  21275.  current graphics mode. s is a sequence of the form:<P>
  21276. {{r,g,b}, {r,g,b}, ..., {r,g,b}}
  21277. <P>
  21278. Each element specifies a new color intensity {red, green, blue}
  21279.  for the corresponding color number, starting with color number 0.
  21280.  The values for red, green and blue must be in the range 0 to 63."
  21281.  >
  21282. <_2clist
  21283.   name="Comments:"
  21284.   description=
  21285. " This executes much faster than if you were to use palette() to
  21286.  set the new color intensities one by one. This procedure can
  21287.  be used with read_bitmap() to quickly display a picture on the
  21288.  screen.
  21289.  "
  21290.  >
  21291. <_2clist
  21292.   name="Example Program:"
  21293.   description="<font color=\"#5500FF\"><b>demo\dos32\bitmap.ex</b></font>"
  21294.  >
  21295.  
  21296.  <_2clist
  21297.   name="See Also:"
  21298.   description="<a href=\"lib_e_g.htm#get_all_palette\">get_all_palette</a>,
  21299. <a href=\"lib_p_r.htm#palette\">palette</a>,
  21300. <a href=\"lib_p_r.htm#read_bitmap\">read_bitmap</a>,
  21301. <a href=\"lib_u_z.htm#video_config\">video_config</a>,
  21302. <a href=\"lib_e_g.htm#graphics_mode\">graphics_mode</a>"
  21303.  >
  21304. </table>
  21305.  
  21306.  
  21307. <_routine name="allocate">
  21308. <table border=0 cellspacing=2 cellpadding=2>
  21309.  
  21310.  
  21311.  <_2clist
  21312.   name="Syntax:"
  21313.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  21314.  a = allocate(i)
  21315. </font>"
  21316.  >
  21317.  <_2clist
  21318.   name="Description:"
  21319.   description=
  21320. "  Allocate i contiguous bytes of memory. Return the address of the
  21321.  block of memory, or return 0 if the memory can't be allocated.
  21322.  The address returned will be at least 4-byte aligned. "
  21323.  >
  21324. <_2clist
  21325.   name="Example:"
  21326.   description=""
  21327.  >
  21328. <_eucode>
  21329. buffer = allocate(100)
  21330. for i = 0 to 99 do
  21331.     poke(buffer+i, 0)
  21332. end for
  21333.  
  21334. </_eucode>
  21335. <_2clist
  21336.   name="See Also:"
  21337.   description="<a href=\"lib_e_g.htm#free\">free</a>,
  21338. <a href=\"lib_a_b.htm#allocate_low\">allocate_low</a>,
  21339. <a href=\"lib_p_r.htm#peek\">peek</a>,
  21340. <a href=\"lib_p_r.htm#poke\">poke</a>,
  21341. <a href=\"lib_c_d.htm#call\">call</a>"
  21342.  >
  21343. </table>
  21344.  
  21345.  
  21346. <_routine name="allocate_low">
  21347. <table border=0 cellspacing=2 cellpadding=2>
  21348.  
  21349.  
  21350.  <_2clist
  21351.   name="Platform:"
  21352.   description="<font color=\"#CC3366\"><b> DOS32</b></font>"
  21353.  >
  21354.  
  21355.  <_2clist
  21356.   name="Syntax:"
  21357.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  21358.  i2 = allocate_low(i1)
  21359. </font>"
  21360.  >
  21361.  <_2clist
  21362.   name="Description:"
  21363.   description=
  21364. "Allocate i1 contiguous bytes of low memory, i.e. conventional
  21365.  memory (address below 1 megabyte). Return the address
  21366.  of the block of memory, or return 0 if the memory can't be
  21367.  allocated. "
  21368.  >
  21369. <_2clist
  21370.   name="Comments:"
  21371.   description=
  21372. " Some DOS software interrupts require that you pass one or
  21373.  more addresses in registers. These addresses must be
  21374.  conventional memory addresses for DOS to be able to read or
  21375.  write to them.
  21376.  "
  21377.  >
  21378. <_2clist
  21379.   name="Example Program:"
  21380.   description="<font color=\"#5500FF\"><b>demo\dos32\dosint.ex</b></font>"
  21381.  >
  21382.  
  21383.  <_2clist
  21384.   name="See Also:"
  21385.   description="<a href=\"lib_c_d.htm#dos_interrupt\">dos_interrupt</a>,
  21386. <a href=\"lib_e_g.htm#free_low\">free_low</a>,
  21387. <a href=\"lib_a_b.htm#allocate\">allocate</a>,
  21388. <a href=\"lib_p_r.htm#peek\">peek</a>,
  21389. <a href=\"lib_p_r.htm#poke\">poke</a>"
  21390.  >
  21391. </table>
  21392.  
  21393.  
  21394. <_routine name="allocate_string">
  21395. <table border=0 cellspacing=2 cellpadding=2>
  21396.  
  21397.  
  21398.  <_2clist
  21399.   name="Syntax:"
  21400.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  21401.  a = allocate_string(s)
  21402. </font>"
  21403.  >
  21404.  <_2clist
  21405.   name="Description:"
  21406.   description=
  21407. "Allocate space for string sequence s. Copy s into this space
  21408.  along with a 0 terminating character. This is the format
  21409.  expected for C strings. The memory address of the string will
  21410.  be returned. If there is not enough memory available,
  21411.  0 will be returned. "
  21412.  >
  21413. <_2clist
  21414.   name="Comments:"
  21415.   description="To free the string, use free()."
  21416.  >
  21417. <_2clist
  21418.   name="Example:"
  21419.   description=""
  21420.  >
  21421. <_eucode>
  21422. atom title
  21423.  
  21424. title = allocate_string("The Wizard of Oz")
  21425.  
  21426. </_eucode>
  21427. <_2clist
  21428.   name="Example Program:"
  21429.   description="<font color=\"#5500FF\"><b>demo\win32\window.exw</b></font>"
  21430.  >
  21431.  
  21432.  <_2clist
  21433.   name="See Also:"
  21434.   description="
  21435.   <a href=\"lib_a_b.htm#allocate\">allocate</a>,
  21436.   <a href=\"lib_e_g.htm#free\">free</a>"
  21437.  >
  21438. </table>
  21439.  
  21440.  
  21441. <_routine name="allow_break">
  21442. <table border=0 cellspacing=2 cellpadding=2>
  21443.  
  21444.  
  21445.  <_2clist
  21446.   name="Syntax:"
  21447.   description="<font face = \"Arial, Helvetica\"> include file.e<BR>
  21448.  allow_break(i)
  21449. </font>"
  21450.  >
  21451.  <_2clist
  21452.   name="Description:"
  21453.   description=
  21454. "When i is 1 (true) control-c and control-Break can terminate
  21455.  your program when it tries to read input from the keyboard. When
  21456.  i is 0 (false) your program will not be terminated by control-c
  21457.  or control-Break."
  21458.  >
  21459. <_2clist
  21460.   name="Comments:"
  21461.   description=
  21462. "DOS will display ^C on the screen, even when your program cannot
  21463.  be terminated.
  21464. <P>
  21465. Initially your program can be terminated at any point where
  21466.  it tries to read from the keyboard. It could also be terminated
  21467.  by other input/output operations depending on options the user
  21468.  has set in his <b>config.sys</b> file. (Consult an MS-DOS manual for the BREAK
  21469.  command.) For some types of program this sudden termination could leave
  21470.  things in a messy state and might result in loss of data.
  21471.  allow_break(0) lets you avoid this situation.
  21472. <P>
  21473. You can find out if the user has pressed control-c or
  21474.  control-Break by calling check_break()."
  21475.  >
  21476. <_2clist
  21477.   name="Example:"
  21478.   description=""
  21479.  >
  21480. <_eucode>
  21481. allow_break(0)  -- don't let the user kill me!
  21482.  
  21483. </_eucode>
  21484. <_2clist
  21485.   name="See Also:"
  21486.   description="<a href=\"lib_c_d.htm#check_break\">check_break</a>"
  21487.  >
  21488. </table>
  21489.  
  21490.  
  21491. <_routine name="and_bits">
  21492. <table border=0 cellspacing=2 cellpadding=2>
  21493.  
  21494.  
  21495.  <_2clist
  21496.   name="Syntax:"
  21497.   description="<font face = \"Arial, Helvetica\"> x3 = and_bits(x1, x2)
  21498. </font>"
  21499.  >
  21500.  <_2clist
  21501.   name="Description:"
  21502.   description=
  21503. "Perform the logical AND operation on corresponding bits in
  21504.  x1 and x2. A bit in x3 will be 1 only if the corresponding
  21505.  bits in x1 and x2 are both 1."
  21506.  >
  21507. <_2clist
  21508.   name="Comments:"
  21509.   description=
  21510. "The arguments to this function may be atoms or sequences. The
  21511.  rules for <a href=\"refman_2.htm#26\">operations on sequences</a> apply.
  21512. <P>
  21513. The arguments must be representable as 32-bit numbers,
  21514.  either signed or unsigned.
  21515. <P>
  21516. If you intend to manipulate full 32-bit values, you should declare your
  21517.  variables as <font color=\"#993333\"><b>atom</b></font>, rather than
  21518.  integer. Euphoria's integer type is limited to 31-bits.
  21519. <P>
  21520. Results are treated as signed numbers. They will be
  21521.  negative when the highest-order bit is 1.
  21522. <P>
  21523. To understand the binary representation of a number you
  21524.  should display it in hexadecimal notation. Use the %x format
  21525.  of <a href=\"lib_p_r.htm#printf\">printf()</a>.
  21526.  "
  21527.  >
  21528. <_2clist
  21529.   name="Example 1:"
  21530.   description=""
  21531.  >
  21532. <_eucode>
  21533. a = and_bits(#0F0F0000, #12345678)
  21534. -- a is #02040000
  21535.  
  21536. </_eucode>
  21537. <_2clist
  21538.   name="Example 2:"
  21539.   description=""
  21540.  >
  21541. <_eucode>
  21542. a = and_bits(#FF, {#123456, #876543, #2211})
  21543. -- a is {#56, #43, #11}
  21544.  
  21545. </_eucode>
  21546. <_2clist
  21547.   name="Example 3:"
  21548.   description=""
  21549.  >
  21550. <_eucode>
  21551. a = and_bits(#FFFFFFFF, #FFFFFFFF)
  21552. -- a is -1
  21553. -- Note that #FFFFFFFF is a positive number,
  21554. -- but the result of a bitwise logical operation is interpreted
  21555. -- as a signed 32-bit number, so it's negative.
  21556.  
  21557. </_eucode>
  21558. <_2clist
  21559.   name="See Also:"
  21560.   description="<a href=\"lib_h_o.htm#or_bits\">or_bits</a>,
  21561. <a href=\"lib_u_z.htm#xor_bits\">xor_bits</a>,
  21562. <a href=\"lib_h_o.htm#not_bits\">not_bits</a>,
  21563. <a href=\"lib_h_o.htm#int_to_bits\">int_to_bits</a>"
  21564.  >
  21565. </table>
  21566.  
  21567.  
  21568. <_routine name="append">
  21569. <table border=0 cellspacing=2 cellpadding=2>
  21570.  
  21571.  
  21572.  <_2clist
  21573.   name="Syntax:"
  21574.   description="<font face = \"Arial, Helvetica\"> s2 = append(s1, x)
  21575. </font>"
  21576.  >
  21577.  <_2clist
  21578.   name="Description:"
  21579.   description=
  21580. "  Create a new sequence identical to s1 but with x added on the end
  21581.  as the last element. The length of s2 will be
  21582.  <a href=\"lib_h_o.htm#length\">length(s1)</a> + 1. "
  21583.  >
  21584. <_2clist
  21585.   name="Comments:"
  21586.   description=
  21587. " If x is an atom this is equivalent to <b>s2 = s1 & x</b>. If x is a
  21588.  sequence it is not equivalent.
  21589. <P>
  21590. The extra storage is allocated automatically and very
  21591.  efficiently with Euphoria's dynamic storage allocation.
  21592.  The case where s1 and s2 are actually the same variable
  21593.  (as in Example 1 below) is highly optimized.
  21594.  "
  21595.  >
  21596. <_2clist
  21597.   name="Example 1:"
  21598.   description=" You can use append() to dynamically grow a sequence, e.g."
  21599.  >
  21600. <_eucode>
  21601. sequence x
  21602.  
  21603. x = {}
  21604. for i = 1 to 10 do
  21605.     x = append(x, i)
  21606. end for
  21607. -- x is now {1,2,3,4,5,6,7,8,9,10}
  21608.  
  21609. </_eucode>
  21610. <_2clist
  21611.   name="Example 2:"
  21612.   description=" Any kind of Euphoria object can be appended to a sequence, e.g."
  21613.  >
  21614. <_eucode>
  21615. sequence x, y, z
  21616.  
  21617. x = {"fred", "barney"}
  21618. y = append(x, "wilma")
  21619. -- y is now {"fred", "barney", "wilma"}
  21620.  
  21621. z = append(append(y, "betty"), {"bam", "bam"})
  21622. -- z is now {"fred", "barney", "wilma", "betty", {"bam", "bam"}}
  21623.  
  21624. </_eucode>
  21625. <_2clist
  21626.   name="See Also:"
  21627.   description="<a href=\"lib_p_r.htm#prepend\">prepend</a>,
  21628.   <a href=\"refman_2.htm#27\">concatenation operator &</a>,
  21629.   <a href=\"refman_2.htm#28\">sequence-formation operator</a>"
  21630.  >
  21631. </table>
  21632.  
  21633.  
  21634. <_routine name="arccos">
  21635. <table border=0 cellspacing=2 cellpadding=2>
  21636.  
  21637.  
  21638.  <_2clist
  21639.   name="Syntax:"
  21640.   description="<font face = \"Arial, Helvetica\"> include misc.e<BR>x2 = arccos(x1)
  21641. </font>"
  21642.  >
  21643.  <_2clist
  21644.   name="Description:"
  21645.   description=
  21646. "  Return an angle with cosine equal to x1. "
  21647.  >
  21648. <_2clist
  21649.   name="Comments:"
  21650.   description=
  21651. " The argument, x1, must be in the range -1 to +1 inclusive.
  21652. <P>
  21653. A value between 0 and <a href=\"lib_p_r.htm#PI\">PI</a> radians will be
  21654. returned.
  21655. <P>
  21656. This function may be applied to an atom or to all elements
  21657.  of a sequence.
  21658. <P>
  21659. arccos() is not as fast as arctan().
  21660.  "
  21661.  >
  21662. <_2clist
  21663.   name="Example:"
  21664.   description=""
  21665.  >
  21666. <_eucode>
  21667. s = arccos({-1,0,1})
  21668. -- s is {3.141592654, 1.570796327, 0}
  21669.  
  21670. </_eucode>
  21671. <_2clist
  21672.   name="See Also:"
  21673.   description="<a href=\"lib_c_d.htm#cos\">cos</a>,
  21674. <a href=\"lib_a_b.htm#arcsin\">arcsin</a>,
  21675. <a href=\"lib_a_b.htm#arctan\">arctan</a>"
  21676.  >
  21677. </table>
  21678.  
  21679.  
  21680. <_routine name="arcsin">
  21681. <table border=0 cellspacing=2 cellpadding=2>
  21682.  
  21683.  
  21684.  <_2clist
  21685.   name="Syntax:"
  21686.   description="<font face = \"Arial, Helvetica\">include misc.e<BR>x2 = arcsin(x1)
  21687. </font>"
  21688.  >
  21689.  <_2clist
  21690.   name="Description:"
  21691.   description=
  21692. "  Return an angle with sine equal to x1. "
  21693.  >
  21694. <_2clist
  21695.   name="Comments:"
  21696.   description=
  21697. " The argument, x1, must be in the range -1 to +1 inclusive.
  21698. <P>
  21699. A value between -PI/2 and +PI/2 (radians) will be returned.
  21700. <P>
  21701. This function may be applied to an atom or to all elements
  21702.  of a sequence.
  21703. <P>
  21704. arcsin() is not as fast as arctan().
  21705.  "
  21706.  >
  21707. <_2clist
  21708.   name="Example:"
  21709.   description=""
  21710.  >
  21711. <_eucode>
  21712. s = arcsin({-1,0,1})
  21713. -- s is {-1.570796327, 0, 1.570796327}
  21714.  
  21715. </_eucode>
  21716. <_2clist
  21717.   name="See Also:"
  21718.   description="<a href=\"lib_s_t.htm#sin\">sin</a>,
  21719. <a href=\"lib_a_b.htm#arccos\">arccos</a>,
  21720. <a href=\"lib_a_b.htm#arctan\">arctan</a>"
  21721.  >
  21722. </table>
  21723.  
  21724.  
  21725. <_routine name="arctan">
  21726. <table border=0 cellspacing=2 cellpadding=2>
  21727.  
  21728.  
  21729.  <_2clist
  21730.   name="Syntax:"
  21731.   description="<font face = \"Arial, Helvetica\"> x2 = arctan(x1)
  21732. </font>"
  21733.  >
  21734.  <_2clist
  21735.   name="Description:"
  21736.   description=
  21737. "  Return an angle with tangent equal to x1. "
  21738.  >
  21739. <_2clist
  21740.   name="Comments:"
  21741.   description=
  21742. " A value between -PI/2 and PI/2 (radians) will be returned.
  21743. <P>
  21744. This function may be applied to an atom or to all elements
  21745.  of a sequence.
  21746. <P>
  21747. arctan() is faster than arcsin() or arccos().
  21748.  "
  21749.  >
  21750. <_2clist
  21751.   name="Example:"
  21752.   description=""
  21753.  >
  21754. <_eucode>
  21755. s = arctan({1,2,3})
  21756. -- s is {0.785398, 1.10715, 1.24905}
  21757.  
  21758. </_eucode>
  21759. <_2clist
  21760.   name="See Also:"
  21761.   description="<a href=\"lib_s_t.htm#tan\">tan</a>,
  21762. <a href=\"lib_a_b.htm#arcsin\">arcsin</a>,
  21763. <a href=\"lib_a_b.htm#arccos\">arccos</a>"
  21764.  >
  21765. </table>
  21766.  
  21767.  
  21768. <_routine name="atom">
  21769. <table border=0 cellspacing=2 cellpadding=2>
  21770.  
  21771.  
  21772.  <_2clist
  21773.   name="Syntax:"
  21774.   description="<font face = \"Arial, Helvetica\"> i = atom(x)
  21775. </font>"
  21776.  >
  21777.  <_2clist
  21778.   name="Description:"
  21779.   description=
  21780. "  Return 1 if x is an atom else return 0. "
  21781.  >
  21782. <_2clist
  21783.   name="Comments:"
  21784.   description=
  21785. " This serves to define the atom type. You can also call it
  21786.  like an ordinary function to determine if an object is an
  21787.  atom.
  21788.  "
  21789.  >
  21790. <_2clist
  21791.   name="Example 1:"
  21792.   description=""
  21793.  >
  21794. <_eucode>
  21795. atom a
  21796. a = 5.99
  21797.  
  21798. </_eucode>
  21799. <_2clist
  21800.   name="Example 2:"
  21801.   description=""
  21802.  >
  21803. <_eucode>
  21804. object line
  21805.  
  21806. line = gets(0)
  21807. if atom(line) then
  21808.     puts(SCREEN, "end of file\n")
  21809. end if
  21810.  
  21811. </_eucode>
  21812. <_2clist
  21813.   name="See Also:"
  21814.   description="<a href=\"lib_s_t.htm#sequence\">sequence</a>,
  21815.                <a href=\"lib_h_o.htm#object\">object</a>,
  21816.                <a href=\"lib_h_o.htm#integer\">integer</a>,
  21817.                <a href=\"refman_2.htm#1\">atoms and sequences</a>"
  21818.  >
  21819. </table>
  21820.  
  21821.  
  21822. <_routine name="atom_to_float32">
  21823. <table border=0 cellspacing=2 cellpadding=2>
  21824.  
  21825.  
  21826.  <_2clist
  21827.   name="Syntax:"
  21828.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  21829.  s = atom_to_float32(a1)
  21830. </font>"
  21831.  >
  21832.  <_2clist
  21833.   name="Description:"
  21834.   description=
  21835. "  Convert a Euphoria atom to a sequence of 4 single-byte values.
  21836.  These 4 bytes contain the representation of an IEEE
  21837.  floating-point number in 32-bit format. "
  21838.  >
  21839. <_2clist
  21840.   name="Comments:"
  21841.   description=
  21842. " Euphoria atoms can have values which are 64-bit IEEE
  21843.  floating-point numbers, so you may lose precision when you convert
  21844.  to 32-bits (16 significant digits versus 7). The range of
  21845.  exponents is much larger in 64-bit format (10 to the 308, versus
  21846.  10 to the 38), so some atoms may be too large or too small to
  21847.  represent in 32-bit format. In this case you will get one of the
  21848.  special 32-bit values:
  21849.  <a href=\"refman_2.htm#inf_nan\">inf or -inf (infinity or -infinity)</a>.
  21850. To avoid this, you can use atom_to_float64().
  21851. <P>
  21852. Integer values will also be converted to 32-bit floating-point
  21853.  format.
  21854.  "
  21855.  >
  21856. <_2clist
  21857.   name="Example:"
  21858.   description=""
  21859.  >
  21860. <_eucode>
  21861. fn = open("numbers.dat", "wb")
  21862. puts(fn, atom_to_float32(157.82)) -- write 4 bytes to a file
  21863.  
  21864. </_eucode>
  21865. <_2clist
  21866.   name="See Also:"
  21867.   description="<a href=\"lib_a_b.htm#atom_to_float64\">atom_to_float64</a>,
  21868. <a href=\"lib_e_g.htm#float32_to_atom\">float32_to_atom</a>"
  21869.  >
  21870. </table>
  21871.  
  21872.  
  21873. <_routine name="atom_to_float64">
  21874. <table border=0 cellspacing=2 cellpadding=2>
  21875.  
  21876.  
  21877.  <_2clist
  21878.   name="Syntax:"
  21879.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  21880.  s = atom_to_float64(a1)
  21881. </font>"
  21882.  >
  21883.  <_2clist
  21884.   name="Description:"
  21885.   description=
  21886. "  Convert a Euphoria atom to a sequence of 8 single-byte values.
  21887.  These 8 bytes contain the representation of an IEEE
  21888.  floating-point number in 64-bit format. "
  21889.  >
  21890. <_2clist
  21891.   name="Comments:"
  21892.   description=
  21893. " All Euphoria atoms have values which can be represented as
  21894.  64-bit IEEE floating-point numbers, so you can convert any atom
  21895.  to 64-bit format without losing any precision.
  21896. <P>
  21897. Integer values will also be converted to 64-bit floating-point
  21898.  format.
  21899.  "
  21900.  >
  21901. <_2clist
  21902.   name="Example:"
  21903.   description=""
  21904.  >
  21905. <_eucode>
  21906. fn = open("numbers.dat", "wb")
  21907. puts(fn, atom_to_float64(157.82)) -- write 8 bytes to a file
  21908.  
  21909. </_eucode>
  21910. <_2clist
  21911.   name="See Also:"
  21912.   description="<a href=\"lib_a_b.htm#atom_to_float32\">atom_to_float32</a>,
  21913. <a href=\"lib_e_g.htm#float64_to_atom\">float64_to_atom</a>"
  21914.  >
  21915. </table>
  21916.  
  21917.  
  21918. <_routine name="bits_to_int">
  21919. <table border=0 cellspacing=2 cellpadding=2>
  21920.  
  21921.  
  21922.  <_2clist
  21923.   name="Syntax:"
  21924.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  21925.  a = bits_to_int(s)
  21926. </font>"
  21927.  >
  21928.  <_2clist
  21929.   name="Description:"
  21930.   description=
  21931. "  Convert a sequence of binary 1's and 0's into a positive
  21932.  number. The least-significant bit is s[1]. "
  21933.  >
  21934. <_2clist
  21935.   name="Comments:"
  21936.   description=
  21937. " If you print s the bits will appear in \"reverse\" order, but
  21938.  it is convenient to have increasing subscripts access bits of
  21939.  increasing significance.
  21940.  "
  21941.  >
  21942. <_2clist
  21943.   name="Example:"
  21944.   description=""
  21945.  >
  21946. <_eucode>
  21947. a = bits_to_int({1,1,1,0,1})
  21948. -- a is 23 (binary 10111)
  21949.  
  21950. </_eucode>
  21951. <_2clist
  21952.   name="See Also:"
  21953.   description="<a href=\"lib_h_o.htm#int_to_bits\">int_to_bits</a>,
  21954.                <a href=\"refman_2.htm#26\">operations on sequences</a>"
  21955.  >
  21956. </table>
  21957.  
  21958.  
  21959. <_routine name="bk_color">
  21960. <table border=0 cellspacing=2 cellpadding=2>
  21961.  
  21962.  
  21963.  <_2clist
  21964.   name="Syntax:"
  21965.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  21966.  bk_color(i)
  21967. </font>"
  21968.  >
  21969.  <_2clist
  21970.   name="Description:"
  21971.   description=
  21972. "Set the background color to one of the 16 standard colors. In
  21973.  <font color=\"#CC3366\">pixel-graphics modes</font> the whole
  21974.  screen is affected immediately. In 
  21975.  <font color=\"#CC3366\">text modes</font> any new characters
  21976.  that you print will have the new background color."
  21977.  >
  21978. <_2clist
  21979.   name="Comments:"
  21980.   description=
  21981. "The 16 standard colors are defined as constants in
  21982.  <font color=\"#5500FF\"><b>graphics.e</b></font>
  21983. <P>
  21984. In <font color=\"#CC3366\">pixel-graphics modes</font>, color 0 which is
  21985.  normally BLACK, will be set to the same {r,g,b} palette value as
  21986.  color number i.
  21987. <p>
  21988. In some <font color=\"#CC3366\">pixel-graphics modes</font>, there is a
  21989.  <i>border</i> color that appears at the edges of the screen. In 256-color
  21990.  modes, this is the 17th color in the palette. You can control it as you
  21991.  would any other color.
  21992. <P>
  21993. In <font color=\"#CC3366\">text modes</font>, to restore the original
  21994.  background color when
  21995.  your program finishes, e.g. 0 - BLACK, you must call bk_color(0).
  21996.  If the cursor is at the bottom line of the screen, you may have
  21997.  to actually print something before terminating your program.
  21998.  Printing '\n' may be enough."
  21999.  >
  22000. <_2clist
  22001.   name="Example:"
  22002.   description=""
  22003.  >
  22004. <_eucode>
  22005. bk_color(BLACK)
  22006.  
  22007. </_eucode>
  22008. <_2clist
  22009.   name="See Also:"
  22010.   description="
  22011.   <a href=\"lib_s_t.htm#text_color\">text_color</a>,
  22012.   <a href=\"lib_p_r.htm#palette\">palette</a>"
  22013.  >
  22014. </table>
  22015.  
  22016.  
  22017. <_routine name="bytes_to_int">
  22018. <table border=0 cellspacing=2 cellpadding=2>
  22019.  
  22020.  
  22021.  <_2clist
  22022.   name="Syntax:"
  22023.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  22024.  a = bytes_to_int(s)
  22025. </font>"
  22026.  >
  22027.  <_2clist
  22028.   name="Description:"
  22029.   description=
  22030. "Convert a 4-element sequence of byte values to an atom.
  22031.  The elements of s are in the order expected for a 32-bit
  22032.  integer on the 386+, i.e. least-significant byte first."
  22033.  >
  22034. <_2clist
  22035.   name="Comments:"
  22036.   description=
  22037. "The result could be greater than the integer type allows, so you should
  22038.  assign it to an <font color=\"#993333\"><b>atom</b></font>.
  22039. <P>
  22040. s would normally contain positive values that have been read
  22041.  using peek() from 4 consecutive memory locations."
  22042.  >
  22043. <_2clist
  22044.   name="Example:"
  22045.   description=""
  22046.  >
  22047. <_eucode>
  22048. atom int32
  22049.  
  22050. int32 = bytes_to_int({37,1,0,0})
  22051. -- int32 is 37 + 256*1 = 293
  22052.  
  22053. </_eucode>
  22054. <_2clist
  22055.   name="See Also:"
  22056.   description="<a href=\"lib_h_o.htm#int_to_bytes\">int_to_bytes</a>,
  22057. <a href=\"lib_a_b.htm#bits_to_int\">bits_to_int</a>,
  22058. <a href=\"lib_p_r.htm#peek\">peek</a>,
  22059. <a href=\"lib_p_r.htm#peek4s\">peek4s</a>,
  22060. <a href=\"lib_p_r.htm#peek4u\">peek4u</a>,
  22061. <a href=\"lib_p_r.htm#poke\">poke</a>"
  22062.  >
  22063. </table>
  22064.  
  22065. <_continue
  22066.   href="lib_c_d.htm"
  22067.   name="From C to D"
  22068. >
  22069.  
  22070. </body>
  22071. </html>
  22072. LIB_C_D.HTX
  22073. 43490
  22074. <_init_comment>
  22075. <html>
  22076. <head><title>Euphoria v2.2 Reference Manual Part II - Section 3</title>
  22077. </head>
  22078. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  22079. <br>
  22080.  
  22081.  
  22082. <_routine name="call">
  22083. <table border=0 cellspacing=2 cellpadding=2>
  22084.  
  22085.  
  22086.  <_2clist
  22087.   name="Syntax:"
  22088.   description="<font face = \"Arial, Helvetica\"> call(a)
  22089. </font>"
  22090.  >
  22091.  <_2clist
  22092.   name="Description:"
  22093.   description=
  22094. "Call a machine language routine that starts at address a. This
  22095.  routine must execute a RET instruction #C3 to return control
  22096.  to Euphoria. The routine should save and restore any registers
  22097.  that it uses."
  22098.  >
  22099. <_2clist
  22100.   name="Comments:"
  22101.   description=
  22102. "You can allocate a block of memory for the routine and then poke
  22103.  in the bytes of machine code. You might allocate other blocks of
  22104.  memory for data and parameters that the machine code can operate
  22105.  on. The addresses of these blocks could be poked into the
  22106.  machine code."
  22107.  >
  22108. <_2clist
  22109.   name="Example Program:"
  22110.   description="<font color=\"#5500FF\"><b>demo\dos32\callmach.ex</b></font>"
  22111.  >
  22112.  
  22113.  <_2clist
  22114.   name="See Also:"
  22115.   description="<a href=\"lib_a_b.htm#allocate\">allocate</a>,
  22116. <a href=\"lib_e_g.htm#free\">free</a>,
  22117. <a href=\"lib_p_r.htm#peek\">peek</a>,
  22118. <a href=\"lib_p_r.htm#poke\">poke</a>,
  22119. <a href=\"lib_p_r.htm#poke4\">poke4</a>"
  22120.  >
  22121. </table>
  22122.  
  22123.  
  22124. <_routine name="call_back">
  22125. <table border=0 cellspacing=2 cellpadding=2>
  22126.  
  22127.  
  22128.  <_2clist
  22129.   name="Platform:"
  22130.   description="<font color=\"#CC3366\"><b>WIN32, Linux</b></font>"
  22131.  >
  22132.  
  22133.  <_2clist
  22134.   name="Syntax:"
  22135.   description="<font face = \"Arial, Helvetica\"> include dll.e<br>
  22136.  a = call_back(i)
  22137. </font>"
  22138.  >
  22139.  <_2clist
  22140.   name="Description:"
  22141.   description=
  22142. "Get a machine address for the Euphoria routine with
  22143.  <font color=\"#993333\"><b>routine id</b></font> i.
  22144.  This address can be
  22145.  used by Windows, or an external C routine in a Windows <b>.</b>dll, 
  22146.  or Linux shared library (.so), as a
  22147.  32-bit \"call-back\" address for calling your Euphoria routine."
  22148.  >
  22149. <_2clist
  22150.   name="Comments:"
  22151.   description=
  22152. "You can set up as many call-back functions as you like, but they
  22153.  must all be Euphoria functions (or types) with 0 to 8 arguments.
  22154. <P>
  22155. When your routine is called, the argument values will all be
  22156.  32-bit unsigned (positive) values. You should declare each
  22157.  parameter of your routine as <font color=\"#993333\"><b>atom</b></font>,
  22158.  unless you want to impose
  22159.  tighter checking. Your routine must return a 32-bit integer
  22160.  value."
  22161.  >
  22162. <_2clist
  22163.   name="Example Program:"
  22164.   description="<font color=\"#5500FF\"><b>demo\win32\window.exw,
  22165.   demo\linux\qsort.exu</b></font>"
  22166.  >
  22167.  
  22168.  <_2clist
  22169.   name="See Also:"
  22170.   description="<a href=\"lib_p_r.htm#routine_id\">routine_id</a>,
  22171.  <a href=\"platform.htm#callback\"><font color=\"#5500FF\"><b>platform.doc</b>
  22172.  </font></a>"
  22173.  >
  22174. </table>
  22175.  
  22176.  
  22177. <_routine name="c_func">
  22178. <table border=0 cellspacing=2 cellpadding=2>
  22179.  
  22180.  
  22181.  <_2clist
  22182.   name="Platform:"
  22183.   description="<font color=\"#CC3366\"><b>WIN32, Linux</b></font>"
  22184.  >
  22185.  
  22186.  <_2clist
  22187.   name="Syntax:"
  22188.   description="<font face = \"Arial, Helvetica\"> a = c_func(i, s)
  22189. </font>"
  22190.  >
  22191.  <_2clist
  22192.   name="Description:"
  22193.   description=
  22194. "Call the C function with <font color=\"#993333\"><b>routine id</b></font> i.
  22195.  i must be a valid routine
  22196.  id returned by define_c_func(). s is a sequence of argument
  22197.  values of length n, where n is the number of arguments required
  22198.  by the function. a will be the result returned by the C function."
  22199.  >
  22200. <_2clist
  22201.   name="Comments:"
  22202.   description=
  22203. "If the C function does not take any arguments then s should
  22204.  be {}.
  22205.  <p>
  22206.  If you pass an argument value which contains a fractional part, 
  22207.  where the C function expects a C integer type, the argument will
  22208.   be rounded towards 0. e.g. 5.9 will be passed as 5, -5.9 will be passed
  22209.    as -5."
  22210.  >
  22211. <_2clist
  22212.   name="Example:"
  22213.   description=""
  22214.  >
  22215. <_eucode>
  22216. atom user32, hwnd, ps, hdc
  22217. integer BeginPaint
  22218.  
  22219. -- open user32.dll - it contains the BeginPaint C function
  22220. user32 = open_dll("user32.dll")
  22221.  
  22222. -- the C function BeginPaint takes a C int argument and
  22223. -- a C pointer, and returns a C int as a result:
  22224. BeginPaint = define_c_func(user32, "BeginPaint",
  22225.                            {C_INT, C_POINTER}, C_INT)
  22226.  
  22227. -- call BeginPaint, passing hwnd and ps as the arguments,
  22228. -- hdc is assigned the result:
  22229. hdc = c_func(BeginPaint, {hwnd, ps})
  22230.  
  22231.  </_eucode>
  22232. <_2clist
  22233.   name="See Also:"
  22234.   description="<a href=\"lib_c_d.htm#c_proc\">c_proc</a>,
  22235. <a href=\"lib_c_d.htm#define_c_func\">define_c_func</a>,
  22236. <a href=\"lib_h_o.htm#open_dll\">open_dll</a>,
  22237. <a href=\"platform.htm#call_cfunc\"><font color=\"#5500FF\"><b>platform.doc</b>
  22238. </font></a>"
  22239.  >
  22240. </table>
  22241.  
  22242.  
  22243. <_routine name="c_proc">
  22244. <table border=0 cellspacing=2 cellpadding=2>
  22245.  
  22246.  
  22247.  <_2clist
  22248.   name="Platform:"
  22249.   description="<font color=\"#CC3366\"><b>WIN32, Linux</b></font>"
  22250.  >
  22251.  
  22252.  <_2clist
  22253.   name="Syntax:"
  22254.   description="<font face = \"Arial, Helvetica\"> c_proc(i, s)
  22255. </font>"
  22256.  >
  22257.  <_2clist
  22258.   name="Description:"
  22259.   description=
  22260. "Call the C function with <font color=\"#993333\"><b>routine id</b></font> i.
  22261.  i must be a valid routine
  22262.  id returned by define_c_proc(). s is a sequence of argument
  22263.  values of length n, where n is the number of arguments required
  22264.  by the function."
  22265.  >
  22266. <_2clist
  22267.   name="Comments:"
  22268.   description=
  22269. "If the C function does not take any arguments then s should
  22270.  be {}.
  22271.  <p>
  22272.  If you pass an argument value which contains a fractional part, 
  22273.  where the C function expects a C integer type, the argument will
  22274.  be rounded towards 0. e.g. 5.9 will be passed as 5, -5.9 will be passed
  22275.    as -5."
  22276.  >
  22277. <_2clist
  22278.   name="Example:"
  22279.   description=""
  22280.  >
  22281. <_eucode>
  22282. atom user32, hwnd, rect
  22283. integer GetClientRect
  22284.  
  22285. -- open user32.dll - it contains the GetClientRect C function
  22286. user32 = open_dll("user32.dll")
  22287.  
  22288. -- GetClientRect is a VOID C function that takes a C int
  22289. -- and a C pointer as its arguments:
  22290. GetClientRect = define_c_proc(user32, "GetClientRect",
  22291.                               {C_INT, C_POINTER})
  22292.  
  22293. -- pass hwnd and rect as the arguments
  22294. c_proc(GetClientRect, {hwnd, rect})
  22295.  
  22296.  </_eucode>
  22297. <_2clist
  22298.   name="See Also:"
  22299.   description="<a href=\"lib_c_d.htm#c_func\">c_func</a>,
  22300. <a href=\"lib_c_d.htm#define_c_proc\">define_c_proc</a>,
  22301. <a href=\"lib_h_o.htm#open_dll\">open_dll</a>,
  22302. <a href=\"platform.htm#call_cfunc\"><font color=\"#5500FF\"><b>platform.doc</b>
  22303. </font></a>"
  22304.  >
  22305. </table>
  22306.  
  22307.  
  22308. <_routine name="call_func">
  22309. <table border=0 cellspacing=2 cellpadding=2>
  22310.  
  22311.  
  22312.  <_2clist
  22313.   name="Syntax:"
  22314.   description="<font face = \"Arial, Helvetica\"> x = call_func(i, s)
  22315. </font>"
  22316.  >
  22317.  <_2clist
  22318.   name="Description:"
  22319.   description=
  22320. "Call the user-defined Euphoria function with
  22321.  <font color=\"#993333\"><b>routine id</b></font> i.
  22322.  i must be a valid routine id returned by routine_id(). s must
  22323.  be a sequence of argument values of length n, where n is the
  22324.  number of arguments required by function i. x will be the
  22325.  result returned by function i. "
  22326.  >
  22327. <_2clist
  22328.   name="Comments:"
  22329.   description=
  22330. " If function i does not take any arguments then s should be {}.
  22331.  "
  22332.  >
  22333. <_2clist
  22334.   name="Example Program:"
  22335.   description="<font color=\"#5500FF\"><b>demo\csort.ex</b></font>"
  22336.  >
  22337.  
  22338.  <_2clist
  22339.   name="See Also:"
  22340.   description="<a href=\"lib_c_d.htm#call_proc\">call_proc</a>,
  22341. <a href=\"lib_p_r.htm#routine_id\">routine_id</a>"
  22342.  >
  22343. </table>
  22344.  
  22345.  
  22346. <_routine name="call_proc">
  22347. <table border=0 cellspacing=2 cellpadding=2>
  22348.  
  22349.  
  22350.  <_2clist
  22351.   name="Syntax:"
  22352.   description="<font face = \"Arial, Helvetica\"> call_proc(i, s)
  22353. </font>"
  22354.  >
  22355.  <_2clist
  22356.   name="Description:"
  22357.   description=
  22358. "Call the user-defined Euphoria procedure with
  22359.  <font color=\"#993333\"><b>routine id</b></font> i.
  22360.  i must be a valid routine id returned by routine_id(). s must be
  22361.  a sequence of argument values of length n, where n is the number
  22362.  of arguments required by procedure i. "
  22363.  >
  22364. <_2clist
  22365.   name="Comments:"
  22366.   description=
  22367. " If procedure i does not take any arguments then s should be {}.
  22368.  "
  22369.  >
  22370. <_2clist
  22371.   name="Example:"
  22372.   description=""
  22373.  >
  22374. <_eucode>
  22375. global integer foo_id
  22376.  
  22377. procedure x()
  22378.     call_proc(foo_id, {1, "Hello World\n"})
  22379. end procedure
  22380.  
  22381. procedure foo(integer a, sequence s)
  22382.     puts(a, s)
  22383. end procedure
  22384.  
  22385. foo_id = routine_id("foo")
  22386.  
  22387. x()
  22388.  
  22389.  </_eucode>
  22390. <_2clist
  22391.   name="See Also:"
  22392.   description="<a href=\"lib_c_d.htm#call_func\">call_func</a>,
  22393. <a href=\"lib_p_r.htm#routine_id\">routine_id</a>"
  22394.  >
  22395. </table>
  22396.  
  22397.  
  22398. <_routine name="chdir">
  22399. <table border=0 cellspacing=2 cellpadding=2>
  22400.  
  22401.  <_2clist
  22402.   name="Syntax:"
  22403.   description="<font face = \"Arial, Helvetica\"> include file.e<BR>
  22404.  i = chdir(s)
  22405. </font>"
  22406.  >
  22407.  <_2clist
  22408.   name="Description:"
  22409.   description=
  22410. "Set the current directory to the path given by sequence s. s must name
  22411.  an existing directory on the system. If successful, chdir() returns 1. 
  22412.  If unsuccessful, chdir() returns 0."
  22413.  >
  22414. <_2clist
  22415.   name="Comments:"
  22416.   description=
  22417. "By setting the current directory, you can refer to files in that
  22418.  directory using just the file name.
  22419. <P>
  22420. The function current_dir() will return the name of the current directory.
  22421. <P>
  22422. On DOS32 and WIN32 the current directory is a global property shared
  22423. by all the processes running under one shell. On Linux, a subprocess
  22424. can change the current directory for itself, but this won't
  22425. affect the current directory of its parent process."
  22426.  
  22427.  >
  22428. <_2clist
  22429.   name="Example:"
  22430.   description=""
  22431.  >
  22432. <_eucode>
  22433. if chdir("c:\\euphoria") then
  22434.     f = open("readme.doc", "r")
  22435. else
  22436.     puts(1, "Error: No euphoria directory?\n")
  22437. end if
  22438. </_eucode>
  22439. <_2clist
  22440.   name="See Also:"
  22441.   description="<a href=\"lib_c_d.htm#current_dir\">current_dir</a>"
  22442.  >
  22443. </table>
  22444.  
  22445.  
  22446. <_routine name="check_break">
  22447. <table border=0 cellspacing=2 cellpadding=2>
  22448.  
  22449.  
  22450.  <_2clist
  22451.   name="Syntax:"
  22452.   description="<font face = \"Arial, Helvetica\"> include file.e<BR>
  22453.  i = check_break()
  22454. </font>"
  22455.  >
  22456.  <_2clist
  22457.   name="Description:"
  22458.   description=
  22459. "Return the number of times that control-c or control-Break have
  22460.  been pressed since the last call to check_break(), or since the
  22461.  beginning of the program if this is the first call."
  22462.  >
  22463. <_2clist
  22464.   name="Comments:"
  22465.   description=
  22466. "This is useful after you have called allow_break(0) which
  22467.  prevents control-c or control-Break from terminating your
  22468.  program. You can use check_break() to find out if the user
  22469.  has pressed one of these keys. You might then perform some action
  22470.  such as a graceful shutdown of your program.
  22471. <P>
  22472. Neither control-c nor control-Break will be returned as input
  22473.  characters when you read the keyboard. You can only detect
  22474.  them by calling check_break()."
  22475.  >
  22476. <_2clist
  22477.   name="Example:"
  22478.   description=""
  22479.  >
  22480. <_eucode>
  22481. k = get_key()
  22482. if check_break() then
  22483.     temp = graphics_mode(-1)
  22484.     puts(1, "Shutting down...")
  22485.     save_all_user_data()
  22486.     abort(1)
  22487. end if
  22488.  
  22489.  </_eucode>
  22490. <_2clist
  22491.   name="See Also:"
  22492.   description="<a href=\"lib_a_b.htm#allow_break\">allow_break</a>,
  22493. <a href=\"lib_e_g.htm#get_key\">get_key</a>"
  22494.  >
  22495. </table>
  22496.  
  22497.  
  22498. <_routine name="clear_screen">
  22499. <table border=0 cellspacing=2 cellpadding=2>
  22500.  
  22501.  
  22502.  <_2clist
  22503.   name="Syntax:"
  22504.   description="<font face = \"Arial, Helvetica\"> clear_screen()
  22505. </font>"
  22506.  >
  22507.  <_2clist
  22508.   name="Description:"
  22509.   description=
  22510. "Clear the screen using the current background color (may be set
  22511.  by bk_color())."
  22512.  >
  22513. <_2clist
  22514.   name="Comments:"
  22515.   description=
  22516. "This works in all <font color=\"#CC3366\">text and pixel-graphics
  22517.  modes</font>."
  22518.  >
  22519. <_2clist
  22520.   name="See Also:"
  22521.   description="<a href=\"lib_a_b.htm#bk_color\">bk_color</a>,
  22522. <a href=\"lib_e_g.htm#graphics_mode\">graphics_mode</a>"
  22523.  >
  22524. </table>
  22525.  
  22526.  
  22527. <_routine name="close">
  22528. <table border=0 cellspacing=2 cellpadding=2>
  22529.  
  22530.  
  22531.  <_2clist
  22532.   name="Syntax:"
  22533.   description="<font face = \"Arial, Helvetica\"> close(fn)
  22534. </font>"
  22535.  >
  22536.  <_2clist
  22537.   name="Description:"
  22538.   description=
  22539. "  Close a file or device and flush out any still-buffered
  22540.  characters. "
  22541.  >
  22542. <_2clist
  22543.   name="Comments:"
  22544.   description=
  22545. " Any still-open files will be closed automatically when your
  22546.  program terminates.
  22547.  "
  22548.  >
  22549. <_2clist
  22550.   name="See Also:"
  22551.   description="<a href=\"lib_h_o.htm#open\">open</a>,
  22552.                <a href=\"lib_e_g.htm#flush\">flush</a>"
  22553.  >
  22554. </table>
  22555.  
  22556.  
  22557. <_routine name="command_line">
  22558. <table border=0 cellspacing=2 cellpadding=2>
  22559.  
  22560.  
  22561.  <_2clist
  22562.   name="Syntax:"
  22563.   description="<font face = \"Arial, Helvetica\"> s = command_line()
  22564. </font>"
  22565.  >
  22566.  <_2clist
  22567.   name="Description:"
  22568.   description=
  22569. "Return a sequence of strings, where each string is a word from
  22570.  the <a href=\"refman_1.htm#3\">command-line</a> that started
  22571.  your program. The first word will be the path to either the Euphoria
  22572.  executable, <b><font color=\"#993333\">ex.exe</font>,
  22573.  <font color=\"#993333\">exw.exe</font> </b>or<b>
  22574.   <font color=\"#993333\">exu</font></b>,
  22575.   or to
  22576.  your <font color=\"#993333\"><b>bound executable</b></font> file. 
  22577.  The next word
  22578.  is either the name of your Euphoria main file, or (again) the path
  22579.  to your bound executable file. After
  22580.  that will come any extra words typed by the user. You can use
  22581.  these words in your program."
  22582.  >
  22583. <_2clist
  22584.   name="Comments:"
  22585.   description=
  22586. "The Euphoria interpreter itself does not use any
  22587.  command-line options. You are free to use any options for your own program.
  22588. <P>
  22589. If you <font color=\"#993333\"><b>bind</b></font> your program you will
  22590.  find that all command-line arguments remain the same, except for the first
  22591.  two, even though your user no longer types \"ex\" on the
  22592.  command-line (see examples below).
  22593.  "
  22594.  >
  22595. <_2clist
  22596.   name="Example 1:"
  22597.   description=""
  22598.  >
  22599. <_eucode>
  22600. -- The user types:  ex myprog myfile.dat 12345
  22601.  
  22602. cmd = command_line()
  22603.  
  22604. -- cmd will be:
  22605.       {"C:\EUPHORIA\BIN\EX.EXE",
  22606.        "myprog",
  22607.        "myfile.dat",
  22608.        "12345"}
  22609.  
  22610.  </_eucode>
  22611. <_2clist
  22612.   name="Example 2:"
  22613.   description=""
  22614.  >
  22615. <_eucode>
  22616. -- Your program is bound with the name "myprog.exe"
  22617. -- and is stored in the directory c:\myfiles
  22618. -- The user types:  myprog myfile.dat 12345
  22619.  
  22620. cmd = command_line()
  22621.  
  22622. -- cmd will be:
  22623.        {"C:\MYFILES\MYPROG.EXE",
  22624.         "C:\MYFILES\MYPROG.EXE", -- spacer
  22625.         "myfile.dat",
  22626.         "12345"}
  22627.  
  22628. -- Note that all arguments remain the same as example 1
  22629. -- except for the first two. The second argument is always
  22630. -- the same as the first and is inserted to keep the numbering
  22631. -- of the subsequent arguments the same, whether your program
  22632. -- is bound as a .exe or not.
  22633.  
  22634.  </_eucode>
  22635. <_2clist
  22636.   name="See Also:"
  22637.   description="<a href=\"lib_e_g.htm#getenv\">getenv</a>"
  22638.  >
  22639. </table>
  22640.  
  22641.  
  22642. <_routine name="compare">
  22643. <table border=0 cellspacing=2 cellpadding=2>
  22644.  
  22645.  
  22646.  <_2clist
  22647.   name="Syntax:"
  22648.   description="<font face = \"Arial, Helvetica\"> i = compare(x1, x2)
  22649. </font>"
  22650.  >
  22651.  <_2clist
  22652.   name="Description:"
  22653.   description=
  22654. "  Return 0 if objects x1 and x2 are identical, 1 if x1 is greater
  22655.  than x2, -1 if x1 is less than x2. Atoms are considered to be
  22656.  less than sequences. Sequences are compared \"alphabetically\"
  22657.  starting with the first element until a difference is found. "
  22658.  >
  22659. <_2clist
  22660.   name="Example 1:"
  22661.   description=""
  22662.  >
  22663. <_eucode>
  22664. x = compare({1,2,{3,{4}},5}, {2-1,1+1,{3,{4}},6-1})
  22665. -- identical, x is 0
  22666.  
  22667.  </_eucode>
  22668. <_2clist
  22669.   name="Example 2:"
  22670.   description=""
  22671.  >
  22672. <_eucode>
  22673. if compare("ABC", "ABCD") < 0 then   -- -1
  22674.     -- will be true: ABC is "less" because it is shorter
  22675. end if
  22676.  
  22677.  </_eucode>
  22678. <_2clist
  22679.   name="Example 3:"
  22680.   description=""
  22681.  >
  22682. <_eucode>
  22683. x = compare({12345, 99999, -1, 700, 2},
  22684.             {12345, 99999, -1, 699, 3, 0})
  22685. -- x will be 1 because 700 > 699
  22686.  
  22687.  </_eucode>
  22688. <_2clist
  22689.   name="Example 4:"
  22690.   description=""
  22691.  >
  22692. <_eucode>
  22693. x = compare('a', "a")
  22694. -- x will be -1 because 'a' is an atom
  22695. -- while "a" is a sequence
  22696.  
  22697.  </_eucode>
  22698. <_2clist
  22699.   name="See Also:"
  22700.   description="<a href=\"lib_e_g.htm#equal\">equal</a>, 
  22701.                <a href=\"refman_2.htm#23\">relational operators</a>,
  22702.                <a href=\"refman_2.htm#26\">operations on sequences</a>"
  22703.  >
  22704. </table>
  22705.  
  22706.  
  22707. <_routine name="cos">
  22708. <table border=0 cellspacing=2 cellpadding=2>
  22709.  
  22710.  
  22711.  <_2clist
  22712.   name="Syntax:"
  22713.   description="<font face = \"Arial, Helvetica\"> x2 = cos(x1)
  22714. </font>"
  22715.  >
  22716.  <_2clist
  22717.   name="Description:"
  22718.   description=
  22719. "  Return the cosine of x1, where x1 is in radians. "
  22720.  >
  22721. <_2clist
  22722.   name="Comments:"
  22723.   description=
  22724. " This function may be applied to an atom or to all elements
  22725.  of a sequence.
  22726.  "
  22727.  >
  22728. <_2clist
  22729.   name="Example:"
  22730.   description=""
  22731.  >
  22732. <_eucode>
  22733. x = cos({.5, .6, .7})
  22734.  
  22735. -- x is {0.8775826, 0.8253356, 0.7648422}
  22736.  
  22737.  </_eucode>
  22738. <_2clist
  22739.   name="See Also:"
  22740.   description="<a href=\"lib_s_t.htm#sin\">sin</a>,
  22741. <a href=\"lib_s_t.htm#tan\">tan</a>,
  22742. <a href=\"lib_h_o.htm#log\">log</a>,
  22743. <a href=\"lib_s_t.htm#sqrt\">sqrt</a>"
  22744.  >
  22745. </table>
  22746.  
  22747.  
  22748. <_routine name="crash_file">
  22749. <table border=0 cellspacing=2 cellpadding=2>
  22750.  
  22751.  
  22752.  <_2clist
  22753.   name="Syntax:"
  22754.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  22755.  crash_file(s)
  22756. </font>"
  22757.  >
  22758.  <_2clist
  22759.   name="Description:"
  22760.   description=
  22761. "Specify a file name, s, for holding error diagnostics if
  22762.  Euphoria must stop your program due to a compile-time or
  22763.  run-time error. "
  22764.  >
  22765. <_2clist
  22766.   name="Comments:"
  22767.   description=
  22768. "Normally Euphoria prints a diagnostic message such as
  22769.  \"syntax error\" or \"divide by zero\" on the screen, as well as
  22770.  dumping debugging information into
  22771.  <font color=\"#993333\"><b>ex.err</b></font> in the current directory. 
  22772.  By calling crash_file()
  22773.  you can control the directory and file name where the debugging information
  22774.  will be written.
  22775. <P>
  22776. s may be empty, i.e. \"\". In this case no diagnostics or debugging 
  22777. information will be written to either a file or the screeen. 
  22778. s might also be \"NUL\" or \"/dev/null\", in which case diagnostics will 
  22779. be written to the screen, but the ex.err information will be discarded.
  22780.  
  22781. <P>
  22782. You can call crash_file() as many times as you like from
  22783.  different parts of your program. The file specified by the
  22784.  last call will be the one used.
  22785. <P>
  22786. Unless you suppress it, you will always get a crash file 
  22787. when a compile-time error (syntax, undeclared variable etc.) occurs. 
  22788. In the case of a run-time error (subscript out of bounds, uninitialized
  22789.  variable, divide by zero etc.) your program must be executed
  22790.  by the Complete Edition interpreter, or have been
  22791.  <font color=\"993333\"><b>bound</b></font>,
  22792.  or be under 300 statements."
  22793. >
  22794.  
  22795. <_2clist
  22796.   name="Example:"
  22797.   description=""
  22798.  >
  22799. <_eucode>
  22800. crash_file("\\tmp\\mybug")
  22801.  
  22802.  </_eucode>
  22803. <_2clist
  22804.   name="See Also:"
  22805.   description="<a href=\"lib_a_b.htm#abort\">abort</a>,
  22806.                <a href=\"lib_c_d.htm#crash_message\">crash_message</a>,
  22807.                <a href=\"refman_3.htm\">debugging and profiling</a>"
  22808.  >
  22809. </table>
  22810.  
  22811. <_routine name="crash_message">
  22812. <table border=0 cellspacing=2 cellpadding=2>
  22813.  
  22814.  
  22815.  <_2clist
  22816.   name="Syntax:"
  22817.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  22818.  crash_message(s)
  22819. </font>"
  22820.  >
  22821.  <_2clist
  22822.   name="Description:"
  22823.   description=
  22824. "  Specify a string, s, to be printed on the screen in the event
  22825.  that Euphoria must stop your program due to a compile-time or
  22826.  run-time error. "
  22827.  >
  22828. <_2clist
  22829.   name="Comments:"
  22830.   description=
  22831. " Normally Euphoria prints a diagnostic message such as
  22832.  \"syntax error\" or \"divide by zero\" on the screen, as well as
  22833.  dumping debugging information into
  22834.  <font color=\"#993333\"><b>ex.err</b></font>. Euphoria's error
  22835.  messages will not be meaningful for your users unless they
  22836.  happen to be Euphoria programmers. By calling crash_message()
  22837.  you can control the message that will appear on the screen.
  22838.  Debugging information will still be stored in
  22839.  <font color=\"#993333\"><b>ex.err</b></font>. You won't
  22840.  lose any information by doing this.
  22841. <P>
  22842. s may contain '\n', new-line characters, so your message can
  22843.  span several lines on the screen. Euphoria will switch to the
  22844.  top of a clear <font color=\"#CC3366\">text-mode</font> screen
  22845.  before printing your message.
  22846. <P>
  22847. You can call crash_message() as many times as you like from
  22848.  different parts of your program. The message specified by the
  22849.  last call will be the one displayed.
  22850. <P>
  22851. Your crash message will always be displayed if a compile-time
  22852.  error (syntax, undeclared variable etc.) occurs. In the case of
  22853.  a run-time error (subscript out of bounds, uninitialized
  22854.  variable, divide by zero etc.) your program must be executed
  22855.  by the Complete Edition interpreter, or have been
  22856.  <font color=\"993333\"><b>bound</b></font>,
  22857.  or be under 300 statements.
  22858.  "
  22859.  >
  22860. <_2clist
  22861.   name="Example:"
  22862.   description=""
  22863.  >
  22864. <_eucode>
  22865. crash_message("An unexpected error has occurred!\n" &
  22866.               "Please contact john_doe@whoops.com\n" &
  22867.               "Do not delete the file \"ex.err\".\n")
  22868.  
  22869.  </_eucode>
  22870. <_2clist
  22871.   name="See Also:"
  22872.   description="<a href=\"lib_a_b.htm#abort\">abort</a>,
  22873.                <a href=\"lib_c_d.htm#crash_file\">crash_file</a>,
  22874.                <a href=\"refman_3.htm\">debugging and profiling</a>"
  22875.  >
  22876. </table>
  22877.  
  22878.  
  22879. <_routine name="current_dir">
  22880. <table border=0 cellspacing=2 cellpadding=2>
  22881.  
  22882.  
  22883.  <_2clist
  22884.   name="Syntax:"
  22885.   description="<font face = \"Arial, Helvetica\"> include file.e<BR>
  22886.  s = current_dir()
  22887. </font>"
  22888.  >
  22889.  <_2clist
  22890.   name="Description:"
  22891.   description=
  22892. "  Return the name of the current working directory. "
  22893.  >
  22894. <_2clist
  22895.   name="Example:"
  22896.   description=""
  22897.  >
  22898. <_eucode>
  22899. sequence s
  22900. s = current_dir()
  22901. -- s would have "C:\EUPHORIA\DOC" if you were in that directory
  22902.  
  22903.  </_eucode>
  22904. <_2clist
  22905.   name="See Also:"
  22906.   description="<a href=\"lib_c_d.htm#dir\">dir</a>,
  22907. <a href=\"lib_c_d.htm#chdir\">chdir</a>,
  22908. <a href=\"lib_e_g.htm#getenv\">getenv</a>"
  22909.  >
  22910. </table>
  22911.  
  22912.  
  22913. <_routine name="cursor">
  22914. <table border=0 cellspacing=2 cellpadding=2>
  22915.  
  22916.  
  22917.  <_2clist
  22918.   name="Syntax:"
  22919.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  22920.  cursor(i)
  22921. </font>"
  22922.  >
  22923.  <_2clist
  22924.   name="Description:"
  22925.   description=
  22926. "Select a style of cursor. <font color=\"#5500FF\"><b>graphics.e</b></font>
  22927.  contains:"
  22928.  >
  22929. <_eucode>
  22930.     global constant NO_CURSOR = #2000,
  22931.              UNDERLINE_CURSOR = #0607,
  22932.        THICK_UNDERLINE_CURSOR = #0507,
  22933.             HALF_BLOCK_CURSOR = #0407,
  22934.                  BLOCK_CURSOR = #0007
  22935. </_eucode> 
  22936.  <_2clist
  22937.   name=""
  22938.   description=
  22939. "The second and fourth hex digits (from the left) determine the
  22940.  top and bottom rows of pixels in the cursor. The first digit
  22941.  controls whether the cursor will be visible or not. For example,
  22942.  #0407 turns on the 4th through 7th rows."
  22943.  >
  22944. <_2clist
  22945.   name="Comments:"
  22946.   description=
  22947. "In <font color=\"#CC3366\">pixel-graphics modes</font> no cursor is
  22948.  displayed.
  22949.  "
  22950.  >
  22951. <_2clist
  22952.   name="Example:"
  22953.   description=""
  22954.  >
  22955. <_eucode>
  22956. cursor(BLOCK_CURSOR)
  22957.  
  22958.  </_eucode>
  22959. <_2clist
  22960.   name="See Also:"
  22961.   description="<a href=\"lib_e_g.htm#graphics_mode\">graphics_mode</a>,
  22962. <a href=\"lib_s_t.htm#text_rows\">text_rows</a>"
  22963.  >
  22964. </table>
  22965.  
  22966.  
  22967. <_routine name="custom_sort">
  22968. <table border=0 cellspacing=2 cellpadding=2>
  22969.  
  22970.  
  22971.  <_2clist
  22972.   name="Syntax:"
  22973.   description="<font face = \"Arial, Helvetica\"> include sort.e<BR>
  22974.  s2 = custom_sort(i, s1)
  22975. </font>"
  22976.  >
  22977.  <_2clist
  22978.   name="Description:"
  22979.   description=
  22980. "  Sort the elements of sequence s1, using a compare function with
  22981.  <font color=\"#993333\"><b>routine id</b></font> i. "
  22982.  >
  22983. <_2clist
  22984.   name="Comments:"
  22985.   description=
  22986. " Your compare function must be a function of two arguments
  22987.  similar to Euphoria's compare(). It will compare two objects
  22988.  and return -1, 0 or +1.
  22989.  "
  22990.  >
  22991. <_2clist
  22992.   name="Example Program:"
  22993.   description="<font color=\"#5500FF\"><b>demo\csort.ex</b></font>"
  22994.  >
  22995.  
  22996.  <_2clist
  22997.   name="See Also:"
  22998.   description="<a href=\"lib_s_t.htm#sort\">sort</a>,
  22999. <a href=\"lib_c_d.htm#compare\">compare</a>,
  23000. <a href=\"lib_p_r.htm#routine_id\">routine_id</a>"
  23001.  >
  23002. </table>
  23003.  
  23004.  
  23005. <_routine name="date">
  23006. <table border=0 cellspacing=2 cellpadding=2>
  23007.  
  23008.  
  23009.  <_2clist
  23010.   name="Syntax:"
  23011.   description="<font face = \"Arial, Helvetica\"> s = date()
  23012. </font>"
  23013.  >
  23014.  <_2clist
  23015.   name="Description:"
  23016.   description=
  23017. "Return a sequence with the following information:"
  23018.  >
  23019. <_eucode>
  23020.              { year,  -- since 1900
  23021.               month,  -- January = 1
  23022.                 day,  -- day of month, starting at 1
  23023.                hour,  -- 0 to 23
  23024.              minute,  -- 0 to 59
  23025.              second,  -- 0 to 59
  23026.     day of the week,  -- Sunday = 1
  23027.     day of the year}  -- January 1st = 1
  23028. </_eucode>
  23029. <_2clist
  23030.   name="Example:"
  23031.   description=""
  23032.  >
  23033. <_eucode>
  23034. now = date()
  23035. -- now has: {95,3,24,23,47,38,6,83}
  23036. -- i.e. Friday March 24, 1995 at 11:47:38pm, day 83 of the year
  23037.  
  23038.  </_eucode>
  23039. <_2clist
  23040.   name="Comments:"
  23041.   description=
  23042. "The value returned for the year is actually the number of years since 1900
  23043.  (<font color=\"#CC0099\"><b><i>not</i></b></font> the last 2 digits of the
  23044.  year). In the year 2000 this value will be 100. In 2001 it will be 101, etc."
  23045.  >
  23046. <_2clist
  23047.   name="See Also:"
  23048.   description="<a href=\"lib_s_t.htm#time\">time</a>"
  23049.  >
  23050. </table>
  23051.  
  23052.  
  23053. <_routine name="define_c_func">
  23054. <table border=0 cellspacing=2 cellpadding=2>
  23055.  
  23056.  
  23057.  <_2clist
  23058.   name="Platform:"
  23059.   description="<font color=\"#CC3366\"><b>WIN32, Linux</b></font>"
  23060.  >
  23061.  
  23062.  <_2clist
  23063.   name="Syntax:"
  23064.   description="<font face = \"Arial, Helvetica\"> include dll.e<BR>
  23065.  i1 = define_c_func(a, s1, s2, i2)
  23066. </font>"
  23067.  >
  23068.  <_2clist
  23069.   name="Description:"
  23070.   description=
  23071. "Define the characteristics of a C function that you wish to
  23072.  call from your Euphoria program. A small integer, known as a
  23073.  <font color=\"#993333\"><b>routine id</b></font>, will be
  23074.  returned, or -1 if the function can't be found. a is an address
  23075.  returned by open_dll(). s1 is the name of the function. s2 is a
  23076.  list of the parameter types for the function. i2 is the return
  23077.  type of the function. A list of C types is contained in
  23078.  <font color=\"#5500FF\"><b>dll.e</b></font>:"
  23079.  >
  23080. <_eucode>
  23081.     global constant C_CHAR = #01000001,
  23082.                    C_UCHAR = #02000001,
  23083.                    C_SHORT = #01000002,
  23084.                   C_USHORT = #02000002,
  23085.                      C_INT = #01000004,
  23086.                     C_UINT = #02000004,
  23087.                     C_LONG = C_INT,
  23088.                    C_ULONG = C_UINT,
  23089.                  C_POINTER = C_ULONG,
  23090.                    C_FLOAT = #03000004,
  23091.                   C_DOUBLE = #03000008
  23092. </_eucode>
  23093.  
  23094. <_2clist
  23095.   name="Comments:"
  23096.   description=
  23097. "The <font color=\"#993333\"><b>routine id</b></font>, i1, can be
  23098.  passed to c_func() when you want to call the C function.
  23099. <P>
  23100. You can pass or return any C integer type or pointer type.
  23101.  You can also pass a Euphoria atom as a C double, and get
  23102.  a C double returned to you as a Euphoria atom.
  23103. <P>
  23104. In C (on WIN32 and Linux), parameter types which use 4 bytes or less are all passed the
  23105.  same way, so it is not necessary to be exact. However the
  23106.  distinction between signed and unsigned may be important when
  23107.  you specify the return type of a function.
  23108. <P>
  23109. Currently, there is no way to pass a C structure by value or
  23110.  get a C structure as a return result. You can only pass a pointer
  23111.  to a structure and get a pointer to a structure as a result.
  23112. <P>
  23113. If you are not interested in using the value returned by the
  23114.  C function, you should instead define it with define_c_proc()
  23115.  and call it with c_proc().
  23116.  "
  23117.  >
  23118. <_2clist
  23119.   name="Example:"
  23120.   description=""
  23121.  >
  23122. <_eucode>
  23123. atom user32
  23124. integer LoadIcon
  23125.  
  23126. -- open user32.dll - it contains the LoadIconA C function
  23127. user32 = open_dll("user32.dll")
  23128.  
  23129. -- It takes a C pointer and a C int as parameters.
  23130. -- It returns a C int as a result.
  23131. LoadIcon = define_c_func(user32, "LoadIconA",
  23132.                          {C_POINTER, C_INT}, C_INT)
  23133. if LoadIcon = -1 then
  23134.     puts(1, "LoadIconA could not be found!\n")
  23135. end if
  23136.  
  23137.  </_eucode>
  23138. <_2clist
  23139.   name="See Also:"
  23140.   description="<a href=\"lib_c_d.htm#c_func\">c_func</a>,
  23141. <a href=\"lib_c_d.htm#define_c_proc\">define_c_proc</a>,
  23142. <a href=\"lib_c_d.htm#c_proc\">c_proc</a>,
  23143. <a href=\"lib_h_o.htm#open_dll\">open_dll</a>,
  23144. <a href=\"platform.htm#call_cfunc\"><font color=\"#5500FF\"><b>platform.doc</b>
  23145. </font></a>"
  23146.  >
  23147. </table>
  23148.  
  23149.  
  23150. <_routine name="define_c_proc">
  23151. <table border=0 cellspacing=2 cellpadding=2>
  23152.  
  23153.  
  23154.  <_2clist
  23155.   name="Platform:"
  23156.   description="<font color=\"#CC3366\"><b>WIN32, Linux</b></font>"
  23157.  >
  23158.  
  23159.  <_2clist
  23160.   name="Syntax:"
  23161.   description="<font face = \"Arial, Helvetica\"> include dll.e<BR>
  23162.  i1 = define_c_proc(a, s1, s2)
  23163. </font>"
  23164.  >
  23165.  <_2clist
  23166.   name="Description:"
  23167.   description=
  23168. "Define the characteristics of a C function that you wish to
  23169.  call as a procedure from your Euphoria program. A small integer, known as
  23170.  a <font color=\"#993333\"><b>routine id</b></font>,
  23171.  will be returned, or -1 if the function can't be found. a is an
  23172.  address returned by open_dll(). s1 is the name of the function.
  23173.  s2 is a list of the parameter types for the function. A list of
  23174.  C types is contained in <font color=\"#5500FF\"><b>dll.e</b></font>. "
  23175.  >
  23176. <_2clist
  23177.   name="Comments:"
  23178.   description=
  23179. "The <font color=\"#993333\"><b>routine id</b></font>, i1, can be
  23180.  passed to c_proc(), when you want to call the C function.
  23181. <P>
  23182. You can pass any C integer type or pointer type.
  23183.  You can also pass a Euphoria atom as a C double.
  23184. <P>
  23185. In C (on WIN32 and Linux), parameter types which use 4 bytes or less are 
  23186.  all passed the same way, so it is not necessary to be exact.
  23187. <P>
  23188. Currently, there is no way to pass a C structure by value.
  23189.  You can only pass a pointer to a structure.
  23190. <P>
  23191. The C function can return a value but it will be ignored.
  23192.  If you want to use the value returned by the C function,
  23193.  you must instead define it with define_c_func() and call it
  23194.  with c_func()."
  23195.  >
  23196. <_2clist
  23197.   name="Example:"
  23198.   description=""
  23199.  >
  23200. <_eucode>
  23201. atom user32
  23202. integer ShowWindow
  23203.  
  23204. -- open user32.dll - it contains the ShowWindow C function
  23205. user32 = open_dll("user32.dll")
  23206.  
  23207. -- It has 2 parameters that are both C int.
  23208. ShowWindow = define_c_proc(user32, "ShowWindow", {C_INT, C_INT})
  23209. if ShowWindow = -1 then
  23210.     puts(1, "ShowWindow not found!\n")
  23211. end if
  23212.  
  23213.  </_eucode>
  23214. <_2clist
  23215.   name="See Also:"
  23216.   description="<a href=\"lib_c_d.htm#c_proc\">c_proc</a>,
  23217. <a href=\"lib_c_d.htm#define_c_func\">define_c_func</a>,
  23218. <a href=\"lib_c_d.htm#c_func\">c_func</a>,
  23219. <a href=\"lib_h_o.htm#open_dll\">open_dll</a>,
  23220. <a href=\"platform.htm#call_cfunc\"><font color=\"#5500FF\"><b>platform.doc</b>
  23221. </font></a>"
  23222.  >
  23223. </table>
  23224.  
  23225. <_routine name="define_c_var">
  23226. <table border=0 cellspacing=2 cellpadding=2>
  23227.  
  23228.  
  23229.  <_2clist
  23230.   name="Platform:"
  23231.   description="<font color=\"#CC3366\"><b>Linux</b></font>"
  23232.  >
  23233.  
  23234.  <_2clist
  23235.   name="Syntax:"
  23236.   description="<font face = \"Arial, Helvetica\"> include dll.e<BR>
  23237.  a1 = define_c_var(a2, s)
  23238. </font>"
  23239.  >
  23240.  <_2clist
  23241.   name="Description:"
  23242.   description=
  23243. "a2 is the address of a Linux shared
  23244.  library, as returned by open_dll(). 
  23245.  s is the name of a global C variable defined within the library.
  23246.  a1 will be the memory address of variable s."
  23247.  >
  23248. <_2clist
  23249.   name="Comments:"
  23250.   description="Once you have the address of a C variable, and you know
  23251.   its type, you can use peek() and poke() to read or write the value 
  23252.   of the variable."
  23253.  >
  23254. <_2clist
  23255.   name="Example Program:"
  23256.   description="euphoria/demo/linux/mylib.exu"
  23257.  >
  23258. <_2clist
  23259.   name="See Also:"
  23260.   description="<a href=\"lib_c_d.htm#c_proc\">c_proc</a>,
  23261. <a href=\"lib_c_d.htm#define_c_func\">define_c_func</a>,
  23262. <a href=\"lib_c_d.htm#c_func\">c_func</a>,
  23263. <a href=\"lib_h_o.htm#open_dll\">open_dll</a>,
  23264. <a href=\"platform.htm#call_cfunc\"><font color=\"#5500FF\"><b>platform.doc</b>
  23265. </font></a>"
  23266.  >
  23267. </table>
  23268.  
  23269.  
  23270. <_routine name="dir">
  23271. <table border=0 cellspacing=2 cellpadding=2>
  23272.  
  23273.  
  23274.  <_2clist
  23275.   name="Syntax:"
  23276.   description="<font face = \"Arial, Helvetica\"> include file.e<BR>
  23277.  x = dir(st)
  23278. </font>"
  23279.  >
  23280.  <_2clist
  23281.   name="Description:"
  23282.   description=
  23283. "Return directory information for the file or directory named by
  23284.  st. If there is no file or directory with this name then -1 is
  23285.  returned. st can contain * and ? wildcards to select multiple
  23286.  files.
  23287. <P>
  23288. <a name=dir_entry></a>
  23289. This information is similar to what you would get from the DOS
  23290.  DIR command. A sequence is returned where each element is a
  23291.  sequence that describes one file or subdirectory.
  23292. <P>
  23293. If st names a <b>directory</b> you may have entries for \".\" and \"..\",
  23294.  just as with the DOS DIR command. If st names a <b>file</b> then x will
  23295.  have just one entry,
  23296.  i.e. <a href=\"lib_h_o.htm#length\">length(x)</a> will
  23297.  be 1. If st contains wildcards you may have multiple entries.
  23298. <P>
  23299. Each entry contains the name, attributes and file size as well as
  23300.  the year, month, day, hour, minute and second of the last modification.
  23301.  You can refer to the elements of an entry with the following constants
  23302.  defined in <font color=\"#5500FF\"><b>file.e</b></font>:"
  23303.  >
  23304. <_eucode>
  23305.     global constant D_NAME = 1,
  23306.               D_ATTRIBUTES = 2,
  23307.                     D_SIZE = 3,
  23308.  
  23309.                     D_YEAR = 4,
  23310.                    D_MONTH = 5,
  23311.                      D_DAY = 6,
  23312.  
  23313.                     D_HOUR = 7,
  23314.                   D_MINUTE = 8,
  23315.                   D_SECOND = 9
  23316. </_eucode>
  23317.  
  23318. <_2clist
  23319.  name=""
  23320.  description=
  23321. "The attributes element is a string sequence containing
  23322.  characters chosen from:"
  23323.  >
  23324. <_eucode>
  23325.     'd' -- directory
  23326.     'r' -- read only file
  23327.     'h' -- hidden file
  23328.     's' -- system file
  23329.     'v' -- volume-id entry
  23330.     'a' -- archive file
  23331. </_eucode>
  23332.  
  23333. <_2clist
  23334.  name=""
  23335.  description=
  23336. "A normal file without special attributes would just have an empty
  23337.  string, \"\", in this field.
  23338.  "
  23339.  >
  23340. <_2clist
  23341.   name="Comments:"
  23342.   description=
  23343. " The top level directory, e.g. c:\ does not have \".\" or \"..\"
  23344.  entries.
  23345. <P>
  23346. This function is often used just to test if a file or
  23347.  directory exists.
  23348. <P>
  23349. Under <font color=\"#CC3366\"><b>WIN32</b></font>, st can have a long file
  23350.  or directory name anywhere in the path.
  23351. <P>
  23352. Under <font color=\"#CC3366\"><b>Linux</b></font>, the only attribute
  23353.  currently available is 'd'.
  23354. <P>
  23355. <font color=\"#CC3366\"><b>DOS32:</b></font> The file name returned
  23356.  in D_NAME will be a standard DOS 8.3 name. (See
  23357.  <a href=\"http://www.RapidEuphoria.com/exestuff.htm\">Archive
  23358.  Web page</a> for a better solution).
  23359. <P>
  23360. <font color=\"#CC3366\"><b>WIN32:</b></font> The file name returned
  23361.  in D_NAME will be a long file name."
  23362.  >
  23363. <_2clist
  23364.   name="Example:"
  23365.   description=""
  23366.  >
  23367. <_eucode>
  23368. d = dir(current_dir())
  23369.  
  23370. -- d might have:
  23371.   {
  23372.     {".",    "d",     0  1994, 1, 18,  9, 30, 02},
  23373.     {"..",   "d",     0  1994, 1, 18,  9, 20, 14},
  23374.     {"fred", "ra", 2350, 1994, 1, 22, 17, 22, 40},
  23375.     {"sub",  "d" ,    0, 1993, 9, 20,  8, 50, 12}
  23376.   }
  23377.  
  23378. d[3][D_NAME] would be "fred"
  23379.  
  23380.  </_eucode>
  23381. <_2clist
  23382.   name="Example Programs:"
  23383.   description="<font color=\"#5500FF\"><b>bin\search.ex</b></font>,
  23384.   <font color=\"#5500FF\"><b>bin\install.ex</b></font>"
  23385.  >
  23386.  
  23387. <_2clist
  23388.   name="See Also:"
  23389.   description="<a href=\"lib_u_z.htm#wildcard_file\">wildcard_file</a>,
  23390. <a href=\"lib_c_d.htm#current_dir\">current_dir</a>,
  23391. <a href=\"lib_h_o.htm#open\">open</a>"
  23392.  >
  23393. </table>
  23394.  
  23395.  
  23396. <_routine name="display_image">
  23397. <table border=0 cellspacing=2 cellpadding=2>
  23398.  
  23399.  
  23400.  <_2clist
  23401.   name="Platform:"
  23402.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  23403.  >
  23404.  
  23405.  <_2clist
  23406.   name="Syntax:"
  23407.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  23408.  display_image(s1, s2)
  23409. </font>"
  23410.  >
  23411.  <_2clist
  23412.   name="Description:"
  23413.   description=
  23414. "Display at point s1 on a <font color=\"#CC3366\">pixel-graphics</font>
  23415.  screen the 2-d sequence
  23416.  of pixels contained in s2. s1 is a two-element sequence {x, y}.
  23417.  s2 is a sequence of sequences, where each sequence is one
  23418.  horizontal row of pixel colors to be displayed. The first pixel
  23419.  of the first sequence is displayed at s1. It is the top-left
  23420.  pixel. All other pixels appear to the right or below of this
  23421.  point. "
  23422.  >
  23423. <_2clist
  23424.   name="Comments:"
  23425.   description=
  23426. " s2 might be the result of a previous call to save_image(), or
  23427.  read_bitmap(), or it could be something you have created.
  23428. <P>
  23429. The sequences (rows) of the image do not have to all be the
  23430.  same length.
  23431.  "
  23432.  >
  23433. <_2clist
  23434.   name="Example:"
  23435.   description=""
  23436.  >
  23437. <_eucode>
  23438. display_image({20,30}, {{7,5,9,4,8},
  23439.                         {2,4,1,2},
  23440.                         {1,0,1,0,4,6,1},
  23441.                         {5,5,5,5,5,5}})
  23442. -- This will display a small image containing 4 rows of
  23443. -- pixels. The first pixel (7) of the top row will be at
  23444. -- {20,30}. The top row contains 5 pixels. The last row
  23445. -- contains 6 pixels ending at {25,33}.
  23446.  
  23447.  </_eucode>
  23448. <_2clist
  23449.   name="Example Program:"
  23450.   description="<font color=\"#5500FF\"><b>demo\dos32\bitmap.ex</b></font>"
  23451.  >
  23452.  
  23453.  <_2clist
  23454.   name="See Also:"
  23455.   description="<a href=\"lib_s_t.htm#save_image\">save_image</a>,
  23456. <a href=\"lib_p_r.htm#read_bitmap\">read_bitmap</a>,
  23457. <a href=\"lib_c_d.htm#display_text_image\">display_text_image</a>"
  23458.  >
  23459. </table>
  23460.  
  23461.  
  23462. <_routine name="display_text_image">
  23463. <table border=0 cellspacing=2 cellpadding=2>
  23464.  
  23465.  
  23466.  <_2clist
  23467.   name="Platform:"
  23468.   description="<font color=\"#CC3366\"><b>DOS32, Linux</b></font>"
  23469.  >
  23470.  
  23471.  <_2clist
  23472.   name="Syntax:"
  23473.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  23474.  display_text_image(s1, s2)
  23475. </font>"
  23476.  >
  23477.  <_2clist
  23478.   name="Description:"
  23479.   description=
  23480. "Display the 2-d sequence of characters and attributes contained
  23481.  in s2 at line s1[1], column s1[2]. s2 is a sequence of sequences,
  23482.  where each sequence is a string of characters and attributes to
  23483.  be displayed. The top-left character is displayed at s1. Other
  23484.  characters appear to the right or below this position. The
  23485.  attributes indicate the foreground and background color of the
  23486.  preceding character. On DOS32, the attribute should consist of the 
  23487.  foreground color plus 16 times the background color."
  23488.  >
  23489. <_2clist
  23490.   name="Comments:"
  23491.   description=
  23492. " s2 would normally be the result of a previous call to
  23493.  save_text_image(), although you could construct it yourself.
  23494. <P>
  23495. This routine only works in <font color=\"#CC3366\">text modes</font>.
  23496. <P>
  23497. You might use save_text_image()/display_text_image() in a text-mode
  23498.  graphical user interface, to allow \"pop-up\" dialog boxes, and
  23499.  drop-down menus to appear and disappear without losing what was
  23500.  previously on the screen.
  23501. <P>
  23502. The sequences of the text image do not have to all be the same
  23503.  length.
  23504.  "
  23505.  >
  23506. <_2clist
  23507.   name="Example:"
  23508.   description=""
  23509.  >
  23510. <_eucode>
  23511. clear_screen()
  23512. display_text_image({1,1}, {{'A', WHITE, 'B', GREEN},
  23513.                            {'C', RED+16*WHITE},
  23514.                            {'D', BLUE}})
  23515. -- displays:
  23516.      AB
  23517.      C
  23518.      D
  23519. -- at the top left corner of the screen.
  23520. -- 'A' will be white with black (0) background color,
  23521. -- 'B' will be green on black, 
  23522. -- 'C' will be red on white, and
  23523. -- 'D' will be blue on black.
  23524.  
  23525.  </_eucode>
  23526. <_2clist
  23527.   name="See Also:"
  23528.   description="<a href=\"lib_s_t.htm#save_text_image\">save_text_image</a>,
  23529. <a href=\"lib_c_d.htm#display_image\">display_image</a>,
  23530. <a href=\"lib_p_r.htm#put_screen_char\">put_screen_char</a>"
  23531.  >
  23532. </table>
  23533.  
  23534.  
  23535. <_routine name="dos_interrupt">
  23536. <table border=0 cellspacing=2 cellpadding=2>
  23537.  
  23538.  
  23539.  <_2clist
  23540.   name="Platform:"
  23541.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  23542.  >
  23543.  
  23544.  <_2clist
  23545.   name="Syntax:"
  23546.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  23547.  s2 = dos_interrupt(i, s1)
  23548. </font>"
  23549.  >
  23550.  <_2clist
  23551.   name="Description:"
  23552.   description=
  23553. "Call DOS software interrupt number i. s1 is a 10-element
  23554.  sequence of 16-bit register values to be used as input to the
  23555.  interrupt routine. s2 is a similar 10-element sequence containing
  23556.  output register values after the call returns. 
  23557.  <font color=\"#5500FF\"><b>machine.e</b></font> has the following
  23558.  declaration which shows the order of
  23559.  the register values in the input and output sequences."
  23560.  >
  23561. <_eucode>
  23562.     global constant REG_DI = 1,
  23563.                     REG_SI = 2,
  23564.                     REG_BP = 3,
  23565.                     REG_BX = 4,
  23566.                     REG_DX = 5,
  23567.                     REG_CX = 6,
  23568.                     REG_AX = 7,
  23569.                     REG_FLAGS = 8,
  23570.                     REG_ES = 9,
  23571.                     REG_DS = 10
  23572. </_eucode>
  23573.  
  23574. <_2clist
  23575.   name="Comments:"
  23576.   description=
  23577. " The register values returned in s2 are always positive values
  23578.  between 0 and #FFFF (65535).
  23579. <P>
  23580. The flags value in s1[REG_FLAGS] is ignored on input. On output
  23581.  the least significant bit of s2[REG_FLAGS] has the carry flag,
  23582.  which usually indicates failure if it is set to 1.
  23583. <P>
  23584. Certain interrupts require that you supply addresses of blocks of
  23585.  memory. These addresses must be conventional, low-memory
  23586.  addresses. You can allocate/deallocate low-memory using
  23587.  allocate_low() and free_low().
  23588. <P>
  23589. With DOS software interrupts you can perform a wide variety
  23590.  of specialized operations, anything from formatting your
  23591.  floppy drive to rebooting your computer. For documentation
  23592.  on these interrupts consult a technical manual such as
  23593.  Peter Norton's <i>\"PC Programmer's Bible\"</i>, or download Ralf
  23594.  Brown's <i>Interrupt List</i> from the Web:
  23595. <P>
  23596. <a href=\"http://www.cs.cmu.edu/afs/cs.cmu.edu/user/ralf/pub/WWW/files.html\">
  23597. http://www.cs.cmu.edu/afs/cs.cmu.edu/user/ralf/pub/WWW/files.html</a>"
  23598.  >
  23599. <_2clist
  23600.   name="Example:"
  23601.   description=""
  23602.  >
  23603. <_eucode>
  23604. sequence registers
  23605.  
  23606. registers = repeat(0, 10)  -- no registers need to be set
  23607.  
  23608. -- call DOS interrupt 5: Print Screen
  23609. registers = dos_interrupt(#5, registers)
  23610.  
  23611.  </_eucode>
  23612. <_2clist
  23613.   name="Example Program:"
  23614.   description="<font color=\"#5500FF\"><b>demo\dos32\dosint.ex</b></font>"
  23615.  >
  23616.  
  23617.  <_2clist
  23618.   name="See Also:"
  23619.   description="<a href=\"lib_a_b.htm#allocate_low\">allocate_low</a>,
  23620. <a href=\"lib_e_g.htm#free_low\">free_low</a>"
  23621.  >
  23622. </table>
  23623.  
  23624.  
  23625. <_routine name="draw_line">
  23626. <table border=0 cellspacing=2 cellpadding=2>
  23627.  
  23628.  
  23629.  <_2clist
  23630.   name="Platform:"
  23631.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  23632.  >
  23633.  
  23634.  <_2clist
  23635.   name="Syntax:"
  23636.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  23637.  draw_line(i, s)
  23638. </font>"
  23639.  >
  23640.  <_2clist
  23641.   name="Description:"
  23642.   description=
  23643. "Draw a line on a <font color=\"#CC3366\">pixel-graphics</font> screen
  23644.  connecting two or more points in s, using color i. "
  23645.  >
  23646. <_2clist
  23647.   name="Example:"
  23648.   description=""
  23649.  >
  23650. <_eucode>
  23651. draw_line(WHITE, {{100, 100}, {200, 200}, {900, 700}})
  23652.  
  23653. -- This would connect the three points in the sequence using
  23654. -- a white line, i.e. a line would be drawn from {100, 100} to
  23655. -- {200, 200} and another line would be drawn from {200, 200} to
  23656. -- {900, 700}.
  23657.  
  23658.  </_eucode>
  23659. <_2clist
  23660.   name="See Also:"
  23661.   description="<a href=\"lib_p_r.htm#polygon\">polygon</a>,
  23662. <a href=\"lib_e_g.htm#ellipse\">ellipse</a>,
  23663. <a href=\"lib_p_r.htm#pixel\">pixel</a>"
  23664.  >
  23665. </table>
  23666.  
  23667. <_continue
  23668.   href="lib_e_g.htm"
  23669.   name="From E to G"
  23670. >
  23671.  
  23672. </body>
  23673. </html>
  23674. LIB_E_G.HTX
  23675. 37236
  23676. <_init_comment>
  23677. <html>
  23678. <head><title>Euphoria v2.2 Reference Manual Part II - Section 3</title>
  23679. </head>
  23680. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  23681. <br>
  23682.  
  23683.  
  23684. <_routine name="ellipse">
  23685. <table border=0 cellspacing=2 cellpadding=2>
  23686.  
  23687.  
  23688.  <_2clist
  23689.   name="Platform:"
  23690.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  23691.  >
  23692.  
  23693.  <_2clist
  23694.   name="Syntax:"
  23695.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  23696.  ellipse(i1, i2, s1, s2)
  23697. </font>"
  23698.  >
  23699.  <_2clist
  23700.   name="Description:"
  23701.   description=
  23702. "Draw an ellipse with color i1 on a
  23703.  <font color=\"#CC3366\">pixel-graphics</font> screen. The
  23704.  ellipse will neatly fit inside the rectangle defined by diagonal
  23705.  points s1 {x1, y1} and s2 {x2, y2}. If the rectangle is a square
  23706.  then the ellipse will be a circle. Fill the ellipse when i2 is 1.
  23707.  Don't fill when i2 is 0. "
  23708.  >
  23709. <_2clist
  23710.   name="Example:"
  23711.   description=""
  23712.  >
  23713. <_eucode>
  23714. ellipse(MAGENTA, 0, {10, 10}, {20, 20})
  23715.  
  23716. -- This would make a magenta colored circle just fitting
  23717. -- inside the square: 
  23718. --        {10, 10}, {10, 20}, {20, 20}, {20, 10}.
  23719.  
  23720.  </_eucode>
  23721. <_2clist
  23722.   name="Example Program:"
  23723.   description="<font color=\"#5500FF\"><b>demo\dos32\sb.ex</b></font>"
  23724.  >
  23725.  
  23726.  <_2clist
  23727.   name="See Also:"
  23728.   description="<a href=\"lib_p_r.htm#polygon\">polygon</a>,
  23729. <a href=\"lib_c_d.htm#draw_line\">draw_line</a>"
  23730.  >
  23731. </table>
  23732.  
  23733.  
  23734. <_routine name="equal">
  23735. <table border=0 cellspacing=2 cellpadding=2>
  23736.  
  23737.  
  23738.  <_2clist
  23739.   name="Syntax:"
  23740.   description="<font face = \"Arial, Helvetica\"> i = equal(x1, x2)
  23741. </font>"
  23742.  >
  23743.  <_2clist
  23744.   name="Description:"
  23745.   description=
  23746. "  Compare two Euphoria objects to see if they are the same.
  23747.  Return 1 (true) if they are the same. Return 0 (false) if
  23748.  they are different. "
  23749.  >
  23750. <_2clist
  23751.   name="Comments:"
  23752.   description=
  23753. " This is equivalent to the expression: <b>compare(x1, x2) = 0</b>
  23754.  "
  23755.  >
  23756. <_2clist
  23757.   name="Example 1:"
  23758.   description=""
  23759.  >
  23760. <_eucode>
  23761. if equal(PI, 3.14) then
  23762.     puts(1, "give me a better value for PI!\n")
  23763. end if
  23764.  
  23765.  </_eucode>
  23766. <_2clist
  23767.   name="Example 2:"
  23768.   description=""
  23769.  >
  23770. <_eucode>
  23771. if equal(name, "George") or equal(name, "GEORGE") then
  23772.     puts(1, "name is George\n")
  23773. end if
  23774.  
  23775.  </_eucode>
  23776. <_2clist
  23777.   name="See Also:"
  23778.   description="<a href=\"lib_c_d.htm#compare\">compare</a>,
  23779.                <a href=\"refman_2.htm#23\">equals operator (=)</a>"
  23780.  >
  23781. </table>
  23782.  
  23783.  
  23784. <_routine name="find">
  23785. <table border=0 cellspacing=2 cellpadding=2>
  23786.  
  23787.  
  23788.  <_2clist
  23789.   name="Syntax:"
  23790.   description="<font face = \"Arial, Helvetica\"> i = find(x, s)
  23791. </font>"
  23792.  >
  23793.  <_2clist
  23794.   name="Description:"
  23795.   description=
  23796. "  Find x as an element of s. If successful, return the index
  23797.  of the first element of s that matches. If unsuccessful
  23798.  return 0. "
  23799.  >
  23800. <_2clist
  23801.   name="Example 1:"
  23802.   description=""
  23803.  >
  23804. <_eucode>
  23805. location = find(11, {5, 8, 11, 2, 3})
  23806. -- location is set to 3
  23807.  
  23808.  </_eucode>
  23809. <_2clist
  23810.   name="Example 2:"
  23811.   description=""
  23812.  >
  23813. <_eucode>
  23814. names = {"fred", "rob", "george", "mary", ""}
  23815. location = find("mary", names)
  23816. -- location is set to 4
  23817.  
  23818.  </_eucode>
  23819. <_2clist
  23820.   name="See Also:"
  23821.   description="<a href=\"lib_h_o.htm#match\">match</a>,
  23822. <a href=\"lib_c_d.htm#compare\">compare</a>"
  23823.  >
  23824. </table>
  23825.  
  23826.  
  23827. <_routine name="float32_to_atom">
  23828. <table border=0 cellspacing=2 cellpadding=2>
  23829.  
  23830.  
  23831.  <_2clist
  23832.   name="Syntax:"
  23833.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  23834.  a1 = float32_to_atom(s)
  23835. </font>"
  23836.  >
  23837.  <_2clist
  23838.   name="Description:"
  23839.   description=
  23840. "  Convert a sequence of 4 bytes to an atom. These 4 bytes must
  23841.  contain an IEEE floating-point number in 32-bit format. "
  23842.  >
  23843. <_2clist
  23844.   name="Comments:"
  23845.   description=
  23846. " Any 32-bit IEEE floating-point number can be converted to an
  23847.  atom.
  23848.  "
  23849.  >
  23850. <_2clist
  23851.   name="Example:"
  23852.   description=""
  23853.  >
  23854. <_eucode>
  23855. f = repeat(0, 4)
  23856. fn = open("numbers.dat", "rb") -- read binary
  23857. f[1] = getc(fn)
  23858. f[2] = getc(fn)
  23859. f[3] = getc(fn)
  23860. f[4] = getc(fn)
  23861. a = float32_to_atom(f)
  23862.  
  23863.  </_eucode>
  23864. <_2clist
  23865.   name="See Also:"
  23866.   description="<a href=\"lib_e_g.htm#float64_to_atom\">float64_to_atom</a>,
  23867. <a href=\"lib_a_b.htm#atom_to_float32\">atom_to_float32</a>"
  23868.  >
  23869. </table>
  23870.  
  23871.  
  23872. <_routine name="float64_to_atom">
  23873. <table border=0 cellspacing=2 cellpadding=2>
  23874.  
  23875.  
  23876.  <_2clist
  23877.   name="Syntax:"
  23878.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  23879.  a1 = float64_to_atom(s)
  23880. </font>"
  23881.  >
  23882.  <_2clist
  23883.   name="Description:"
  23884.   description=
  23885. "  Convert a sequence of 8 bytes to an atom. These 8 bytes must
  23886.  contain an IEEE floating-point number in 64-bit format. "
  23887.  >
  23888. <_2clist
  23889.   name="Comments:"
  23890.   description=
  23891. " Any 64-bit IEEE floating-point number can be converted to an
  23892.  atom.
  23893.  "
  23894.  >
  23895. <_2clist
  23896.   name="Example:"
  23897.   description=""
  23898.  >
  23899. <_eucode>
  23900. f = repeat(0, 8)
  23901. fn = open("numbers.dat", "rb")  -- read binary
  23902. for i = 1 to 8 do
  23903.     f[i] = getc(fn)
  23904. end for
  23905. a = float64_to_atom(f)
  23906.  
  23907.  </_eucode>
  23908. <_2clist
  23909.   name="See Also:"
  23910.   description="<a href=\"lib_e_g.htm#float32_to_atom\">float32_to_atom</a>,
  23911. <a href=\"lib_a_b.htm#atom_to_float64\">atom_to_float64</a>"
  23912.  >
  23913. </table>
  23914.  
  23915.  
  23916. <_routine name="floor">
  23917. <table border=0 cellspacing=2 cellpadding=2>
  23918.  
  23919.  
  23920.  <_2clist
  23921.   name="Syntax:"
  23922.   description="<font face = \"Arial, Helvetica\"> x2 = floor(x1)
  23923. </font>"
  23924.  >
  23925.  <_2clist
  23926.   name="Description:"
  23927.   description=
  23928. "  Return the greatest integer less than or equal to x1. (Round
  23929.  down to an integer.) "
  23930.  >
  23931. <_2clist
  23932.   name="Comments:"
  23933.   description=
  23934. " This function may be applied to an atom or to all elements
  23935.  of a sequence.
  23936.  "
  23937.  >
  23938. <_2clist
  23939.   name="Example:"
  23940.   description=""
  23941.  >
  23942. <_eucode>
  23943. y = floor({0.5, -1.6, 9.99, 100})
  23944. -- y is {0, -2, 9, 100}
  23945.  
  23946.  </_eucode>
  23947. <_2clist
  23948.   name="See Also:"
  23949.   description="<a href=\"lib_p_r.htm#remainder\">remainder</a>"
  23950.  >
  23951. </table>
  23952.  
  23953.  
  23954. <_routine name="flush">
  23955. <table border=0 cellspacing=2 cellpadding=2>
  23956.  
  23957.  
  23958.  <_2clist
  23959.   name="Syntax:"
  23960.   description="<font face = \"Arial, Helvetica\"> include file.e<BR>flush(fn)
  23961. </font>"
  23962.  >
  23963.  <_2clist
  23964.   name="Description:"
  23965.   description=
  23966. "When you write data to a file, Euphoria normally stores the data
  23967. in a memory buffer until a large enough chunk of data has accumulated. 
  23968. This large chunk can then be written to disk very efficiently. 
  23969. Sometimes you may want to force, or flush, all data out immediately, 
  23970. even if the memory buffer is not full. To do this you must call flush(fn),
  23971. where fn is the file number of a file open for writing or appending."
  23972.  >
  23973. <_2clist
  23974.   name="Comments:"
  23975.   description=
  23976. "When a file is closed, (see close()), all buffered data is flushed out. 
  23977.  When a program terminates, all open files are flushed and closed 
  23978.  automatically. <P>Use flush() when another process may need to
  23979.  see all of the data written so far, but you aren't ready
  23980.   to close the file yet."
  23981.  >
  23982.  
  23983. <_2clist
  23984.   name="Example:"
  23985.   description=""
  23986.  >
  23987. <_eucode>
  23988. f = open("logfile", "w")
  23989. puts(f, "Record#1\n")
  23990. puts(1, "Press Enter when ready\n")
  23991.  
  23992. flush(f)  -- This forces "Record #1" into "logfile" on disk.
  23993.           -- Without this, "logfile" will appear to have 
  23994.           -- 0 characters when we stop for keyboard input.
  23995.  
  23996. s = gets(0) -- wait for keyboard input
  23997.  
  23998.  </_eucode>
  23999. <_2clist
  24000.   name="See Also:"
  24001.   description="<a href=\"lib_c_d.htm#close\">close</a>,
  24002.                <a href=\"lib_h_o.htm#lock_file\">lock_file</a>"
  24003.  >
  24004. </table>
  24005.  
  24006.  
  24007. <_routine name="free">
  24008. <table border=0 cellspacing=2 cellpadding=2>
  24009.  
  24010.  
  24011.  <_2clist
  24012.   name="Syntax:"
  24013.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  24014.  free(a)
  24015. </font>"
  24016.  >
  24017.  <_2clist
  24018.   name="Description:"
  24019.   description=
  24020. "  Free up a previously allocated block of memory by specifying the
  24021.  address of the start of the block, i.e. the address that was
  24022.  returned by allocate(). "
  24023.  >
  24024. <_2clist
  24025.   name="Comments:"
  24026.   description=
  24027. " Use free() to recycle blocks of memory during execution. This
  24028.  will reduce the chance of running out of memory or getting into
  24029.  excessive virtual memory swapping to disk. Do not reference
  24030.  a block of memory that has been freed. When your program
  24031.  terminates, all allocated memory will be returned to the system.
  24032. <P>
  24033. Do not use free() to deallocate memory that was allocated using
  24034.  <a href=\"lib_a_b.htm#allocate_low\">allocate_low()</a>.
  24035.  Use free_low() for this purpose."
  24036.  >
  24037. <_2clist
  24038.   name="Example Program:"
  24039.   description="<font color=\"#5500FF\"><b>demo\dos32\callmach.ex</b></font>"
  24040.  >
  24041.  
  24042.  <_2clist
  24043.   name="See Also:"
  24044.   description="<a href=\"lib_a_b.htm#allocate\">allocate</a>,
  24045. <a href=\"lib_e_g.htm#free_low\">free_low</a>"
  24046.  >
  24047. </table>
  24048.  
  24049.  
  24050. <_routine name="free_console">
  24051. <table border=0 cellspacing=2 cellpadding=2>
  24052.  
  24053.  
  24054.  <_2clist
  24055.   name="Platform:"
  24056.   description="<font color=\"#CC3366\"><b>WIN32, Linux</b></font>"
  24057.  >
  24058.  
  24059.  <_2clist
  24060.   name="Syntax:"
  24061.   description="<font face = \"Arial, Helvetica\"> include dll.e<BR>
  24062.  free_console()
  24063. </font>"
  24064.  >
  24065.  <_2clist
  24066.   name="Description:"
  24067.   description=
  24068. "Free (delete) any console window associated with your program."
  24069.  >
  24070. <_2clist
  24071.   name="Comments:"
  24072.   description=
  24073. "Euphoria will create a console <font color=\"CC3366\">text</font> window
  24074.  for your program the first time that your program prints something to the
  24075.  screen, reads something from the keyboard, or in some way needs a
  24076.  console (similar to a DOS-prompt window). On WIN32 this window will
  24077.  automatically disappear when your program terminates, but you
  24078.  can call free_console() to make it disappear sooner. On Linux, the
  24079.  text mode console is always there, but an xterm window will disappear
  24080.  after Euphoria issues a \"Press Enter\" prompt at the end of execution.
  24081.  
  24082. <p>
  24083.  On Linux, free_console()
  24084.  will set the terminal parameters back to normal, undoing the effect
  24085.  that curses has on the screen.
  24086. <p>
  24087. In a Linux xterm window, a call to free_console(), without any
  24088. further printing to the screen or reading from the keyboard, will eliminate
  24089. the \"Press Enter\" prompt that Euphoria normally issues at 
  24090. the end of execution.
  24091. <P>
  24092. After freeing the console window, you can create a new console
  24093.  window by printing something to the screen, or simply calling
  24094.  clear_screen(), <a href=\"lib_p_r.htm#position\">position()</a> or any
  24095.  other routine that needs a console.
  24096. <P>
  24097. When you use the <font color=\"#993333\"><b>trace</b></font> facility,
  24098.  or when your program has an
  24099.  error, Euphoria will automatically create a console window
  24100.  to display trace information, error messages etc.
  24101. <P>
  24102. There's a WIN32 API routine, FreeConsole() that does something
  24103.  similar to free_console(). You should use free_console(),
  24104.  because it lets the interpreter know that there is no longer
  24105.  a console."
  24106.  >
  24107. <_2clist
  24108.   name="See Also:"
  24109.   description="<a href=\"lib_c_d.htm#clear_screen\">clear_screen</a>,
  24110.  <a href=\"platform.htm#win32plat\"><font color=\"#5500FF\"><b>platform.doc</b>
  24111.  </font></a>"
  24112.  >
  24113. </table>
  24114.  
  24115.  
  24116. <_routine name="free_low">
  24117. <table border=0 cellspacing=2 cellpadding=2>
  24118.  
  24119.  
  24120.  <_2clist
  24121.   name="Platform:"
  24122.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  24123.  >
  24124.  
  24125.  <_2clist
  24126.   name="Syntax:"
  24127.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  24128.  free_low(i)
  24129. </font>"
  24130.  >
  24131.  <_2clist
  24132.   name="Description:"
  24133.   description=
  24134. "  Free up a previously allocated block of conventional memory by
  24135.  specifying the address of the start of the block, i.e. the
  24136.  address that was returned by allocate_low(). "
  24137.  >
  24138. <_2clist
  24139.   name="Comments:"
  24140.   description=
  24141. " Use free_low() to recycle blocks of conventional memory during
  24142.  execution. This will reduce the chance of running out of
  24143.  conventional memory. Do not reference a block of memory that has
  24144.  been freed. When your program terminates, all allocated memory
  24145.  will be returned to the system.
  24146. <P>
  24147. Do not use free_low() to deallocate memory that was allocated using
  24148.  <a href=\"lib_a_b.htm#allocate\">allocate()</a>. Use free() for this purpose."
  24149.  >
  24150. <_2clist
  24151.   name="Example Program:"
  24152.   description="<font color=\"#5500FF\"><b>demo\dos32\dosint.ex</b></font>"
  24153.  >
  24154.  
  24155.  <_2clist
  24156.   name="See Also:"
  24157.   description="<a href=\"lib_a_b.htm#allocate_low\">allocate_low</a>,
  24158. <a href=\"lib_c_d.htm#dos_interrupt\">dos_interrupt</a>,
  24159. <a href=\"lib_e_g.htm#free\">free</a>"
  24160.  >
  24161. </table>
  24162.  
  24163.  
  24164. <_routine name="get">
  24165. <table border=0 cellspacing=2 cellpadding=2>
  24166.  
  24167.  
  24168.  <_2clist
  24169.   name="Syntax:"
  24170.   description="<font face = \"Arial, Helvetica\"> include get.e<BR>
  24171.  s = get(fn)
  24172. </font>"
  24173.  >
  24174.  <_2clist
  24175.   name="Description:"
  24176.   description=
  24177. "Input, from file fn, a human-readable string of characters
  24178.  representing a Euphoria object. Convert the string into the
  24179.  numeric value of that object. s will be a 2-element sequence:
  24180.  <b>{error status, value}</b>. Error status codes are:"
  24181.  >
  24182. <_eucode>
  24183.     GET_SUCCESS -- object was read successfully
  24184.     GET_EOF     -- end of file before object was read
  24185.     GET_FAIL    -- object is not syntactically correct
  24186. </_eucode>
  24187.  
  24188.  <_2clist
  24189.   name=""
  24190.   description=
  24191. "get() can read arbitrarily complicated Euphoria objects. You
  24192.  could have a long sequence of values in braces and separated by
  24193.  commas, e.g. {23, {49, 57}, 0.5, -1, 99, 'A', \"john\"}.
  24194.  <font color=\"#CC0099\"><b>A single call to get() will read in this
  24195.  entire sequence and return it's value as a result.</b></font>
  24196. <P>
  24197. Each call to get() picks up where the previous call left off. For
  24198.  instance, a series of 5 calls to get() would be needed to read
  24199.  in:
  24200. <P>
  24201. 99 5.2 {1,2,3} \"Hello\" -1
  24202. <P>
  24203. On the sixth and any subsequent call to get() you would see a
  24204.  GET_EOF status. If you had something like:
  24205. <P>
  24206. {1, 2, xxx}
  24207. <P>
  24208. in the input stream you would see a GET_FAIL error status
  24209.  because xxx is not a Euphoria object.
  24210. <P>
  24211. Multiple \"top-level\" objects in the input stream must be
  24212.  separated from each other with one or more \"whitespace\"
  24213.  characters (blank, tab, \r or \n). Whitespace is not necessary
  24214.  <b><i>within</i></b> a top-level object. A call to get() will 
  24215.  read one entire top-level object, plus one additional 
  24216.  (whitespace) character."
  24217.  >
  24218. <_2clist
  24219.   name="Comments:"
  24220.   description=
  24221. "The combination of print() and get() can be used to save a
  24222.  Euphoria object to disk and later read it back. This technique
  24223.  could be used to implement a database as one or more large
  24224.  Euphoria sequences stored in disk files. The sequences could be
  24225.  read into memory, updated and then written back to disk after
  24226.  each series of transactions is complete. Remember to write out
  24227.  a whitespace character (using puts()) after each call to print().
  24228. <P>
  24229. The value returned is not meaningful unless you have a
  24230.  GET_SUCCESS status.
  24231.  "
  24232.  >
  24233. <_2clist
  24234.   name="Example:"
  24235.   description="Suppose your program asks the user to enter a number from the
  24236.   keyboard."
  24237.  >
  24238. <_eucode>
  24239. -- If he types 77.5, get(0) would return:
  24240.  
  24241. {GET_SUCCESS, 77.5}
  24242.  
  24243. -- whereas gets(0) would return:
  24244.  
  24245. "77.5\n"
  24246.  
  24247.  </_eucode>
  24248. <_2clist
  24249.   name="Example Program:"
  24250.   description="<font color=\"#5500FF\"><b>demo\mydata.ex</b></font>"
  24251.  >
  24252.  
  24253.  <_2clist
  24254.   name="See Also:"
  24255.   description="<a href=\"lib_p_r.htm#print\">print</a>,
  24256. <a href=\"lib_u_z.htm#value\">value</a>,
  24257. <a href=\"lib_e_g.htm#gets\">gets</a>,
  24258. <a href=\"lib_e_g.htm#getc\">getc</a>,
  24259. <a href=\"lib_p_r.htm#prompt_number\">prompt_number</a>,
  24260. <a href=\"lib_p_r.htm#prompt_string\">prompt_string</a>"
  24261.  >
  24262. </table>
  24263.  
  24264.  
  24265. <_routine name="get_active_page">
  24266. <table border=0 cellspacing=2 cellpadding=2>
  24267.  
  24268.  
  24269.  <_2clist
  24270.   name="Platform:"
  24271.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  24272.  >
  24273.  
  24274.  <_2clist
  24275.   name="Syntax:"
  24276.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  24277.  i = get_active_page()
  24278. </font>"
  24279.  >
  24280.  <_2clist
  24281.   name="Description:"
  24282.   description=
  24283. "Some graphics modes on most video cards have
  24284.  multiple pages of memory. This lets you write screen output to one page
  24285.  while displaying a different page. get_active_page() returns
  24286.  the current page number that screen output is being sent to."
  24287.  >
  24288. <_2clist
  24289.   name="Comments:"
  24290.   description=
  24291. " The active and display pages are both 0 by default.
  24292. <P>
  24293. video_config() will tell you how many pages are available in
  24294.  the current graphics mode."
  24295.  >
  24296. <_2clist
  24297.   name="See Also:"
  24298.   description="<a href=\"lib_s_t.htm#set_active_page\">set_active_page</a>,
  24299. <a href=\"lib_e_g.htm#get_display_page\">get_display_page</a>,
  24300. <a href=\"lib_u_z.htm#video_config\">video_config</a>"
  24301.  >
  24302. </table>
  24303.  
  24304.  
  24305. <_routine name="get_all_palette">
  24306. <table border=0 cellspacing=2 cellpadding=2>
  24307.  
  24308.  
  24309.  <_2clist
  24310.   name="Platform:"
  24311.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  24312.  >
  24313.  
  24314.  <_2clist
  24315.   name="Syntax:"
  24316.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  24317.  s = get_all_palette()
  24318. </font>"
  24319.  >
  24320.  <_2clist
  24321.   name="Description:"
  24322.   description=
  24323. "Retrieve color intensities for the entire set of colors in the current
  24324.  graphics mode. s is a sequence of the form:<p>
  24325.  {{r,g,b}, {r,g,b}, ..., {r,g,b}}
  24326. <p>
  24327. Each element specifies a color intensity {red, green, blue}
  24328.  for the corresponding color number, starting with color
  24329.  number 0. The values for red, green and blue will be in the
  24330.  range 0 to 63."
  24331.  >
  24332. <_2clist
  24333.   name="Comments:"
  24334.   description=
  24335. " This function might be used to get the palette values needed
  24336.  by save_bitmap(). Remember to multiply these values by 4 before
  24337.  calling save_bitmap(), since save_bitmap() expects values in the
  24338.  range 0 to 255.
  24339.  "
  24340.  >
  24341. <_2clist
  24342.   name="See Also:"
  24343.   description="<a href=\"lib_p_r.htm#palette\">palette</a>,
  24344. <a href=\"lib_a_b.htm#all_palette\">all_palette</a>,
  24345. <a href=\"lib_p_r.htm#read_bitmap\">read_bitmap</a>,
  24346. <a href=\"lib_s_t.htm#save_bitmap\">save_bitmap</a>,
  24347. <a href=\"lib_s_t.htm#save_screen\">save_screen</a>"
  24348.  >
  24349. </table>
  24350.  
  24351.  
  24352. <_routine name="get_bytes">
  24353. <table border=0 cellspacing=2 cellpadding=2>
  24354.  
  24355.  
  24356.  <_2clist
  24357.   name="Syntax:"
  24358.   description="<font face = \"Arial, Helvetica\"> include get.e<BR>
  24359.  s = get_bytes(fn, i)
  24360. </font>"
  24361.  >
  24362.  <_2clist
  24363.   name="Description:"
  24364.   description=
  24365. "Read the next i bytes from file number fn. Return the bytes
  24366.  as a sequence. The sequence will be of length i, except
  24367.  when there are fewer than i bytes remaining to be read in the
  24368.  file. "
  24369.  >
  24370. <_2clist
  24371.   name="Comments:"
  24372.   description=
  24373. "When i > 0 and <a href=\"lib_h_o.htm#length\">length(s)</a> < i you know
  24374.  you've reached the end of file. Eventually, an
  24375.  <a href=\"refman_2.htm#empty_seq\">empty sequence</a> will be returned
  24376.  for s."
  24377.  >
  24378. <_2clist
  24379.   name="Example:"
  24380.   description=""
  24381.  >
  24382. <_eucode>
  24383. include get.e
  24384.  
  24385. integer fn
  24386. fn = open("temp", "rb")  -- an existing file
  24387.  
  24388. sequence whole_file
  24389. whole_file = {}
  24390.  
  24391. sequence chunk
  24392.  
  24393. while 1 do
  24394.     chunk = get_bytes(fn, 100) -- read 100 bytes at a time
  24395.     whole_file &= chunk        -- chunk might be empty, that's ok
  24396.     if length(chunk) < 100 then
  24397.         exit
  24398.     end if
  24399. end while
  24400.  
  24401. close(fn)
  24402. ? length(whole_file)  -- should match DIR size of "temp"
  24403.  
  24404.  </_eucode>
  24405. <_2clist
  24406.   name="See Also:"
  24407.   description="<a href=\"lib_e_g.htm#getc\">getc</a>,
  24408. <a href=\"lib_e_g.htm#gets\">gets</a>"
  24409.  >
  24410. </table>
  24411.  
  24412.  
  24413. <_routine name="get_display_page">
  24414. <table border=0 cellspacing=2 cellpadding=2>
  24415.  
  24416.  
  24417.  <_2clist
  24418.   name="Platform:"
  24419.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  24420.  >
  24421.  
  24422.  <_2clist
  24423.   name="Syntax:"
  24424.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  24425.  i = get_display_page()
  24426. </font>"
  24427.  >
  24428.  <_2clist
  24429.   name="Description:"
  24430.   description=
  24431. "Some graphics modes on most video cards
  24432.  have multiple pages of memory. This lets you write screen output to one page
  24433.  while displaying another. get_display_page() returns the current
  24434.  page number that is being displayed on the monitor."
  24435.  >
  24436. <_2clist
  24437.   name="Comments:"
  24438.   description=
  24439. "The active and display pages are both 0 by default.
  24440. <P>
  24441. video_config() will tell you how many pages are available in
  24442.  the current graphics mode."
  24443.  >
  24444. <_2clist
  24445.   name="See Also:"
  24446.   description="<a href=\"lib_s_t.htm#set_display_page\">set_display_page</a>,
  24447. <a href=\"lib_e_g.htm#get_active_page\">get_active_page</a>,
  24448. <a href=\"lib_u_z.htm#video_config\">video_config</a>"
  24449.  >
  24450. </table>
  24451.  
  24452.  
  24453. <_routine name="get_key">
  24454. <table border=0 cellspacing=2 cellpadding=2>
  24455.  
  24456.  
  24457.  <_2clist
  24458.   name="Syntax:"
  24459.   description="<font face = \"Arial, Helvetica\"> i = get_key()
  24460. </font>"
  24461.  >
  24462.  <_2clist
  24463.   name="Description:"
  24464.   description=
  24465. "Return the key that was pressed by the user, without waiting.
  24466.  Return -1 if no key was pressed. Special
  24467.  codes are returned for the function keys, arrow keys etc. "
  24468.  >
  24469. <_2clist
  24470.   name="Comments:"
  24471.   description=
  24472. "The operating system can hold a small number of key-hits in its 
  24473.  keyboard buffer. get_key() will return the next one from the buffer, 
  24474.  or -1 if the buffer is empty.
  24475. <P>
  24476. Run the <font color=\"#5500FF\"><b>key.bat</b></font> program to see what
  24477.  key code is generated for each key on your keyboard."
  24478.  >
  24479. <_2clist
  24480.   name="See Also:"
  24481.   description="<a href=\"lib_u_z.htm#wait_key\">wait_key</a>,
  24482. <a href=\"lib_e_g.htm#getc\">getc</a>"
  24483.  >
  24484. </table>
  24485.  
  24486.  
  24487. <_routine name="get_mouse">
  24488. <table border=0 cellspacing=2 cellpadding=2>
  24489.  
  24490.  
  24491.  <_2clist
  24492.   name="Platform:"
  24493.   description="<font color=\"#CC3366\"><b>DOS32, Linux</b></font>"
  24494.  >
  24495.  
  24496.  <_2clist
  24497.   name="Syntax:"
  24498.   description="<font face = \"Arial, Helvetica\"> include mouse.e<BR>
  24499.  x1 = get_mouse()
  24500. </font>"
  24501.  >
  24502.  <_2clist
  24503.   name="Description:"
  24504.   description=
  24505. "Return the last mouse event in the form: <b>{event, x, y}</b> or
  24506.  return -1 if there has not been a mouse event since the last
  24507.  time get_mouse() was called.
  24508. <P>
  24509. Constants have been defined in
  24510.  <font color=\"#5500FF\"><b>mouse.e</b></font> for the possible mouse
  24511.  events:"
  24512.  >
  24513. <_eucode>
  24514.     global constant MOVE = 1,
  24515.                LEFT_DOWN = 2,
  24516.                  LEFT_UP = 4,
  24517.               RIGHT_DOWN = 8,
  24518.                 RIGHT_UP = 16,
  24519.              MIDDLE_DOWN = 32,
  24520.                MIDDLE_UP = 64
  24521. </_eucode>
  24522.  
  24523.  <_2clist
  24524.   name=""
  24525.   description=
  24526. "x and y are the coordinates of the mouse pointer at the time that
  24527.  the event occurred. get_mouse() returns immediately with either
  24528.  a -1 or a mouse event. It does not wait for an event to occur.
  24529.  You must check it frequently enough to avoid missing an event.
  24530.  When the next event occurs, the current event will be lost, if
  24531.  you haven't read it. In practice it is not hard to catch almost
  24532.  all events. Losing a MOVE event is generally not too serious,
  24533.  as the next MOVE will tell you where the mouse pointer is.
  24534. <P>
  24535. Sometimes multiple events will be reported. For example, if the
  24536.  mouse is moving when the left button is clicked, get_mouse()
  24537.  will report an event value of LEFT_DOWN+MOVE, i.e. 2+1 or 3.
  24538.  For this reason you should test for a particular event using
  24539.  and_bits(). See examples below.
  24540.  "
  24541.  >
  24542. <_2clist
  24543.   name="Comments:"
  24544.   description=
  24545. "In <font color=\"#CC3366\">pixel-graphics modes</font> that are 320 pixels
  24546.  wide, you need to divide the x value by 2 to get the correct position on
  24547.  the screen. (A strange feature of DOS.)
  24548. <P>
  24549. In DOS32 <font color=\"#CC3366\">text modes</font> you need to scale the x and y
  24550.  coordinates to get line and column positions. In Linux, no scaling is
  24551.  required - x and y correspond to the line and column on the screen, 
  24552.  with (1,1) at the top left. 
  24553. <P>
  24554. In DOS32, you need a DOS mouse driver to use this routine. In Linux, 
  24555. GPM Server must be running.
  24556. <p>
  24557. In Linux, mouse movement events are not reported in an xterm window, 
  24558. only in the text console. 
  24559. <P>
  24560. In Linux, LEFT_UP, RIGHT_UP and MIDDLE_UP are not distinguishable 
  24561. from one another.
  24562. <P>
  24563. You can use get_mouse() in <font color=\"#CC3366\">most text and
  24564.  pixel-graphics modes</font>.
  24565. <P>
  24566. The first call that you make to get_mouse() will turn on a
  24567.  mouse pointer, or a highlighted character.
  24568. <P>
  24569. DOS generally does not support the use of a mouse in SVGA
  24570.  graphics modes (beyond 640x480 pixels). This restriction
  24571.  has been removed in Windows 95 (DOS 7.0). <b>Graeme Burke</b>,
  24572.  <b>Peter Blue</b> and others have contributed <b>mouse routines</b> that
  24573.  get around the problems with using a mouse in SVGA. See the
  24574.  Euphoria <a href=\"http://www.RapidEuphoria.com/exestuff.htm\">Archive
  24575.  Web page</a>.
  24576. <P>
  24577. The x,y coordinate returned could be that of the very tip of the
  24578.  mouse pointer or might refer to the pixel pointed-to by
  24579.  the mouse pointer. Test this if you are trying to read the
  24580.  pixel color using <a href=\"lib_e_g.htm#get_pixel\">get_pixel()</a>. You
  24581.  may have to read x-1,y-1 instead."
  24582.  >
  24583. <_2clist
  24584.   name="Example 1:"
  24585.   description=" a return value of:"
  24586.  >
  24587.  
  24588. <_eucode>
  24589. {2, 100, 50}
  24590. </_eucode>
  24591.  
  24592. <_2clist
  24593.   name=""
  24594.   description="would indicate that the left button was pressed down when the
  24595.  mouse pointer was at location x=100, y=50 on the screen."
  24596.  >
  24597.  
  24598. <_2clist
  24599.   name="Example 2:"
  24600.   description=" To test for LEFT_DOWN, write something like the following:"
  24601.  >
  24602.  
  24603. <_eucode>
  24604. object event
  24605.  
  24606. while 1 do
  24607.     event = get_mouse()
  24608.     if sequence(event) then
  24609.         if and_bits(event[1], LEFT_DOWN) then
  24610.             -- left button was pressed
  24611.             exit
  24612.         end if
  24613.     end if
  24614. end while
  24615.  
  24616.  </_eucode>
  24617. <_2clist
  24618.   name="See Also:"
  24619.   description="<a href=\"lib_h_o.htm#mouse_events\">mouse_events</a>,
  24620. <a href=\"lib_h_o.htm#mouse_pointer\">mouse_pointer</a>,
  24621. <a href=\"lib_a_b.htm#and_bits\">and_bits</a>"
  24622.  >
  24623. </table>
  24624.  
  24625.  
  24626. <_routine name="get_pixel">
  24627. <table border=0 cellspacing=2 cellpadding=2>
  24628.  
  24629.  
  24630.  <_2clist
  24631.   name="Platform:"
  24632.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  24633.  >
  24634.  
  24635.  <_2clist
  24636.   name="Syntax:"
  24637.   description="<font face = \"Arial, Helvetica\"> x = get_pixel(s)
  24638. </font>"
  24639.  >
  24640.  <_2clist
  24641.   name="Description:"
  24642.   description=
  24643. "When s is a 2-element screen coordinate {x, y}, get_pixel()
  24644.  returns the color (a small integer) of the pixel on the
  24645.  <font color=\"#CC3366\">pixel-graphics</font> screen
  24646.  at that point.<P>
  24647. When s is a 3-element sequence of the form: {x, y, n}
  24648.  get_pixel() returns a sequence of n colors for the
  24649.  points starting at {x, y} and moving to the right {x+1, y},
  24650.  {x+2, y} etc.
  24651. <P>
  24652. Points off the screen have unpredictable color values."
  24653.  >
  24654. <_2clist
  24655.   name="Comments:"
  24656.   description=
  24657. "When n is specified, a very fast algorithm is used to read the
  24658.  pixel colors on the screen. It is much faster to call get_pixel()
  24659.  once, specifying a large value of n, than it is to call it many
  24660.  times, reading one pixel color at a time."
  24661.  >
  24662. <_2clist
  24663.   name="Example:"
  24664.   description=""
  24665.  >
  24666. <_eucode>
  24667. object x
  24668.  
  24669. x = get_pixel({30,40})
  24670. -- x is set to the color value of point x=30, y=40
  24671.  
  24672. x = get_pixel({30,40,100})
  24673. -- x is set to a sequence of 100 integer values, representing
  24674. -- the colors starting at {30,40} and going to the right
  24675.  
  24676.  </_eucode>
  24677. <_2clist
  24678.   name="See Also:"
  24679.   description="<a href=\"lib_p_r.htm#pixel\">pixel</a>,
  24680. <a href=\"lib_e_g.htm#graphics_mode\">graphics_mode</a>,
  24681. <a href=\"lib_e_g.htm#get_position\">get_position</a>"
  24682.  >
  24683. </table>
  24684.  
  24685.  
  24686. <_routine name="get_position">
  24687. <table border=0 cellspacing=2 cellpadding=2>
  24688.  
  24689.  
  24690.  <_2clist
  24691.   name="Syntax:"
  24692.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  24693.  s = get_position()
  24694. </font>"
  24695.  >
  24696.  <_2clist
  24697.   name="Description:"
  24698.   description=
  24699. "Return the current line and column position of the cursor as a
  24700.  2-element sequence <b>{line, column}</b>. "
  24701.  >
  24702. <_2clist
  24703.   name="Comments:"
  24704.   description=
  24705. "get_position() works in both <font color=\"#CC3366\">text and
  24706.  pixel-graphics modes</font>.
  24707.  In <font color=\"#CC3366\">pixel-graphics modes</font> no cursor will be
  24708.  displayed, but get_position() will return the line and column where the
  24709.  next character will be displayed.
  24710. <P>
  24711. The coordinate system for displaying text is different from the
  24712.  one for displaying pixels. Pixels are displayed such that the
  24713.  top-left is (x=0,y=0) and the first coordinate controls the
  24714.  horizontal, left-right location. In pixel-graphics modes
  24715.  you can display both text and pixels. get_position() returns the
  24716.  current line and column for the text that you are displaying,
  24717.  not the pixels that you may be plotting. There is no
  24718.  corresponding routine for getting the current pixel position.
  24719.  "
  24720.  >
  24721. <_2clist
  24722.   name="See Also:"
  24723.   description="<a href=\"lib_p_r.htm#position\">position</a>,
  24724. <a href=\"lib_e_g.htm#get_pixel\">get_pixel</a>"
  24725.  >
  24726. </table>
  24727.  
  24728.  
  24729. <_routine name="get_screen_char">
  24730. <table border=0 cellspacing=2 cellpadding=2>
  24731.  
  24732.  
  24733.  <_2clist
  24734.   name="Syntax:"
  24735.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  24736.  s = get_screen_char(i1, i2)
  24737. </font>"
  24738.  >
  24739.  <_2clist
  24740.   name="Description:"
  24741.   description=
  24742. "Return a 2-element sequence s, of the form
  24743.   <b>{ascii-code, attributes}</b> for
  24744.  the character on the screen at line i1, column i2. s consists of
  24745.  two atoms. The first is the ASCII code for the character. The second
  24746.  is an atom that contains the foreground and background color of the character,
  24747.  and possibly other information describing the appearance of the character
  24748.  on the screen."
  24749.  >
  24750. <_2clist
  24751.   name="Comments:"
  24752.   description="With get_screen_char() and put_screen_char() you can
  24753.    save and restore a character on the screen along with its attributes."
  24754.  >
  24755. <_2clist
  24756.   name="Example:"
  24757.   description=""
  24758.  >
  24759. <_eucode>
  24760. -- read character and attributes at top left corner
  24761. s = get_screen_char(1,1) 
  24762. -- store character and attributes at line 25, column 10
  24763. put_screen_char(25, 10, {s})
  24764. </_eucode>
  24765. <_2clist
  24766.   name="See Also:"
  24767.   description="<a href=\"lib_p_r.htm#put_screen_char\">put_screen_char</a>,
  24768. <a href=\"lib_s_t.htm#save_text_image\">save_text_image</a>"
  24769.  >
  24770. </table>
  24771.  
  24772.  
  24773. <_routine name="get_vector">
  24774. <table border=0 cellspacing=2 cellpadding=2>
  24775.  
  24776.  
  24777.  <_2clist
  24778.   name="Platform:"
  24779.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  24780.  >
  24781.  
  24782.  <_2clist
  24783.   name="Syntax:"
  24784.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  24785.  s = get_vector(i)
  24786. </font>"
  24787.  >
  24788.  <_2clist
  24789.   name="Description:"
  24790.   description=
  24791. "Return the current protected mode far address of the handler
  24792.  for interrupt number i. s will be a 2-element sequence:
  24793.  <b>{16-bit segment, 32-bit offset}</b>."
  24794.  >
  24795. <_2clist
  24796.   name="Example:"
  24797.   description=""
  24798.  >
  24799. <_eucode>
  24800. s = get_vector(#1C)
  24801. -- s will be set to the far address of the clock tick
  24802. -- interrupt handler, for example: {59, 808}
  24803.  
  24804.  </_eucode>
  24805. <_2clist
  24806.   name="Example Program:"
  24807.   description="<font color=\"#5500FF\"><b>demo\dos32\hardint.ex</b></font>"
  24808.  >
  24809.  
  24810.  <_2clist
  24811.   name="See Also:"
  24812.   description="<a href=\"lib_s_t.htm#set_vector\">set_vector</a>,
  24813. <a href=\"lib_h_o.htm#lock_memory\">lock_memory</a>"
  24814.  >
  24815. </table>
  24816.  
  24817.  
  24818. <_routine name="getc">
  24819. <table border=0 cellspacing=2 cellpadding=2>
  24820.  
  24821.  
  24822.  <_2clist
  24823.   name="Syntax:"
  24824.   description="<font face = \"Arial, Helvetica\"> i = getc(fn)
  24825. </font>"
  24826.  >
  24827.  <_2clist
  24828.   name="Description:"
  24829.   description=
  24830. "Get the next character (byte) from file or device fn. The character will
  24831.  have a value from 0 to 255. -1 is returned at end of file."
  24832.  >
  24833. <_2clist
  24834.   name="Comments:"
  24835.   description=
  24836. "File input using getc() is buffered, i.e. getc() does not actually
  24837.  go out to the disk for each character. Instead, a large block of
  24838.  characters will be read in at one time and returned to you one
  24839.  by one from a memory buffer.
  24840.  <p>
  24841.  When getc() reads from the keyboard, it will not see any characters until
  24842.  the user presses Enter.
  24843.  Note that the user can type
  24844.  control-Z, which the operating system treats as \"end of file\".
  24845.  -1 will be returned."
  24846.  >
  24847. <_2clist
  24848.   name="See Also:"
  24849.   description="<a href=\"lib_e_g.htm#gets\">gets</a>,
  24850. <a href=\"lib_e_g.htm#get_key\">get_key</a>,
  24851. <a href=\"lib_u_z.htm#wait_key\">wait_key</a>,
  24852. <a href=\"lib_h_o.htm#open\">open</a>"
  24853.  >
  24854. </table>
  24855.  
  24856.  
  24857. <_routine name="getenv">
  24858. <table border=0 cellspacing=2 cellpadding=2>
  24859.  
  24860.  
  24861.  <_2clist
  24862.   name="Syntax:"
  24863.   description="<font face = \"Arial, Helvetica\"> x = getenv(s)
  24864. </font>"
  24865.  >
  24866.  <_2clist
  24867.   name="Description:"
  24868.   description=
  24869. "Return the value of a DOS environment variable. If the variable
  24870.  is undefined return -1."
  24871.  >
  24872. <_2clist
  24873.   name="Comments:"
  24874.   description=
  24875. " Because either a sequence or an atom (-1) might be returned, you
  24876.  should probably assign the result to a variable declared as
  24877.  object."
  24878.  >
  24879. <_2clist
  24880.   name="Example:"
  24881.   description=""
  24882.  >
  24883. <_eucode>
  24884. e = getenv("EUDIR")
  24885. -- e will be "C:\EUPHORIA" -- or perhaps D:, E: etc.
  24886.  
  24887.  </_eucode>
  24888. <_2clist
  24889.   name="See Also:"
  24890.   description="<a href=\"lib_c_d.htm#command_line\">command_line</a>"
  24891.  >
  24892. </table>
  24893.  
  24894.  
  24895. <_routine name="gets">
  24896. <table border=0 cellspacing=2 cellpadding=2>
  24897.  
  24898.  
  24899.  <_2clist
  24900.   name="Syntax:"
  24901.   description="<font face = \"Arial, Helvetica\"> x = gets(fn)
  24902. </font>"
  24903.  >
  24904.  <_2clist
  24905.   name="Description:"
  24906.   description=
  24907. "Get the next sequence (one line, including '\n') of characters
  24908.  from file or device fn. The characters will have values from 0
  24909.  to 255. The atom -1 is returned on end of file."
  24910.  >
  24911. <_2clist
  24912.   name="Comments:"
  24913.   description=
  24914. "Because either a sequence or an atom (-1) might be returned, you
  24915.  should probably assign the result to a variable declared as
  24916.  object.
  24917. <P>
  24918. After reading a line of text from the keyboard, you should
  24919.  normally output a \n character, e.g. puts(1, '\n'), before
  24920.  printing something. Only on the last line of the screen does the
  24921.  operating system automatically scroll the screen and advance to
  24922.  the next line.
  24923. <P>
  24924. The last line in a file might not end with a new-line '\n'
  24925.  character.
  24926. <P>
  24927. When your program reads from the keyboard, the user can type
  24928.  control-Z, which the operating system treats as \"end of file\".
  24929.  -1 will be returned.
  24930. <P>
  24931. In SVGA modes, DOS might set the wrong cursor position, after a call to
  24932.  gets(0) to read the keyboard. You should set it yourself using
  24933.  <a href=\"lib_p_r.htm#position\">position()</a>."
  24934.  >
  24935. <_2clist
  24936.   name="Example 1:"
  24937.   description=""
  24938.  >
  24939. <_eucode>
  24940. sequence buffer
  24941. object line
  24942. integer fn
  24943.  
  24944. -- read a text file into a sequence
  24945. fn = open("myfile.txt", "r")
  24946. if fn = -1 then
  24947.     puts(1, "Couldn't open myfile.txt\n")
  24948.     abort(1)
  24949. end if
  24950.  
  24951. buffer = {}
  24952. while 1 do
  24953.     line = gets(fn)
  24954.     if atom(line) then
  24955.         exit   -- -1 is returned at end of file
  24956.     end if
  24957.     buffer = append(buffer, line)
  24958. end while
  24959.  
  24960.  </_eucode>
  24961. <_2clist
  24962.   name="Example 2:"
  24963.   description=""
  24964.  >
  24965. <_eucode>
  24966. object line
  24967.  
  24968. puts(1, "What is your name?\n")
  24969. line = gets(0)  -- read standard input (keyboard)
  24970. line = line[1..length(line)-1] -- get rid of \n character at end
  24971. puts(1, '\n')   -- necessary
  24972. puts(1, line & " is a nice name.\n")
  24973.  
  24974.  </_eucode>
  24975. <_2clist
  24976.   name="See Also:"
  24977.   description="<a href=\"lib_e_g.htm#getc\">getc</a>,
  24978. <a href=\"lib_p_r.htm#puts\">puts</a>,
  24979. <a href=\"lib_h_o.htm#open\">open</a>"
  24980.  >
  24981. </table>
  24982.  
  24983.  
  24984. <_routine name="graphics_mode">
  24985. <table border=0 cellspacing=2 cellpadding=2>
  24986.  
  24987.  
  24988.  <_2clist
  24989.   name="Platform:"
  24990.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  24991.  >
  24992.  
  24993.  <_2clist
  24994.   name="Syntax:"
  24995.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  24996.  i1 = graphics_mode(i2)
  24997. </font>"
  24998.  >
  24999.  <_2clist
  25000.   name="Description:"
  25001.   description=
  25002. "Select graphics mode i2. See <font color=\"#5500FF\"><b>graphics.e</b></font>
  25003.  for a list of valid graphics modes. If successful, i1 is set to 0,
  25004.  otherwise i1 is set to 1."
  25005.  >
  25006. <_2clist
  25007.   name="Comments:"
  25008.   description=
  25009. "Some modes are referred to as <font color=\"#CC3366\">text modes</font>
  25010.  because they only let you display text. Other modes are referred to as
  25011.  <font color=\"#CC3366\">pixel-graphics modes</font> because you can
  25012.  display pixels, lines, ellipses etc., as well as text.
  25013. <P>
  25014. As a convenience to your users, it is usually a good idea to
  25015.  switch back from a pixel-graphics mode to the standard text
  25016.  mode before your program terminates. You can do this with
  25017.  graphics_mode(-1). If a pixel-graphics program leaves your screen
  25018.  in a mess, you can clear it up with the DOS CLS command, or
  25019.  by running <font color=\"#993333\"><b>ex</b></font> or
  25020.  <font color=\"#993333\"><b>ed</b></font>.
  25021. <P>
  25022. Some graphics cards will be unable to enter some SVGA modes,
  25023.  under some conditions. You can't always tell from the i1 value,
  25024.  whether the graphics mode was set up successfully.
  25025. <P>
  25026. On the <font color=\"#CC3366\"><b>WIN32</b></font> and 
  25027. <font color=\"#CC3366\"><b>Linux</b></font>
  25028. platforms, graphics_mode() will allocate a plain, text mode console if one
  25029. does not exist yet. It will then return 0, no matter what value is 
  25030. passed as i2."
  25031.  >
  25032. <_2clist
  25033.   name="Example:"
  25034.   description=""
  25035.  >
  25036. <_eucode>
  25037. if graphics_mode(18) then
  25038.     puts(SCREEN, "need VGA graphics!\n")
  25039.     abort(1)
  25040. end if
  25041. draw_line(BLUE, {{0,0}, {50,50}})
  25042.  
  25043.  </_eucode>
  25044. <_2clist
  25045.   name="See Also:"
  25046.   description="<a href=\"lib_s_t.htm#text_rows\">text_rows</a>,
  25047. <a href=\"lib_u_z.htm#video_config\">video_config</a>"
  25048.  >
  25049. </table>
  25050.  
  25051. <_continue
  25052.   href="lib_h_o.htm"
  25053.   name="From H to O"
  25054. >
  25055.  
  25056. </body>
  25057. </html>
  25058. LIB_H_O.HTX
  25059. 28390
  25060. <_init_comment>
  25061. <html>
  25062. <head><title>Euphoria v2.2 Reference Manual Part II - Section 3</title>
  25063. </head>
  25064. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  25065. <br>
  25066.  
  25067.  
  25068. <_routine name="instance">
  25069. <table border=0 cellspacing=2 cellpadding=2>
  25070.  
  25071.  
  25072.  <_2clist
  25073.   name="Platform:"
  25074.   description="<font color=\"#CC3366\"><b>WIN32</b></font>"
  25075.  >
  25076.  
  25077.  <_2clist
  25078.   name="Syntax:"
  25079.   description="<font face = \"Arial, Helvetica\"> include misc.e<BR>
  25080.  i = instance()
  25081. </font>"
  25082.  >
  25083.  <_2clist
  25084.   name="Description:"
  25085.   description=
  25086. "Return a handle to the current program."
  25087.  >
  25088. <_2clist
  25089.   name="Comments:"
  25090.   description=
  25091. "This handle value can be passed to various Windows routines
  25092.  to get information about the current program that is running,
  25093.  i.e. your program. Each time a user starts up your program,
  25094.  a different instance will be created.
  25095. <p>
  25096. In C, this is the first parameter to WinMain().
  25097. <P>
  25098. On <font color=\"#CC3366\"><b>DOS32 and Linux</b></font>, instance() always returns 0."
  25099.  >
  25100. <_2clist
  25101.   name="See Also:"
  25102.   description="
  25103.  <a href=\"platform.htm#win32plat\"><font color=\"#5500FF\"><b>platform.doc</b>
  25104.  </font></a>"
  25105.  >
  25106. </table>
  25107.  
  25108.  
  25109. <_routine name="int_to_bits">
  25110. <table border=0 cellspacing=2 cellpadding=2>
  25111.  
  25112.  
  25113.  <_2clist
  25114.   name="Syntax:"
  25115.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  25116.  s = int_to_bits(a, i)
  25117. </font>"
  25118.  >
  25119.  <_2clist
  25120.   name="Description:"
  25121.   description=
  25122. "Return the low-order i bits of a, as a sequence of 1's and 0's.
  25123.  The least significant bits come first. For negative numbers
  25124.  the two's complement bit pattern is returned."
  25125.  >
  25126. <_2clist
  25127.   name="Comments:"
  25128.   description=
  25129. "You can use <a href=\"refman_2.htm#21\">subscripting</a>,
  25130.  <a href=\"refman_2.htm#22\">slicing</a>,
  25131.  <a href=\"refman_2.htm#24\">and/or/xor/not</a> of entire
  25132.  sequences etc. to manipulate sequences of bits. Shifting
  25133.  of bits and rotating of bits are easy to perform."
  25134.  >
  25135. <_2clist
  25136.   name="Example:"
  25137.   description=""
  25138.  >
  25139. <_eucode>
  25140. s = int_to_bits(177, 8)
  25141. -- s is {1,0,0,0,1,1,0,1} -- "reverse" order
  25142.  
  25143.  </_eucode>
  25144. <_2clist
  25145.   name="See Also:"
  25146.   description="<a href=\"lib_a_b.htm#bits_to_int\">bits_to_int</a>,
  25147. <a href=\"lib_a_b.htm#and_bits\">and_bits</a>,
  25148. <a href=\"lib_h_o.htm#or_bits\">or_bits</a>,
  25149. <a href=\"lib_u_z.htm#xor_bits\">xor_bits</a>,
  25150. <a href=\"lib_h_o.htm#not_bits\">not_bits</a>,
  25151. <a href=\"refman_2.htm#26\">operations on sequences</a>"
  25152.  >
  25153. </table>
  25154.  
  25155.  
  25156. <_routine name="int_to_bytes">
  25157. <table border=0 cellspacing=2 cellpadding=2>
  25158.  
  25159.  
  25160.  <_2clist
  25161.   name="Syntax:"
  25162.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  25163.  s = int_to_bytes(a)
  25164. </font>"
  25165.  >
  25166.  <_2clist
  25167.   name="Description:"
  25168.   description=
  25169. "  Convert an integer into a sequence of 4 bytes. These bytes are in
  25170.  the order expected on the 386+, i.e. least-significant byte
  25171.  first. "
  25172.  >
  25173. <_2clist
  25174.   name="Comments:"
  25175.   description=
  25176. " You might use this routine prior to poking the 4 bytes into
  25177.  memory for use by a machine language program.
  25178. <P>
  25179. The integer can be negative. Negative byte-values will be
  25180.  returned, but after poking them into memory you will have
  25181.  the correct (two's complement) representation for the 386+.
  25182. <P>
  25183. This function will correctly convert integer values up to 32-bits. For
  25184.  larger values, only the low-order 32-bits are converted. Euphoria's
  25185.  integer type only allows values up to 31-bits, so declare your variables as
  25186.  <font color=\"#993333\"><b>atom</b></font> if you need a larger range."
  25187.  >
  25188. <_2clist
  25189.   name="Example 1:"
  25190.   description=""
  25191.  >
  25192. <_eucode>
  25193. s = int_to_bytes(999)
  25194. -- s is {231, 3, 0, 0}
  25195.  
  25196.  </_eucode>
  25197. <_2clist
  25198.   name="Example 2:"
  25199.   description=""
  25200.  >
  25201. <_eucode>
  25202. s = int_to_bytes(-999)
  25203. -- s is {-231, -4, -1, -1}
  25204.  
  25205.  </_eucode>
  25206. <_2clist
  25207.   name="See Also:"
  25208.   description="<a href=\"lib_a_b.htm#bytes_to_int\">bytes_to_int</a>,
  25209. <a href=\"lib_h_o.htm#int_to_bits\">int_to_bits</a>,
  25210. <a href=\"lib_a_b.htm#bits_to_int\">bits_to_int</a>,
  25211. <a href=\"lib_p_r.htm#peek\">peek</a>,
  25212. <a href=\"lib_p_r.htm#poke\">poke</a>,
  25213. <a href=\"lib_p_r.htm#poke4\">poke4</a>"
  25214.  >
  25215. </table>
  25216.  
  25217.  
  25218. <_routine name="integer">
  25219. <table border=0 cellspacing=2 cellpadding=2>
  25220.  
  25221.  
  25222.  <_2clist
  25223.   name="Syntax:"
  25224.   description="<font face = \"Arial, Helvetica\"> i = integer(x)
  25225. </font>"
  25226.  >
  25227.  <_2clist
  25228.   name="Description:"
  25229.   description=
  25230. "  Return 1 if x is an integer in the range -1073741824 to
  25231.  +1073741823. Otherwise return 0. "
  25232.  >
  25233. <_2clist
  25234.   name="Comments:"
  25235.   description=
  25236. " This serves to define the integer type. You can also call it
  25237.  like an ordinary function to determine if an object is an
  25238.  integer.
  25239.  "
  25240.  >
  25241. <_2clist
  25242.   name="Example 1:"
  25243.   description=""
  25244.  >
  25245. <_eucode>
  25246. integer z
  25247. z = -1
  25248.  
  25249.  </_eucode>
  25250. <_2clist
  25251.   name="Example 2:"
  25252.   description=""
  25253.  >
  25254. <_eucode>
  25255. if integer(y/x) then
  25256.     puts(SCREEN, "y is an exact multiple of x")
  25257. end if
  25258.  
  25259.  </_eucode>
  25260. <_2clist
  25261.   name="See Also:"
  25262.   description="<a href=\"lib_a_b.htm#atom\">atom</a>,
  25263. <a href=\"lib_s_t.htm#sequence\">sequence</a>,
  25264. <a href=\"lib_e_g.htm#floor\">floor</a>"
  25265.  >
  25266. </table>
  25267.  
  25268.  
  25269. <_routine name="length">
  25270. <table border=0 cellspacing=2 cellpadding=2>
  25271.  
  25272.  
  25273.  <_2clist
  25274.   name="Syntax:"
  25275.   description="<font face = \"Arial, Helvetica\"> i = length(s)
  25276. </font>"
  25277.  >
  25278.  <_2clist
  25279.   name="Description:"
  25280.   description=
  25281. "  Return the length of s. s must be a sequence. An error will
  25282.  occur if s is an atom. "
  25283.  >
  25284. <_2clist
  25285.   name="Comments:"
  25286.   description=
  25287. " The length of each sequence is stored internally by the
  25288.  interpreter for quick access. (In other languages this
  25289.  operation requires a search through memory for an end marker.)
  25290.  "
  25291.  >
  25292. <_2clist
  25293.   name="Example 1:"
  25294.   description=""
  25295.  >
  25296. <_eucode>
  25297. length({{1,2}, {3,4}, {5,6}})   -- 3
  25298.  
  25299.  </_eucode>
  25300. <_2clist
  25301.   name="Example 2:"
  25302.   description=""
  25303.  >
  25304. <_eucode>
  25305. length("")    -- 0
  25306.  
  25307.  </_eucode>
  25308. <_2clist
  25309.   name="Example 3:"
  25310.   description=""
  25311.  >
  25312. <_eucode>
  25313. length({})    -- 0
  25314.  
  25315.  </_eucode>
  25316. <_2clist
  25317.   name="See Also:"
  25318.   description="<a href=\"lib_s_t.htm#sequence\">sequence</a>"
  25319.  >
  25320. </table>
  25321.  
  25322.  
  25323. <_routine name="lock_file">
  25324. <table border=0 cellspacing=2 cellpadding=2>
  25325.  
  25326.  
  25327.  <_2clist
  25328.   name="Syntax:"
  25329.   description="<font face = \"Arial, Helvetica\"> include file.e<BR>
  25330.  lock_file(fn, i, s)
  25331. </font>"
  25332.  >
  25333.  <_2clist
  25334.   name="Description:"
  25335.   description="When multiple processes can simultaneously access a
  25336. file, some kind of locking mechanism may be needed to avoid mangling
  25337. the contents of the file, or causing erroneous data to be read from the file.
  25338. <P>lock_file() attempts to place a lock on an open file, fn, to stop 
  25339. other processes from using the file while your program is reading it 
  25340. or writing it. Under Linux, there are two types of locks that 
  25341. you can request using the i parameter. (Under DOS32 and WIN32 the i parameter
  25342. is ignored, but should be an integer.)
  25343. Ask for a <b><i>shared</b></i> lock when you intend to read a file, and you want to 
  25344. temporarily block other processes from writing it. Ask for an 
  25345. <b><i>exclusive</i></b> lock 
  25346. when you intend to write to a file and you want to temporarily block other 
  25347. processes from reading or writing it. It's ok for many processes to 
  25348. simultaneously have shared locks on the same file, but only one process 
  25349. can have an exclusive lock, and that can happen only when no other 
  25350. process has any kind of lock on the file. file.e contains the following
  25351. declaration:"
  25352. >
  25353. <_eucode>
  25354. global constant LOCK_SHARED = 1, 
  25355.         LOCK_EXCLUSIVE = 2
  25356. </_eucode>
  25357.  
  25358. <_2clist
  25359.  name=""
  25360.  description="On DOS32 and WIN32 you can lock a specified 
  25361.  portion of a file using the s parameter. s is a sequence of the 
  25362.  form: {first_byte, last_byte}.
  25363.  It indicates the first byte and last byte in the file,
  25364.  that the lock applies to. Specify the empty sequence {}, 
  25365.  if you want to lock the whole file. In the current release for Linux,
  25366.  locks always apply to the whole file, and you should specify {}
  25367.  for this parameter.
  25368. <p>
  25369. If it is successful in obtaining the desired lock, lock_file() will 
  25370. return 1. If unsuccessful, it will return 0. lock_file() does not wait
  25371. for other processes to relinquish their locks. You may have to call 
  25372. it repeatedly, before the lock request is granted."
  25373.  >
  25374.  
  25375. <_2clist
  25376.   name="Comments:"
  25377.   description="On Linux, these locks are called advisory locks, which
  25378.     means they aren't enforced by the operating system. It is up to the
  25379.     processes that use a particular file to cooperate with each other.
  25380.     A process can access a file without first obtaining a lock on it.
  25381.     On WIN32 and DOS32, locks are enforced by the operating system."
  25382.  >
  25383. <_2clist
  25384.   name=""
  25385.   description="On DOS32, lock_file() is more useful when
  25386.    file sharing is enabled. It will typically return 0 (unsuccessful) 
  25387.    under plain MS-DOS, outside of Windows."
  25388.  >
  25389. <_2clist
  25390.   name="Example:"
  25391.   description=""
  25392.  >
  25393. <_eucode>
  25394. include misc.e
  25395. include file.e
  25396. integer v
  25397. atom t
  25398. v = open("visitor_log", "a")  -- open for append
  25399. t = time()
  25400. while not lock_file(v, LOCK_EXCLUSIVE, {}) do
  25401.     if time() > t + 60 then
  25402.         puts(1, "One minute already ... I can't wait forever!\n")
  25403.         abort(1)
  25404.     end if
  25405.     sleep(5) -- let other processes run
  25406. end while
  25407. puts(v, "Yet another visitor\n")
  25408. unlock_file(v, {})
  25409. close(v)
  25410.  </_eucode>
  25411.  
  25412.  <_2clist
  25413.   name="See Also:"
  25414.   description="<a href=\"lib_u_z.htm#unlock_file\">unlock_file</a>,
  25415. <a href=\"lib_e_g.htm#flush\">flush</a>,
  25416. <a href=\"lib_s_t.htm#sleep\">sleep</a>"
  25417.  >
  25418. </table>
  25419.  
  25420. <_routine name="lock_memory">
  25421. <table border=0 cellspacing=2 cellpadding=2>
  25422.  
  25423.  
  25424.  <_2clist
  25425.   name="Platform:"
  25426.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  25427.  >
  25428.  
  25429.  <_2clist
  25430.   name="Syntax:"
  25431.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  25432.  lock_memory(a, i)
  25433. </font>"
  25434.  >
  25435.  <_2clist
  25436.   name="Description:"
  25437.   description=
  25438. "Prevent the block of virtual memory starting at address a,
  25439.  of length i, from ever being swapped out to disk."
  25440.  >
  25441. <_2clist
  25442.   name="Comments:"
  25443.   description=
  25444. "Use this to ensure that all code and data required for
  25445.  handling interrupts is kept in memory at all times
  25446.  while your program is running."
  25447.  >
  25448. <_2clist
  25449.   name="Example Program:"
  25450.   description="<font color=\"#5500FF\"><b>demo\dos32\hardint.ex</b></font>"
  25451.  >
  25452.  
  25453.  <_2clist
  25454.   name="See Also:"
  25455.   description="<a href=\"lib_e_g.htm#get_vector\">get_vector</a>,
  25456. <a href=\"lib_s_t.htm#set_vector\">set_vector</a>"
  25457.  >
  25458. </table>
  25459.  
  25460.  
  25461. <_routine name="log">
  25462. <table border=0 cellspacing=2 cellpadding=2>
  25463.  
  25464.  
  25465.  <_2clist
  25466.   name="Syntax:"
  25467.   description="<font face = \"Arial, Helvetica\"> x2 = log(x1)
  25468. </font>"
  25469.  >
  25470.  <_2clist
  25471.   name="Description:"
  25472.   description=
  25473. "Return the natural logarithm of x1."
  25474.  >
  25475. <_2clist
  25476.   name="Comments:"
  25477.   description=
  25478. "This function may be applied to an atom or to all elements
  25479.  of a sequence. Note that log is only defined for positive
  25480.  numbers. Your program will abort with a message if you
  25481.  try to take the log of a negative number or zero."
  25482.  >
  25483. <_2clist
  25484.   name="Example:"
  25485.   description=""
  25486.  >
  25487. <_eucode>
  25488. a = log(100)
  25489. -- a is 4.60517
  25490.  
  25491.  </_eucode>
  25492. <_2clist
  25493.   name="See Also:"
  25494.   description="<a href=\"lib_s_t.htm#sin\">sin</a>,
  25495. <a href=\"lib_c_d.htm#cos\">cos</a>,
  25496. <a href=\"lib_s_t.htm#tan\">tan</a>,
  25497. <a href=\"lib_s_t.htm#sqrt\">sqrt</a>"
  25498.  >
  25499. </table>
  25500.  
  25501.  
  25502. <_routine name="lower">
  25503. <table border=0 cellspacing=2 cellpadding=2>
  25504.  
  25505.  
  25506.  <_2clist
  25507.   name="Syntax:"
  25508.   description="<font face = \"Arial, Helvetica\"> include wildcard.e<BR>
  25509.  x2 = lower(x1)
  25510. </font>"
  25511.  >
  25512.  <_2clist
  25513.   name="Description:"
  25514.   description=
  25515. "Convert an atom or sequence to lower case."
  25516.  >
  25517. <_2clist
  25518.   name="Example:"
  25519.   description=""
  25520.  >
  25521. <_eucode>
  25522. s = lower("Euphoria")
  25523. -- s is "euphoria"
  25524.  
  25525. a = lower('B')
  25526. -- a is 'b'
  25527.  
  25528. s = lower({"Euphoria", "Programming"})
  25529. -- s is {"euphoria", "programming"}
  25530.  
  25531.  </_eucode>
  25532. <_2clist
  25533.   name="See Also:"
  25534.   description="<a href=\"lib_u_z.htm#upper\">upper</a>"
  25535.  >
  25536. </table>
  25537.  
  25538.  
  25539. <_routine name="machine_func">
  25540. <table border=0 cellspacing=2 cellpadding=2>
  25541.  
  25542.  
  25543.  <_2clist
  25544.   name="Syntax:"
  25545.   description="<font face = \"Arial, Helvetica\"> x1 = machine_func(a, x)
  25546. </font>"
  25547.  >
  25548.  <_2clist
  25549.   name="Description:"
  25550.   description=
  25551. "see <a href=\"lib_h_o.htm#machine_proc\">machine_proc()</a> below"
  25552.  >
  25553. </table>
  25554.  
  25555.  
  25556. <_routine name="machine_proc">
  25557. <table border=0 cellspacing=2 cellpadding=2>
  25558.  
  25559.  
  25560.  <_2clist
  25561.   name="Syntax:"
  25562.   description="<font face = \"Arial, Helvetica\"> machine_proc(a, x)
  25563. </font>"
  25564.  >
  25565.  <_2clist
  25566.   name="Description:"
  25567.   description=
  25568. "  Perform a machine-specific operation such as graphics and sound
  25569.  effects. This routine should normally be called indirectly via
  25570.  one of the library routines in a Euphoria include file. A direct
  25571.  call might cause a machine exception if done incorrectly. "
  25572.  >
  25573. <_2clist
  25574.   name="See Also:"
  25575.   description="<a href=\"lib_h_o.htm#machine_func\">machine_func</a>"
  25576.  >
  25577. </table>
  25578.  
  25579.  
  25580. <_routine name="match">
  25581. <table border=0 cellspacing=2 cellpadding=2>
  25582.  
  25583.  
  25584.  <_2clist
  25585.   name="Syntax:"
  25586.   description="<font face = \"Arial, Helvetica\"> i = match(s1, s2)
  25587. </font>"
  25588.  >
  25589.  <_2clist
  25590.   name="Description:"
  25591.   description=
  25592. "  Try to match s1 against some slice of s2. If successful, return
  25593.  the element number of s2 where the (first) matching slice begins,
  25594.  else return 0. "
  25595.  >
  25596. <_2clist
  25597.   name="Example:"
  25598.   description=""
  25599.  >
  25600. <_eucode>
  25601. location = match("pho", "Euphoria")
  25602. -- location is set to 3
  25603.  
  25604.  </_eucode>
  25605. <_2clist
  25606.   name="See Also:"
  25607.   description="<a href=\"lib_e_g.htm#find\">find</a>,
  25608. <a href=\"lib_c_d.htm#compare\">compare</a>,
  25609. <a href=\"lib_u_z.htm#wildcard_match\">wildcard_match</a>"
  25610.  >
  25611. </table>
  25612.  
  25613.  
  25614. <_routine name="mem_copy">
  25615. <table border=0 cellspacing=2 cellpadding=2>
  25616.  
  25617.  
  25618.  <_2clist
  25619.   name="Syntax:"
  25620.   description="<font face = \"Arial, Helvetica\"> mem_copy(a1, a2, i)
  25621. </font>"
  25622.  >
  25623.  <_2clist
  25624.   name="Description:"
  25625.   description=
  25626. "  Copy a block of i bytes of memory from address a2 to address a1. "
  25627.  >
  25628. <_2clist
  25629.   name="Comments:"
  25630.   description=
  25631. " The bytes of memory will be copied correctly even if the block
  25632.  of memory at a2 overlaps with the block of memory at a1.
  25633. <P>
  25634. mem_copy(a1, a2, i) is equivalent to: <b>poke(a1, peek({a2, i}))</b>
  25635.  but is much faster."
  25636.  >
  25637. <_2clist
  25638.   name="Example:"
  25639.   description=""
  25640.  >
  25641. <_eucode>
  25642. dest = allocate(50)
  25643. src = allocate(100)
  25644. poke(src, {1,2,3,4,5,6,7,8,9})
  25645. mem_copy(dest, src, 9)
  25646.  
  25647.  </_eucode>
  25648. <_2clist
  25649.   name="See Also:"
  25650.   description="<a href=\"lib_h_o.htm#mem_set\">mem_set</a>,
  25651. <a href=\"lib_p_r.htm#peek\">peek</a>,
  25652. <a href=\"lib_p_r.htm#poke\">poke</a>,
  25653. <a href=\"lib_a_b.htm#allocate\">allocate</a>,
  25654. <a href=\"lib_a_b.htm#allocate_low\">allocate_low</a>"
  25655.  >
  25656. </table>
  25657.  
  25658.  
  25659. <_routine name="mem_set">
  25660. <table border=0 cellspacing=2 cellpadding=2>
  25661.  
  25662.  
  25663.  <_2clist
  25664.   name="Syntax:"
  25665.   description="<font face = \"Arial, Helvetica\"> mem_set(a1, i1, i2)
  25666. </font>"
  25667.  >
  25668.  <_2clist
  25669.   name="Description:"
  25670.   description=
  25671. "Set i2 bytes of memory, starting at address a1, to the value of i1."
  25672.  >
  25673. <_2clist
  25674.   name="Comments:"
  25675.   description=
  25676. "The low order 8 bits of i1 are actually stored in each byte.
  25677. <P>
  25678. mem_set(a1, i1, i2) is equivalent to: <b>poke(a1, repeat(i1, i2))</b>
  25679.  but is much faster."
  25680.  >
  25681. <_2clist
  25682.   name="Example:"
  25683.   description=""
  25684.  >
  25685. <_eucode>
  25686. destination = allocate(1000)
  25687. mem_set(destination, ' ', 1000)
  25688. -- 1000 consecutive bytes in memory will be set to 32 
  25689. -- (the ASCII code for ' ')
  25690.  
  25691.  </_eucode>
  25692. <_2clist
  25693.   name="See Also:"
  25694.   description="<a href=\"lib_h_o.htm#mem_copy\">mem_copy</a>,
  25695. <a href=\"lib_p_r.htm#peek\">peek</a>,
  25696. <a href=\"lib_p_r.htm#poke\">poke</a>,
  25697. <a href=\"lib_a_b.htm#allocate\">allocate</a>,
  25698. <a href=\"lib_a_b.htm#allocate_low\">allocate_low</a>"
  25699.  >
  25700. </table>
  25701.  
  25702.  
  25703. <_routine name="message_box">
  25704. <table border=0 cellspacing=2 cellpadding=2>
  25705.  
  25706.  
  25707.  <_2clist
  25708.   name="Platform:"
  25709.   description="<font color=\"#CC3366\"><b>WIN32</b></font>"
  25710.  >
  25711.  
  25712.  <_2clist
  25713.   name="Syntax:"
  25714.   description="<font face = \"Arial, Helvetica\"> include msgbox.e<BR>
  25715.  i = message_box(s1, s2, x)
  25716. </font>"
  25717.  >
  25718.  <_2clist
  25719.   name="Description:"
  25720.   description=
  25721. "Display a window with title s2, containing the message string s1.
  25722.  x determines the combination of buttons that will be available
  25723.  for the user to press, plus some other characteristics. x can be
  25724.  an atom or a sequence. A return value of 0 indicates a failure to set up
  25725.  the window."
  25726.  >
  25727. <_2clist
  25728.   name="Comments:"
  25729.   description=
  25730. "See <font color=\"#5500FF\"><b>msgbox.e</b></font> for a complete list
  25731.  of possible values for x and i."
  25732.  >
  25733. <_2clist
  25734.   name="Example:"
  25735.   description=""
  25736.  >
  25737. <_eucode>
  25738. response = message_box("Do you wish to proceed?",
  25739.                        "My Application",
  25740.                        MB_YESNOCANCEL)
  25741. if response = IDCANCEL or response = IDNO then
  25742.     abort(1)
  25743. end if
  25744.  
  25745.  </_eucode>
  25746. <_2clist
  25747.   name="Example Program:"
  25748.   description="<font color=\"#5500FF\"><b>demo\win32\email.exw</b></font>"
  25749.  >
  25750.  
  25751. </table>
  25752.  
  25753.  
  25754. <_routine name="mouse_events">
  25755. <table border=0 cellspacing=2 cellpadding=2>
  25756.  
  25757.  
  25758.  <_2clist
  25759.   name="Platform:"
  25760.   description="<font color=\"#CC3366\"><b>DOS32, Linux</b></font>"
  25761.  >
  25762.  
  25763.  <_2clist
  25764.   name="Syntax:"
  25765.   description="<font face = \"Arial, Helvetica\"> include mouse.e<BR>
  25766.  mouse_events(i)
  25767. </font>"
  25768.  >
  25769.  <_2clist
  25770.   name="Description:"
  25771.   description=
  25772. "Use this procedure to select the mouse events that you want
  25773.  get_mouse() to report. By default, get_mouse() will report all
  25774.  events. mouse_events() can be called at various stages of the
  25775.  execution of your program, as the need to detect events changes.
  25776.  Under Linux, mouse_events() currently has no effect."
  25777.  >
  25778. <_2clist
  25779.   name="Comments:"
  25780.   description=
  25781. "It is good practice to ignore events that you are not interested
  25782.  in, particularly the very frequent MOVE event, in order to reduce
  25783.  the chance that you will miss a significant event.
  25784. <P>
  25785. The first call that you make to mouse_events() will turn on a
  25786.  mouse pointer, or a highlighted character."
  25787.  >
  25788. <_2clist
  25789.   name="Example:"
  25790.   description=""
  25791.  >
  25792. <_eucode>
  25793. mouse_events(LEFT_DOWN + LEFT_UP + RIGHT_DOWN)
  25794. -- will restrict get_mouse() to reporting the left button
  25795. -- being pressed down or released, and the right button
  25796. -- being pressed down. All other events will be ignored.
  25797.  
  25798.  </_eucode>
  25799. <_2clist
  25800.   name="See Also:"
  25801.   description="<a href=\"lib_e_g.htm#get_mouse\">get_mouse</a>,
  25802. <a href=\"lib_h_o.htm#mouse_pointer\">mouse_pointer</a>"
  25803.  >
  25804. </table>
  25805.  
  25806.  
  25807. <_routine name="mouse_pointer">
  25808. <table border=0 cellspacing=2 cellpadding=2>
  25809.  
  25810.  
  25811.  <_2clist
  25812.   name="Platform:"
  25813.   description="<font color=\"#CC3366\"><b>DOS32, Linux</b></font>"
  25814.  >
  25815.  
  25816.  <_2clist
  25817.   name="Syntax:"
  25818.   description="<font face = \"Arial, Helvetica\"> include mouse.e<BR>
  25819.  mouse_pointer(i)
  25820. </font>"
  25821.  >
  25822.  <_2clist
  25823.   name="Description:"
  25824.   description=
  25825. "If i is 0 hide the mouse pointer, otherwise turn on the mouse
  25826.  pointer. Multiple calls to hide the pointer will require
  25827.  multiple calls to turn it back on. The first call to either
  25828.  get_mouse() or mouse_events(), will also turn the pointer
  25829.  on (once). Under Linux, mouse_pointer() currently has no effect" 
  25830.  >
  25831. <_2clist
  25832.   name="Comments:"
  25833.   description=
  25834. "It may be necessary to hide the mouse pointer temporarily when
  25835.  you update the screen.
  25836. <P>
  25837. After a call to <a href=\"lib_s_t.htm#text_rows\">text_rows()</a> you may
  25838.  have to call mouse_pointer(1) to see the mouse pointer again."
  25839.  >
  25840. <_2clist
  25841.   name="See Also:"
  25842.   description="<a href=\"lib_e_g.htm#get_mouse\">get_mouse</a>,
  25843. <a href=\"lib_h_o.htm#mouse_events\">mouse_events</a>"
  25844.  >
  25845. </table>
  25846.  
  25847.  
  25848. <_routine name="not_bits">
  25849. <table border=0 cellspacing=2 cellpadding=2>
  25850.  
  25851.  
  25852.  <_2clist
  25853.   name="Syntax:"
  25854.   description="<font face = \"Arial, Helvetica\"> x2 = not_bits(x1)
  25855. </font>"
  25856.  >
  25857.  <_2clist
  25858.   name="Description:"
  25859.   description=
  25860. "Perform the logical NOT operation on each bit in x1.
  25861.  A bit in x2 will be 1 when the corresponding bit in x1
  25862.  is 0, and will be 0 when the corresponding bit in x1 is 1."
  25863.  >
  25864. <_2clist
  25865.   name="Comments:"
  25866.   description=
  25867. "The argument to this function may be an atom or a sequence.
  25868.  The rules for <a href=\"refman_2.htm#26\">operations on sequences</a> apply.
  25869. <P>
  25870. The argument must be representable as a 32-bit number,
  25871.  either signed or unsigned.
  25872. <P>
  25873. If you intend to manipulate full 32-bit values, you should
  25874.  declare your variables as <font color=\"#993333\"><b>atom</b></font>,
  25875.  rather than integer. Euphoria's integer type is limited to 31-bits.
  25876. <P>
  25877. Results are treated as signed numbers. They will be
  25878.  negative when the highest-order bit is 1."
  25879.  >
  25880. <_2clist
  25881.   name="Example:"
  25882.   description=""
  25883.  >
  25884. <_eucode>
  25885. a = not_bits(#000000F7)
  25886. -- a is -248 (i.e. FFFFFF08 interpreted as a negative number)
  25887.  
  25888.  </_eucode>
  25889. <_2clist
  25890.   name="See Also:"
  25891.   description="<a href=\"lib_a_b.htm#and_bits\">and_bits</a>,
  25892. <a href=\"lib_h_o.htm#or_bits\">or_bits</a>,
  25893. <a href=\"lib_u_z.htm#xor_bits\">xor_bits</a>,
  25894. <a href=\"lib_h_o.htm#int_to_bits\">int_to_bits</a>"
  25895.  >
  25896. </table>
  25897.  
  25898.  
  25899. <_routine name="object">
  25900. <table border=0 cellspacing=2 cellpadding=2>
  25901.  
  25902.  
  25903.  <_2clist
  25904.   name="Syntax:"
  25905.   description="<font face = \"Arial, Helvetica\"> i = object(x)
  25906. </font>"
  25907.  >
  25908.  <_2clist
  25909.   name="Description:"
  25910.   description=
  25911. "Test if x is of type object. This will always be true, so
  25912.  object() will always return 1."
  25913.  >
  25914. <_2clist
  25915.   name="Comments:"
  25916.   description=
  25917. "All <a href=\"refman_2.htm#43\">predefined</a> and
  25918.  <a href=\"refman_2.htm#type\">user-defined types</a> can also be used as
  25919.  functions to test if a value belongs to the type. object()
  25920.  is included just for completeness. It always returns 1."
  25921.  >
  25922. <_2clist
  25923.   name="Example:"
  25924.   description=""
  25925.  >
  25926. <_eucode>
  25927. ? object({1,2,3})  -- always prints 1
  25928.  
  25929.  </_eucode>
  25930. <_2clist
  25931.   name="See Also:"
  25932.   description="<a href=\"lib_h_o.htm#integer\">integer</a>,
  25933. <a href=\"lib_a_b.htm#atom\">atom</a>,
  25934. <a href=\"lib_s_t.htm#sequence\">sequence</a>"
  25935.  >
  25936. </table>
  25937.  
  25938.  
  25939. <_routine name="open">
  25940. <table border=0 cellspacing=2 cellpadding=2>
  25941.  
  25942.  
  25943.  <_2clist
  25944.   name="Syntax:"
  25945.   description="<font face = \"Arial, Helvetica\"> fn = open(st1, st2)
  25946. </font>"
  25947.  >
  25948.  <_2clist
  25949.   name="Description:"
  25950.   description=
  25951. "Open a file or device, to get the file number. -1 is returned if
  25952.  the open fails. st1 is the path name of the file or device. st2 is
  25953.  the mode in which the file is to be opened. Possible modes are:<P>
  25954. \"r\" - open text file for reading<BR>
  25955.  \"rb\" - open binary file for reading<BR>
  25956.  \"w\" - create text file for writing<BR>
  25957.  \"wb\" - create binary file for writing<BR>
  25958.  \"u\" - open text file for update (reading and writing)<BR>
  25959.  \"ub\" - open binary file for update<BR>
  25960.  \"a\" - open text file for appending<BR>
  25961.  \"ab\" - open binary file for appending<BR>
  25962. <P>
  25963. Files opened for read or update must already exist. Files opened
  25964.  for write or append will be created if necessary. A file opened
  25965.  for write will be set to 0 bytes. Output to a file opened for
  25966.  append will start at the end of file.
  25967. <P>
  25968. Output to <b>text files</b> will have carriage-return characters
  25969.  automatically added before linefeed characters. On input, these
  25970.  carriage-return characters are removed. A control-Z character
  25971.  (ASCII 26) will signal an immediate end of file.
  25972. <P>
  25973. I/O to <b>binary files</b> is not modified in any way. Any byte values
  25974.  from 0 to 255 can be read or written.
  25975. <P>
  25976. Some typical devices that you can open are:
  25977. <P>
  25978. \"CON\" - the console (screen)<BR>
  25979.  \"AUX\" - the serial auxiliary port<BR>
  25980.  \"COM1\" - serial port 1<BR>
  25981.  \"COM2\" - serial port 2<BR>
  25982.  \"PRN\" - the printer on the parallel port<BR>
  25983.  \"NUL\" - a non-existent device that accepts and discards output<BR>
  25984.  "
  25985.  >
  25986. <_2clist
  25987.   name="Comments:"
  25988.   description=
  25989. "<font color=\"#CC3366\"><b>DOS32:</b></font>
  25990.  When running under Windows 95/98, you can open any existing file
  25991.  that has a long file or directory name in its path (i.e. greater
  25992.  than the standard DOS 8.3 format) using any open mode - read,
  25993.  write etc. However, if you try to create a <b><i>new</i></b> file (open with
  25994.  \"w\" or \"a\" and the file does not already exist) then the name
  25995.  will be truncated if necessary to an 8.3 style name. We hope to
  25996.  support creation of new long-filename files in a future release.
  25997.  <p>
  25998.  <font color=\"#CC3366\"><b>WIN32, Linux:</b></font>
  25999.  Long filenames are fully supported for reading and writing and creating."
  26000.  >
  26001. <_2clist
  26002.   name="Example:"
  26003.   description=""
  26004.  >
  26005. <_eucode>
  26006. integer file_num, file_num95
  26007. sequence first_line
  26008. constant ERROR = 2
  26009.  
  26010. file_num = open("myfile", "r")
  26011. if file_num = -1 then
  26012.     puts(ERROR, "couldn't open myfile\n")
  26013. else
  26014.     first_line = gets(file_num)
  26015. end if
  26016.  
  26017. file_num = open("PRN", "w") -- open printer for output
  26018.  
  26019. -- on Windows 95:
  26020. file_num95 = open("bigdirectoryname\\verylongfilename.abcdefg",
  26021.                   "r")
  26022. if file_num95 != -1 then
  26023.     puts(1, "it worked!\n")
  26024. end if
  26025.  
  26026.  </_eucode>
  26027. <_2clist
  26028.   name="See Also:"
  26029.   description="<a href=\"lib_c_d.htm#close\">close</a>"
  26030.  >
  26031. </table>
  26032.  
  26033.  
  26034. <_routine name="open_dll">
  26035. <table border=0 cellspacing=2 cellpadding=2>
  26036.  
  26037.  
  26038.  <_2clist
  26039.   name="Platform:"
  26040.   description="<font color=\"#CC3366\"><b>WIN32, Linux</b></font>"
  26041.  >
  26042.  
  26043.  <_2clist
  26044.   name="Syntax:"
  26045.   description="<font face = \"Arial, Helvetica\"> include dll.e<BR>
  26046.  a = open_dll(st)
  26047. </font>"
  26048.  >
  26049.  <_2clist
  26050.   name="Description:"
  26051.   description=
  26052. "Open a Windows dynamic link library (<b>.</b>dll) file, or a Linux
  26053. shared library (<b>.</b>so) file. A 32-bit address will
  26054.  be returned, or 0 if the <b>.</b>dll can't be found. st can be a relative
  26055.  or an absolute file name. Windows will use the normal search
  26056.  path for locating <b>.</b>dll files."
  26057.  >
  26058. <_2clist
  26059.   name="Comments:"
  26060.   description=
  26061. "The value returned by open_dll() can be passed to define_c_proc(),
  26062.  define_c_func(), or define_c_var().
  26063. <P>
  26064. You can open the same <b>.</b>dll or <b>.</b>so file multiple times.
  26065.  No extra memory is used and you'll get the same number returned
  26066.  each time."
  26067.  >
  26068. <_2clist
  26069.   name="Example:"
  26070.   description=""
  26071.  >
  26072. <_eucode>
  26073. atom user32
  26074. user32 = open_dll("user32.dll")
  26075. if user32 = 0 then
  26076.     puts(1, "Couldn't open user32.dll!\n")
  26077. end if
  26078.  
  26079.  </_eucode>
  26080. <_2clist
  26081.   name="See Also:"
  26082.   description="<a href=\"lib_c_d.htm#define_c_func\">define_c_func</a>,
  26083. <a href=\"lib_c_d.htm#define_c_proc\">define_c_proc</a>,
  26084. <a href=\"lib_c_d.htm#define_c_var\">define_c_var</a>,
  26085. <a href=\"lib_c_d.htm#c_func\">c_func</a>,
  26086. <a href=\"lib_c_d.htm#c_proc\">c_proc</a>,
  26087. <a href=\"platform.htm#call_cfunc\"><font color=\"#5500FF\"><b>platform.doc</b>
  26088. </font></a>"
  26089.  >
  26090. </table>
  26091.  
  26092.  
  26093. <_routine name="or_bits">
  26094. <table border=0 cellspacing=2 cellpadding=2>
  26095.  
  26096.  
  26097.  <_2clist
  26098.   name="Syntax:"
  26099.   description="<font face = \"Arial, Helvetica\"> x3 = or_bits(x1, x2)
  26100. </font>"
  26101.  >
  26102.  <_2clist
  26103.   name="Description:"
  26104.   description=
  26105. "Perform the logical OR operation on corresponding bits in
  26106.  x1 and x2. A bit in x3 will be 1 when a corresponding
  26107.  bit in either x1 or x2 is 1."
  26108.  >
  26109. <_2clist
  26110.   name="Comments:"
  26111.   description=
  26112. "The arguments to this function may be atoms or sequences. The
  26113.  rules for <a href=\"refman_2.htm#26\">operations on sequences</a> apply.
  26114. <P>
  26115. The arguments must be representable as 32-bit numbers,
  26116.  either signed or unsigned.
  26117. <P>
  26118. If you intend to manipulate full 32-bit values, you should declare your
  26119.  variables as <font color=\"#993333\"><b>atom</b></font>, rather than
  26120.  integer. Euphoria's integer type is limited to 31-bits.
  26121. <P>
  26122. Results are treated as signed numbers. They will be
  26123.  negative when the highest-order bit is 1."
  26124.  >
  26125. <_2clist
  26126.   name="Example 1:"
  26127.   description=""
  26128.  >
  26129. <_eucode>
  26130. a = or_bits(#0F0F0000, #12345678)
  26131. -- a is #1F3F5678
  26132.  
  26133.  </_eucode>
  26134. <_2clist
  26135.   name="Example 2:"
  26136.   description=""
  26137.  >
  26138. <_eucode>
  26139. a = or_bits(#FF, {#123456, #876543, #2211})
  26140. -- a is {#1234FF, #8765FF, #22FF}
  26141.  
  26142.  </_eucode>
  26143. <_2clist
  26144.   name="See Also:"
  26145.   description="<a href=\"lib_a_b.htm#and_bits\">and_bits</a>,
  26146. <a href=\"lib_u_z.htm#xor_bits\">xor_bits</a>,
  26147. <a href=\"lib_h_o.htm#not_bits\">not_bits</a>,
  26148. <a href=\"lib_h_o.htm#int_to_bits\">int_to_bits</a>"
  26149.  >
  26150. </table>
  26151.  
  26152. <_continue
  26153.   href="lib_p_r.htm"
  26154.   name="From P to R"
  26155. >
  26156.  
  26157. </body>
  26158. </html>
  26159. LIB_P_R.HTX
  26160. 40932
  26161. <_init_comment>
  26162. <html>
  26163. <head><title>Euphoria v2.2 Reference Manual Part II - Section 3</title>
  26164. </head>
  26165. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  26166. <br>
  26167.  
  26168.  
  26169. <_routine name="palette">
  26170. <table border=0 cellspacing=2 cellpadding=2>
  26171.  
  26172.  
  26173.  <_2clist
  26174.   name="Platform:"
  26175.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  26176.  >
  26177.  
  26178.  <_2clist
  26179.   name="Syntax:"
  26180.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  26181.  x = palette(i, s)
  26182. </font>"
  26183.  >
  26184.  <_2clist
  26185.   name="Description:"
  26186.   description=
  26187. "  Change the color for color number i to s, where s is a sequence
  26188.  of color intensities: {red, green, blue}. Each value in s can be
  26189.  from 0 to 63. If successful, a 3-element sequence containing the
  26190.  previous color for i will be returned, and all pixels on the
  26191.  screen with value i will be set to the new color. If
  26192.  unsuccessful, the atom -1 will be returned. "
  26193.  >
  26194. <_2clist
  26195.   name="Example:"
  26196.   description=""
  26197.  >
  26198. <_eucode>
  26199. x = palette(0, {15, 40, 10})
  26200. -- color number 0 (normally black) is changed to a shade
  26201. -- of mainly green.
  26202.  
  26203.  </_eucode>
  26204. <_2clist
  26205.   name="See Also:"
  26206.   description="<a href=\"lib_a_b.htm#all_palette\">all_palette</a>"
  26207.  >
  26208. </table>
  26209.  
  26210.  
  26211. <_routine name="peek">
  26212. <table border=0 cellspacing=2 cellpadding=2>
  26213.  
  26214.  
  26215.  <_2clist
  26216.   name="Syntax:"
  26217.   description="<font face = \"Arial, Helvetica\"> i = peek(a)<BR>
  26218.  or ...<BR>
  26219.   s = peek({a, i})
  26220. </font>"
  26221.  >
  26222.  <_2clist
  26223.   name="Description:"
  26224.   description=
  26225. "Return a single byte value in the range 0 to 255 from machine
  26226.  address a, or return a sequence containing i consecutive byte
  26227.  values starting at address a in memory."
  26228.  >
  26229. <_2clist
  26230.   name="Comments:"
  26231.   description=
  26232. "Since addresses are 32-bit numbers, they can be larger than the largest
  26233.  value of type integer (31-bits). Variables that hold an address should
  26234.  therefore be declared as <font color=\"#993333\"><b>atoms</b></font>.
  26235. <P>
  26236. It is faster to read several bytes at once using the second
  26237.  form of peek() than it is to read one byte at a time in a loop.
  26238. <P>
  26239. Remember that peek takes just one argument, which in the
  26240.  second form is actually a 2-element sequence."
  26241.  >
  26242. <_2clist
  26243.   name="Example:"
  26244.   description=" The following are equivalent:"
  26245.  >
  26246. <_eucode>
  26247.  
  26248. -- method 1
  26249. s = {peek(100), peek(101), peek(102), peek(103)}
  26250.  
  26251. -- method 2
  26252. s = peek({100, 4})
  26253.  
  26254.  </_eucode>
  26255. <_2clist
  26256.   name="See Also:"
  26257.   description="<a href=\"lib_p_r.htm#poke\">poke</a>,
  26258. <a href=\"lib_p_r.htm#peek4s\">peek4s</a>,
  26259. <a href=\"lib_p_r.htm#peek4u\">peek4u</a>,
  26260. <a href=\"lib_a_b.htm#allocate\">allocate</a>,
  26261. <a href=\"lib_e_g.htm#free\">free</a>,
  26262. <a href=\"lib_a_b.htm#allocate_low\">allocate_low</a>,
  26263. <a href=\"lib_e_g.htm#free_low\">free_low</a>,
  26264. <a href=\"lib_c_d.htm#call\">call</a>"
  26265.  >
  26266. </table>
  26267.  
  26268.  
  26269. <_routine name="peek4s">
  26270. <table border=0 cellspacing=2 cellpadding=2>
  26271.  
  26272.  
  26273.  <_2clist
  26274.   name="Syntax:"
  26275.   description="<font face = \"Arial, Helvetica\"> a2 = peek4s(a1)<BR>
  26276.  or ...<BR>
  26277.   s = peek4s({a1, i})
  26278. </font>"
  26279.  >
  26280.  <_2clist
  26281.   name="Description:"
  26282.   description=
  26283. "Return a 4-byte (32-bit) signed value in the range -2147483648 to
  26284.  +2147483647 from machine address a1, or return a sequence
  26285.  containing i consecutive 4-byte signed values starting at
  26286.  address a1 in memory."
  26287.  >
  26288. <_2clist
  26289.   name="Comments:"
  26290.   description=
  26291. "The 32-bit values returned by peek4s() may be too large for the Euphoria
  26292.  integer type (31-bits), so you should use
  26293.  <font color=\"#993333\"><b>atom</b></font> variables.
  26294. <P>
  26295. Since machine addresses are 32-bit numbers, they can also be too large for
  26296.  Euphoria's integer type. Variables that hold an address should therefore
  26297.  be declared as <font color=\"#993333\"><b>atoms</b></font>.
  26298. <P>
  26299. It is faster to read several 4-byte values at once using the
  26300.  second form of peek4s() than it is to read one 4-byte value at
  26301.  a time in a loop.
  26302. <P>
  26303. Remember that peek4s() takes just one argument, which in the
  26304.  second form is actually a 2-element sequence."
  26305.  >
  26306. <_2clist
  26307.   name="Example:"
  26308.   description=" The following are equivalent:"
  26309.  >
  26310. <_eucode>
  26311.  
  26312. -- method 1
  26313. s = {peek4s(100), peek4s(104), peek4s(108), peek4s(112)}
  26314.  
  26315. -- method 2
  26316. s = peek4s({100, 4})
  26317.  
  26318.  </_eucode>
  26319. <_2clist
  26320.   name="See Also:"
  26321.   description="<a href=\"lib_p_r.htm#peek4u\">peek4u</a>,
  26322. <a href=\"lib_p_r.htm#peek\">peek</a>,
  26323. <a href=\"lib_p_r.htm#poke4\">poke4</a>,
  26324. <a href=\"lib_a_b.htm#allocate\">allocate</a>,
  26325. <a href=\"lib_e_g.htm#free\">free</a>,
  26326. <a href=\"lib_a_b.htm#allocate_low\">allocate_low</a>,
  26327. <a href=\"lib_e_g.htm#free_low\">free_low</a>,
  26328. <a href=\"lib_c_d.htm#call\">call</a>"
  26329.  >
  26330. </table>
  26331.  
  26332.  
  26333. <_routine name="peek4u">
  26334. <table border=0 cellspacing=2 cellpadding=2>
  26335.  
  26336.  
  26337.  <_2clist
  26338.   name="Syntax:"
  26339.   description="<font face = \"Arial, Helvetica\"> a2 = peek4u(a1)<BR>
  26340.  or ...<BR>
  26341.   s = peek4u({a1, i})
  26342. </font>"
  26343.  >
  26344.  <_2clist
  26345.   name="Description:"
  26346.   description=
  26347. "Return a 4-byte (32-bit) unsigned value in the range 0 to
  26348.  4294967295 from machine address a1, or return a sequence
  26349.  containing i consecutive 4-byte unsigned values starting at
  26350.  address a1 in memory."
  26351.  >
  26352. <_2clist
  26353.   name="Comments:"
  26354.   description=
  26355. "The 32-bit values returned by peek4u() may be too large for the Euphoria
  26356.  integer type (31-bits), so you should use
  26357.  <font color=\"#993333\"><b>atom</b></font> variables.
  26358. <P>
  26359. Since machine addresses are 32-bit numbers, they can also be too large for
  26360.  Euphoria's integer type. Variables that hold an address should therefore
  26361.  be declared as <font color=\"#993333\"><b>atoms</b></font>.
  26362. <P>
  26363. It is faster to read several 4-byte values at once using the
  26364.  second form of peek4u() than it is to read one 4-byte value at
  26365.  a time in a loop.
  26366. <P>
  26367. Remember that peek4u() takes just one argument, which in the
  26368.  second form is actually a 2-element sequence."
  26369.  >
  26370. <_2clist
  26371.   name="Example:"
  26372.   description=" The following are equivalent:"
  26373.  >
  26374. <_eucode>
  26375.  
  26376. -- method 1
  26377. s = {peek4u(100), peek4u(104), peek4u(108), peek4u(112)}
  26378.  
  26379. -- method 2
  26380. s = peek4u({100, 4})
  26381.  
  26382.  </_eucode>
  26383. <_2clist
  26384.   name="See Also:"
  26385.   description="<a href=\"lib_p_r.htm#peek4s\">peek4s</a>,
  26386. <a href=\"lib_p_r.htm#peek\">peek</a>,
  26387. <a href=\"lib_p_r.htm#poke4\">poke4</a>,
  26388. <a href=\"lib_a_b.htm#allocate\">allocate</a>,
  26389. <a href=\"lib_e_g.htm#free\">free</a>,
  26390. <a href=\"lib_a_b.htm#allocate_low\">allocate_low</a>,
  26391. <a href=\"lib_e_g.htm#free_low\">free_low</a>,
  26392. <a href=\"lib_c_d.htm#call\">call</a>"
  26393.  >
  26394. </table>
  26395.  
  26396.  
  26397. <_routine name="PI">
  26398. <table border=0 cellspacing=2 cellpadding=2>
  26399.  
  26400.  
  26401.  <_2clist
  26402.   name="Syntax:"
  26403.   description="<font face = \"Arial, Helvetica\"> include misc.e<BR>
  26404.  PI
  26405. </font>"
  26406.  >
  26407.  <_2clist
  26408.   name="Description:"
  26409.   description=
  26410. "PI (3.14159...) has been defined as a global constant."
  26411.  >
  26412. <_2clist
  26413.   name="Comments:"
  26414.   description=
  26415. "Enough digits have been used to attain the maximum accuracy
  26416.  possible for a Euphoria atom."
  26417.  >
  26418. <_2clist
  26419.   name="Example:"
  26420.   description=""
  26421.  >
  26422. <_eucode>
  26423. x = PI  -- x is 3.14159...
  26424.  
  26425.  </_eucode>
  26426. <_2clist
  26427.   name="See Also:"
  26428.   description="<a href=\"lib_s_t.htm#sin\">sin</a>,
  26429. <a href=\"lib_c_d.htm#cos\">cos</a>,
  26430. <a href=\"lib_s_t.htm#tan\">tan</a>"
  26431.  >
  26432. </table>
  26433.  
  26434.  
  26435. <_routine name="pixel">
  26436. <table border=0 cellspacing=2 cellpadding=2>
  26437.  
  26438.  
  26439.  <_2clist
  26440.   name="Platform:"
  26441.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  26442.  >
  26443.  
  26444.  <_2clist
  26445.   name="Syntax:"
  26446.   description="<font face = \"Arial, Helvetica\"> pixel(x1, s)
  26447. </font>"
  26448.  >
  26449.  <_2clist
  26450.   name="Description:"
  26451.   description=
  26452. "Set one or more pixels on a <font color=\"#CC3366\">pixel-graphics</font>
  26453.  screen starting at point s, where s is a 2-element screen coordinate {x, y}.
  26454.  If x1 is an atom, one pixel will be set to the color indicated by x1.
  26455.  If x1 is a sequence then a number of pixels will be set, starting
  26456.  at s and moving to the right (increasing x value, same y value)."
  26457.  >
  26458. <_2clist
  26459.   name="Comments:"
  26460.   description=
  26461. "When x1 is a sequence, a very fast algorithm is used to put the
  26462.  pixels on the screen. It is much faster to call pixel() once,
  26463.  with a sequence of pixel colors, than it is to call it many
  26464.  times, plotting one pixel color at a time.
  26465. <P>
  26466. In graphics mode 19, pixel() is highly optimized."
  26467.  >
  26468. <_2clist
  26469.   name="Example 1:"
  26470.   description=""
  26471.  >
  26472. <_eucode>
  26473. pixel(BLUE, {50, 60})
  26474. -- the point {50,60} is set to the color BLUE
  26475.  
  26476.  </_eucode>
  26477. <_2clist
  26478.   name="Example 2:"
  26479.   description=""
  26480.  >
  26481. <_eucode>
  26482. pixel({BLUE, GREEN, WHITE, RED}, {50,60})
  26483. -- {50,60} set to BLUE
  26484. -- {51,60} set to GREEN
  26485. -- {52,60} set to WHITE
  26486. -- {53,60} set to RED
  26487.  
  26488.  </_eucode>
  26489. <_2clist
  26490.   name="See Also:"
  26491.   description="<a href=\"lib_e_g.htm#get_pixel\">get_pixel</a>,
  26492. <a href=\"lib_e_g.htm#graphics_mode\">graphics_mode</a>"
  26493.  >
  26494. </table>
  26495.  
  26496.  
  26497. <_routine name="platform">
  26498. <table border=0 cellspacing=2 cellpadding=2>
  26499.  
  26500.  
  26501.  <_2clist
  26502.   name="Syntax:"
  26503.   description="<font face = \"Arial, Helvetica\">
  26504.  i = platform()
  26505. </font>"
  26506.  >
  26507.  <_2clist
  26508.   name="Description:"
  26509.   description=
  26510. "platform() is a function built-in to the interpreter. It indicates
  26511.  the platform that the program is being executed on:
  26512.  <font color=\"#CC3366\"><b>DOS32</b></font>,
  26513.  <font color=\"#CC3366\"><b>WIN32</b></font> or
  26514.  <font color=\"#CC3366\"><b>Linux</b></font>."
  26515.  >
  26516. <_2clist
  26517.   name="Comments:"
  26518.   description=
  26519. "When <font color=\"#993333\"><b>ex.exe</b></font> is running, the platform
  26520.  is DOS32. When <font color=\"#993333\"><b>exw.exe</b></font>
  26521.  is running the platform is WIN32. When 
  26522.  <font color=\"#993333\"><b>exu</b></font> is running the platform is LINUX
  26523. <P>
  26524. The include file <font color=\"#5500FF\"><b>misc.e</b></font> contains the
  26525.  following constants:"
  26526.  >
  26527. <_eucode>
  26528.     global constant DOS32 = 1,
  26529.                     WIN32 = 2,
  26530.                     LINUX = 3
  26531. </_eucode>
  26532. <_2clist
  26533.   name=""
  26534.   description=
  26535. "Use platform() when you want to execute different code depending
  26536.  on which platform the program is running on.
  26537.  
  26538. <P>
  26539.  Additional platforms will be added as Euphoria is ported to new
  26540.  machines and operating environments.
  26541.  
  26542. <P>
  26543.  The call to platform() costs nothing. It is optimized
  26544.  at compile-time into the appropriate integer value: 1, 2 or 3."
  26545.  
  26546.  >
  26547.  
  26548. <_2clist
  26549.   name="Example 1:"
  26550.   description=""
  26551.  >
  26552. <_eucode>
  26553. if platform() = WIN32 then
  26554.     -- call system Beep routine
  26555.     err = c_func(Beep, {0,0})
  26556. elsif platform() = DOS32 then
  26557.     -- make beep
  26558.     sound(500)
  26559.     t = time()
  26560.     while time() < t + 0.5 do
  26561.     end while
  26562.     sound(0)
  26563. else
  26564.     -- do nothing (Linux)
  26565. end if
  26566.  
  26567.  </_eucode>
  26568.  
  26569. <_2clist
  26570.   name="See Also:"
  26571.   description="
  26572.  <a href=\"platform.htm\"><font color=\"#5500FF\"><b>platform.doc</b>
  26573.  </font></a>"
  26574. >
  26575. </table>
  26576.  
  26577.  
  26578. <_routine name="poke">
  26579. <table border=0 cellspacing=2 cellpadding=2>
  26580.  
  26581.  
  26582.  <_2clist
  26583.   name="Syntax:"
  26584.   description="<font face = \"Arial, Helvetica\"> poke(a, x)
  26585. </font>"
  26586.  >
  26587.  <_2clist
  26588.   name="Description:"
  26589.   description=
  26590. "If x is an atom, write a single byte value to memory address a.<P>
  26591. If x is a sequence, write a sequence of byte values to
  26592.  consecutive memory locations starting at location a."
  26593.  >
  26594. <_2clist
  26595.   name="Comments:"
  26596.   description=
  26597. "The lower 8-bits of each byte value, i.e. <b>remainder(x, 256)</b>,
  26598.  is actually stored in memory.
  26599. <P>
  26600. It is faster to write several bytes at once by poking a sequence
  26601.  of values, than it is to write one byte at a time in a loop.
  26602. <P>
  26603. Writing to the screen memory with poke() can be much faster than using
  26604.  <a href=\"lib_p_r.htm#puts\">puts()</a> or
  26605.  <a href=\"lib_p_r.htm#printf\">printf()</a>, but the programming is more
  26606.  difficult. In most cases the speed is not needed. For example, the Euphoria
  26607.  editor, <font color=\"#993333\"><b>ed</b></font>, never uses poke()."
  26608.  >
  26609. <_2clist
  26610.   name="Example:"
  26611.   description=""
  26612.  >
  26613. <_eucode>
  26614. a = allocate(100)   -- allocate 100 bytes in memory
  26615.  
  26616. -- poke one byte at a time:
  26617. poke(a, 97)
  26618. poke(a+1, 98)
  26619. poke(a+2, 99)
  26620.  
  26621. -- poke 3 bytes at once:
  26622. poke(a, {97, 98, 99})
  26623.  
  26624.  </_eucode>
  26625. <_2clist
  26626.   name="Example Program:"
  26627.   description="<font color=\"#5500FF\"><b>demo\dos32\callmach.ex</b></font>"
  26628.  >
  26629.  
  26630.  <_2clist
  26631.   name="See Also:"
  26632.   description="<a href=\"lib_p_r.htm#peek\">peek</a>,
  26633. <a href=\"lib_p_r.htm#poke4\">poke4</a>,
  26634. <a href=\"lib_a_b.htm#allocate\">allocate</a>,
  26635. <a href=\"lib_e_g.htm#free\">free</a>,
  26636. <a href=\"lib_a_b.htm#allocate_low\">allocate_low</a>,
  26637. <a href=\"lib_e_g.htm#free_low\">free_low</a>,
  26638. <a href=\"lib_c_d.htm#call\">call</a>,
  26639. <a href=\"library.htm#safe\"><font color=\"#5500FF\"><b>safe.e</b></font></a>"
  26640.  >
  26641. </table>
  26642.  
  26643.  
  26644. <_routine name="poke4">
  26645. <table border=0 cellspacing=2 cellpadding=2>
  26646.  
  26647.  
  26648.  <_2clist
  26649.   name="Syntax:"
  26650.   description="<font face = \"Arial, Helvetica\"> poke4(a, x)
  26651. </font>"
  26652.  >
  26653.  <_2clist
  26654.   name="Description:"
  26655.   description=
  26656. "If x is an atom, write a 4-byte (32-bit) value to memory
  26657.  address a.<P>
  26658. If x is a sequence, write a sequence of 4-byte values to
  26659.  consecutive memory locations starting at location a."
  26660.  >
  26661. <_2clist
  26662.   name="Comments:"
  26663.   description=
  26664. "The value or values to be stored must not exceed 32-bits in size.
  26665. <P>
  26666. It is faster to write several 4-byte values at once by poking
  26667.  a sequence of values, than it is to write one 4-byte value at a
  26668.  time in a loop.
  26669. <P>
  26670. The 4-byte values to be stored can be negative or positive.
  26671.  You can read them back with either peek4s() or peek4u()."
  26672.  >
  26673. <_2clist
  26674.   name="Example:"
  26675.   description=""
  26676.  >
  26677. <_eucode>
  26678. a = allocate(100)   -- allocate 100 bytes in memory
  26679.  
  26680. -- poke one 4-byte value at a time:
  26681. poke4(a, 9712345)
  26682. poke4(a+4, #FF00FF00)
  26683. poke4(a+8, -12345)
  26684.  
  26685. -- poke 3 4-byte values at once:
  26686. poke4(a, {9712345, #FF00FF00, -12345})
  26687.  
  26688.  </_eucode>
  26689. <_2clist
  26690.   name="See Also:"
  26691.   description="<a href=\"lib_p_r.htm#peek4u\">peek4u</a>,
  26692. <a href=\"lib_p_r.htm#peek4s\">peek4s</a>,
  26693. <a href=\"lib_p_r.htm#poke\">poke</a>,
  26694. <a href=\"lib_a_b.htm#allocate\">allocate</a>,
  26695. <a href=\"lib_a_b.htm#allocate_low\">allocate_low</a>,
  26696. <a href=\"lib_c_d.htm#call\">call</a>"
  26697.  >
  26698. </table>
  26699.  
  26700.  
  26701. <_routine name="polygon">
  26702. <table border=0 cellspacing=2 cellpadding=2>
  26703.  
  26704.  
  26705.  <_2clist
  26706.   name="Platform:"
  26707.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  26708.  >
  26709.  
  26710.  <_2clist
  26711.   name="Syntax:"
  26712.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  26713.  polygon(i1, i2, s)
  26714. </font>"
  26715.  >
  26716.  <_2clist
  26717.   name="Description:"
  26718.   description=
  26719. "Draw a polygon with 3 or more vertices given in s, on a
  26720.  <font color=\"#CC3366\">pixel-graphics</font> screen using a certain
  26721.  color i1. Fill the area if i2 is 1. Don't fill if i2 is 0."
  26722.  >
  26723. <_2clist
  26724.   name="Example:"
  26725.   description=""
  26726.  >
  26727. <_eucode>
  26728. polygon(GREEN, 1, {{100, 100}, {200, 200}, {900, 700}})
  26729. -- makes a solid green triangle.
  26730.  
  26731.  </_eucode>
  26732. <_2clist
  26733.   name="See Also:"
  26734.   description="<a href=\"lib_c_d.htm#draw_line\">draw_line</a>,
  26735. <a href=\"lib_e_g.htm#ellipse\">ellipse</a>"
  26736.  >
  26737. </table>
  26738.  
  26739.  
  26740. <_routine name="position">
  26741. <table border=0 cellspacing=2 cellpadding=2>
  26742.  
  26743.  
  26744.  <_2clist
  26745.   name="Syntax:"
  26746.   description="<font face = \"Arial, Helvetica\"> position(i1, i2)
  26747. </font>"
  26748.  >
  26749.  <_2clist
  26750.   name="Description:"
  26751.   description=
  26752. "Set the cursor to line i1, column i2, where the top left corner
  26753.  of the screen is line 1, column 1. The next character displayed
  26754.  on the screen will be printed at this location. position() will
  26755.  report an error if the location is off the screen."
  26756.  >
  26757. <_2clist
  26758.   name="Comments:"
  26759.   description=
  26760. "position() works in both <font color=\"#CC3366\">text and pixel-graphics
  26761.  modes</font>.
  26762. <p>
  26763. The coordinate system for displaying text is different from the one for
  26764.  displaying pixels. Pixels are displayed such that the top-left is (x=0,y=0)
  26765.  and the first coordinate controls the horizontal, left-right location.
  26766.  In <font color=\"#CC3366\">pixel-graphics modes</font>
  26767.  you can display both text and pixels. position() only sets the
  26768.  line and column for the text that you display, not the pixels
  26769.  that you plot. There is no corresponding routine for setting
  26770.  the next pixel position."
  26771.  >
  26772. <_2clist
  26773.   name="Example:"
  26774.   description=""
  26775.  >
  26776. <_eucode>
  26777. position(2,1)
  26778. -- the cursor moves to the beginning of the second line from
  26779. -- the top
  26780.  
  26781.  </_eucode>
  26782. <_2clist
  26783.   name="See Also:"
  26784.   description="<a href=\"lib_e_g.htm#get_position\">get_position</a>,
  26785. <a href=\"lib_p_r.htm#puts\">puts</a>,
  26786. <a href=\"lib_p_r.htm#print\">print</a>,
  26787. <a href=\"lib_p_r.htm#printf\">printf</a>"
  26788.  >
  26789. </table>
  26790.  
  26791.  
  26792. <_routine name="power">
  26793. <table border=0 cellspacing=2 cellpadding=2>
  26794.  
  26795.  
  26796.  <_2clist
  26797.   name="Syntax:"
  26798.   description="<font face = \"Arial, Helvetica\"> x3 = power(x1, x2)
  26799. </font>"
  26800.  >
  26801.  <_2clist
  26802.   name="Description:"
  26803.   description=
  26804. "Raise x1 to the power x2"
  26805.  >
  26806. <_2clist
  26807.   name="Comments:"
  26808.   description=
  26809. "The arguments to this function may be atoms or sequences. The
  26810.  rules for <a href=\"refman_2.htm#26\">operations on sequences</a> apply.
  26811. <P>
  26812. Powers of 2 are calculated very efficiently."
  26813.  >
  26814. <_2clist
  26815.   name="Example 1:"
  26816.   description=""
  26817.  >
  26818. <_eucode>
  26819. ? power(5, 2)
  26820. -- 25 is printed
  26821.  
  26822.  </_eucode>
  26823. <_2clist
  26824.   name="Example 2:"
  26825.   description=""
  26826.  >
  26827. <_eucode>
  26828. ? power({5, 4, 3.5}, {2, 1, -0.5})
  26829. -- {25, 4, 0.534522} is printed
  26830.  
  26831.  </_eucode>
  26832. <_2clist
  26833.   name="Example 3:"
  26834.   description=""
  26835.  >
  26836. <_eucode>
  26837. ? power(2, {1, 2, 3, 4})
  26838. -- {2, 4, 8, 16}
  26839.  
  26840.  </_eucode>
  26841. <_2clist
  26842.   name="Example 4:"
  26843.   description=""
  26844.  >
  26845. <_eucode>
  26846. ? power({1, 2, 3, 4}, 2)
  26847. -- {1, 4, 9, 16}
  26848.  
  26849.  </_eucode>
  26850. <_2clist
  26851.   name="See Also:"
  26852.   description="<a href=\"lib_h_o.htm#log\">log</a>,
  26853. <a href=\"lib_s_t.htm#sqrt\">sqrt</a>"
  26854.  >
  26855. </table>
  26856.  
  26857.  
  26858. <_routine name="prepend">
  26859. <table border=0 cellspacing=2 cellpadding=2>
  26860.  
  26861.  
  26862.  <_2clist
  26863.   name="Syntax:"
  26864.   description="<font face = \"Arial, Helvetica\"> s2 = prepend(s1, x)
  26865. </font>"
  26866.  >
  26867.  <_2clist
  26868.   name="Description:"
  26869.   description=
  26870. "Prepend x to the start of sequence s1. The length of s2 will be
  26871.  <a href=\"lib_h_o.htm#length\">length(s1)</a> + 1."
  26872.  >
  26873. <_2clist
  26874.   name="Comments:"
  26875.   description=
  26876. "If x is an atom this is the same as <b>s2 = x & s1</b>. If x is a
  26877.  sequence it is definitely not the same.
  26878. <P>
  26879. The case where s1 and s2 are the same variable is handled
  26880.  very efficiently."
  26881.  >
  26882. <_2clist
  26883.   name="Example 1:"
  26884.   description=""
  26885.  >
  26886. <_eucode>
  26887. prepend({1,2,3}, {0,0})   -- {{0,0}, 1, 2, 3}
  26888.  
  26889. -- Compare with concatenation:
  26890.  
  26891. {0,0} & {1,2,3}           -- {0, 0, 1, 2, 3}
  26892.  
  26893.  </_eucode>
  26894. <_2clist
  26895.   name="Example 2:"
  26896.   description=""
  26897.  >
  26898. <_eucode>
  26899. s = {}
  26900. for i = 1 to 10 do
  26901.     s = prepend(s, i)
  26902. end for
  26903. -- s is {10,9,8,7,6,5,4,3,2,1}
  26904.  
  26905.  </_eucode>
  26906. <_2clist
  26907.   name="See Also:"
  26908.   description="<a href=\"lib_a_b.htm#append\">append</a>,
  26909.                <a href=\"refman_2.htm#27\">concatenation operator &</a>,
  26910.                <a href=\"refman_2.htm#28\">sequence-formation operator</a>"
  26911.  >
  26912. </table>
  26913.  
  26914.  
  26915. <_routine name="print">
  26916. <table border=0 cellspacing=2 cellpadding=2>
  26917.  
  26918.  
  26919.  <_2clist
  26920.   name="Syntax:"
  26921.   description="<font face = \"Arial, Helvetica\"> print(fn, x)
  26922. </font>"
  26923.  >
  26924.  <_2clist
  26925.   name="Description:"
  26926.   description=
  26927. "Print, to file or device fn, an object x with braces { , , , }
  26928.  to show the structure."
  26929.  >
  26930. <_2clist
  26931.   name="Example 1:"
  26932.   description=""
  26933.  >
  26934. <_eucode>
  26935. print(1, "ABC")  -- output is:  {65, 66, 67}
  26936. puts(1, "ABC")   -- output is:  ABC
  26937.  
  26938.  </_eucode>
  26939. <_2clist
  26940.   name="Example 2:"
  26941.   description=""
  26942.  >
  26943. <_eucode>
  26944. print(1, repeat({10,20}, 3))
  26945. -- output is: {{10,20},{10,20},{10,20}}
  26946.  
  26947.  </_eucode>
  26948. <_2clist
  26949.   name="See Also:"
  26950.   description="<a href=\"lib_a_b.htm#?\">?</a>,
  26951. <a href=\"lib_p_r.htm#puts\">puts</a>,
  26952. <a href=\"lib_p_r.htm#printf\">printf</a>,
  26953. <a href=\"lib_e_g.htm#get\">get</a>"
  26954.  >
  26955. </table>
  26956.  
  26957.  
  26958. <_routine name="printf">
  26959. <table border=0 cellspacing=2 cellpadding=2>
  26960.  
  26961.  
  26962.  <_2clist
  26963.   name="Syntax:"
  26964.   description="<font face = \"Arial, Helvetica\"> printf(fn, st, x)
  26965. </font>"
  26966.  >
  26967.  <_2clist
  26968.   name="Description:"
  26969.   description=
  26970. "Print x, to file or device fn, using format string st. If x is
  26971.  an atom then a single value will be printed. If x is a sequence,
  26972.  then formats from st are applied to <b><i>successive elements</i></b> of x.
  26973.  Thus printf() always takes exactly 3 arguments. Only the length of
  26974.  the last argument, containing the values to be printed, will
  26975.  vary. The basic formats are:<P>
  26976.  %d - print an atom as a decimal integer<BR>
  26977.  %x - print an atom as a hexadecimal integer<BR>
  26978.  %o - print an atom as an octal integer<BR>
  26979.  %s - print a sequence as a string of characters, or print an atom as
  26980.  a single character<BR>
  26981.  %e - print an atom as a floating point number with exponential
  26982.  notation<BR>
  26983.  %f - print an atom as a floating-point number with a decimal
  26984.  point but no exponent<BR>
  26985.  %g - print an atom as a floating point number using either
  26986.  the %f or %e format, whichever seems more appropriate<BR>
  26987.  %% - print the '%' character itself<BR>
  26988. <P>
  26989. Field widths can be added to the basic formats, e.g. %5d, %8.2f,
  26990.  %10.4s. The number before the decimal point is the minimum field
  26991.  width to be used. The number after the decimal point is the
  26992.  precision to be used.
  26993. <P>
  26994. If the field width is negative, e.g. %-5d then the value will be
  26995.  left-justified within the field. Normally it will be right-justified.
  26996.  If the field width starts with a leading 0, e.g. %08d
  26997.  then leading zeros will be supplied to fill up the field. If the
  26998.  field width starts with a '+' e.g. %+7d then a plus sign will be
  26999.  printed for positive values."
  27000.  >
  27001. <_2clist
  27002.   name="Comments:"
  27003.   description=
  27004. "Watch out for the following common mistake:"
  27005. >
  27006. <_eucode>
  27007.     name="John Smith"
  27008.     printf(1, "%s", name)     -- error!
  27009. </_eucode>
  27010.  
  27011. <_2clist
  27012.   name=""
  27013.   description=
  27014. "This will print only the first character, J, of name, as each element
  27015.  of name is taken to be a separate value to be formatted. You must
  27016.  say this instead:"
  27017.  >
  27018. <_eucode>
  27019.     name="John Smith"
  27020.     printf(1, "%s", {name})   -- correct
  27021. </_eucode>
  27022.  
  27023. <_2clist
  27024.   name=""
  27025.   description=
  27026. "Now, the third argument of printf() is a one-element sequence
  27027.  containing the item to be formatted."
  27028.  >
  27029. <_2clist
  27030.   name="Example 1:"
  27031.   description=""
  27032.  >
  27033. <_eucode>
  27034. rate = 7.875
  27035. printf(myfile, "The interest rate is: %8.2f\n", rate)
  27036.  
  27037.       The interest rate is:     7.88
  27038.  
  27039.  </_eucode>
  27040. <_2clist
  27041.   name="Example 2:"
  27042.   description=""
  27043.  >
  27044. <_eucode>
  27045. name="John Smith"
  27046. score=97
  27047. printf(1, "%15s, %5d\n", {name, score})
  27048.  
  27049.       John Smith,    97
  27050.  
  27051.  </_eucode>
  27052. <_2clist
  27053.   name="Example 3:"
  27054.   description=""
  27055.  >
  27056. <_eucode>
  27057. printf(1, "%-10.4s $ %s", {"ABCDEFGHIJKLMNOP", "XXX"})
  27058.  
  27059.       ABCD       $ XXX
  27060.  
  27061.  </_eucode>
  27062. <_2clist
  27063.   name="See Also:"
  27064.   description="<a href=\"lib_s_t.htm#sprintf\">sprintf</a>,
  27065. <a href=\"lib_p_r.htm#puts\">puts</a>,
  27066. <a href=\"lib_h_o.htm#open\">open</a>"
  27067.  >
  27068. </table>
  27069.  
  27070.  
  27071. <_routine name="profile">
  27072. <table border=0 cellspacing=2 cellpadding=2>
  27073.  
  27074.  
  27075.  <_2clist
  27076.   name="Syntax:"
  27077.   description="<font face = \"Arial, Helvetica\"> profile(i)
  27078. </font>"
  27079.  >
  27080.  <_2clist
  27081.   name="Description:"
  27082.   description=
  27083. "Enable or disable profiling at run-time. This works for both
  27084.  <font color=\"#993333\"><b>execution-count</b></font> and 
  27085.  <font color=\"#993333\"><b>time-profiling</b></font>.
  27086.  If i is 1 then profiling will be enabled, and samples/counts will be
  27087.  recorded. If i is 0 then profiling will be disabled and
  27088.  samples/counts will not be recorded."
  27089.  >
  27090. <_2clist
  27091.   name="Comments:"
  27092.   description=
  27093. "After a \"<b>with profile</b>\" or \"<b>with profile_time</b>\" statement,
  27094.  profiling is turned on automatically. Use profile(0) to
  27095.  turn it off. Use profile(1) to turn it back on when
  27096.  execution reaches the code that you wish to focus the
  27097.  profile on."
  27098.  >
  27099. <_2clist
  27100.   name="Example 1:"
  27101.   description=""
  27102.  >
  27103. <_eucode>
  27104. with profile_time
  27105. profile(0)
  27106.   ...
  27107. procedure slow_routine()
  27108. profile(1)
  27109.   ...
  27110. profile(0)
  27111. end procedure
  27112.  
  27113.  </_eucode>
  27114. <_2clist
  27115.   name="See Also:"
  27116.   description="<a href=\"lib_s_t.htm#trace\">trace</a>,
  27117.                <a href=\"refman_3.htm#2\">profiling</a>,
  27118.                <a href=\"refman_2.htm#6\">special top-level statements</a>"
  27119.  >
  27120. </table>
  27121.  
  27122.  
  27123. <_routine name="prompt_number">
  27124. <table border=0 cellspacing=2 cellpadding=2>
  27125.  
  27126.  
  27127.  <_2clist
  27128.   name="Syntax:"
  27129.   description="<font face = \"Arial, Helvetica\"> include get.e<BR>
  27130.  a = prompt_number(st, s)
  27131. </font>"
  27132.  >
  27133.  <_2clist
  27134.   name="Description:"
  27135.   description=
  27136. "Prompt the user to enter a number. st is a string of text that will be
  27137.  displayed on the screen. s is a sequence of two values {lower, upper}
  27138.  which determine the range of values that the user may enter. If the user
  27139.  enters a number that is less than lower or greater than upper, he will
  27140.  be prompted again. s can be <a href=\"refman_2.htm#empty_seq\">empty</a>,
  27141.  {}, if there are no restrictions."
  27142.  >
  27143.  
  27144. <_2clist
  27145.   name="Comments:"
  27146.   description="If this routine is too simple for your needs, feel free to
  27147.      copy it and make your own more specialized version."
  27148. >
  27149.  
  27150. <_2clist
  27151.   name="Example 1:"
  27152.   description=""
  27153.  >
  27154. <_eucode>
  27155. age = prompt_number("What is your age? ", {0, 150})
  27156.  
  27157.  </_eucode>
  27158. <_2clist
  27159.   name="Example 2:"
  27160.   description=""
  27161.  >
  27162. <_eucode>
  27163. t = prompt_number("Enter a temperature in Celcius:\n", {})
  27164.  
  27165.  </_eucode>
  27166. <_2clist
  27167.   name="See Also:"
  27168.   description="<a href=\"lib_e_g.htm#get\">get</a>,
  27169. <a href=\"lib_p_r.htm#prompt_string\">prompt_string</a>"
  27170.  >
  27171. </table>
  27172.  
  27173.  
  27174. <_routine name="prompt_string">
  27175. <table border=0 cellspacing=2 cellpadding=2>
  27176.  
  27177.  
  27178.  <_2clist
  27179.   name="Syntax:"
  27180.   description="<font face = \"Arial, Helvetica\"> include get.e<BR>
  27181.  s = prompt_string(st)
  27182. </font>"
  27183.  >
  27184.  <_2clist
  27185.   name="Description:"
  27186.   description=
  27187. "  Prompt the user to enter a string of text. st is a string that
  27188.  will be displayed on the screen. The string that the user types
  27189.  will be returned as a sequence, minus any new-line character. "
  27190.  >
  27191. <_2clist
  27192.   name="Comments:"
  27193.   description=
  27194. " If the user happens to type control-Z (indicates end-of-file), 
  27195.   \"\" will be returned.
  27196.  "
  27197.  >
  27198. <_2clist
  27199.   name="Example:"
  27200.   description=""
  27201.  >
  27202. <_eucode>
  27203. name = prompt_string("What is your name? ")
  27204.  
  27205.  </_eucode>
  27206. <_2clist
  27207.   name="See Also:"
  27208.   description="<a href=\"lib_e_g.htm#gets\">gets</a>,
  27209. <a href=\"lib_p_r.htm#prompt_number\">prompt_number</a>"
  27210.  >
  27211. </table>
  27212.  
  27213.  
  27214. <_routine name="put_screen_char">
  27215. <table border=0 cellspacing=2 cellpadding=2>
  27216.  
  27217.  
  27218.  <_2clist
  27219.   name="Syntax:"
  27220.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  27221.   put_screen_char(i1, i2, s)
  27222. </font>"
  27223.  >
  27224.  <_2clist
  27225.   name="Description:"
  27226.   description=
  27227. "Write zero or more characters onto the screen along with their attributes.
  27228. i1 specifies the line, and i2 specifies the column where the first
  27229. character should be written. The sequence s looks
  27230. like: {ascii-code1, attribute1, ascii-code2, attribute2, ...}.
  27231. Each pair of elements in s describes one character. The ascii-code
  27232. atom contains the ASCII code of the character. The attributes atom contains
  27233. the foreground color, background color, and possibly other platform-dependent
  27234. information controlling how the character is displayed on the screen."
  27235.  >
  27236. <_2clist
  27237.   name="Comments:"
  27238.   description=
  27239. "The length of s must be a multiple of 2. If s has 0 length, nothing
  27240.  will be written to the screen.<p>
  27241.  It's faster to write several characters to the screen with a single
  27242.  call to put_screen_char() than it is to write one character at a time."
  27243. >
  27244. <_2clist
  27245.   name="Example:"
  27246.   description=""
  27247.  >
  27248. <_eucode>
  27249. -- write AZ to the top left of the screen
  27250. -- (attributes are platform-dependent)
  27251. put_screen_char(1, 1, {'A', 152, 'Z', 131}) 
  27252.  </_eucode>
  27253. <_2clist
  27254.   name="See Also:"
  27255.   description="<a href=\"lib_e_g.htm#get_screen_char\">get_screen_char</a>,
  27256. <a href=\"lib_c_d.htm#display_text_image\">display_text_image</a>"
  27257.  >
  27258. </table>
  27259.  
  27260.  
  27261. <_routine name="puts">
  27262. <table border=0 cellspacing=2 cellpadding=2>
  27263.  
  27264.  
  27265.  <_2clist
  27266.   name="Syntax:"
  27267.   description="<font face = \"Arial, Helvetica\"> puts(fn, x)
  27268. </font>"
  27269.  >
  27270.  <_2clist
  27271.   name="Description:"
  27272.   description=
  27273. "Output, to file or device fn, a single byte (atom) or sequence
  27274.  of bytes. The low order 8-bits of each value is actually sent
  27275.  out. If fn is the screen you will see text characters displayed."
  27276.  >
  27277. <_2clist
  27278.   name="Comments:"
  27279.   description=
  27280. "When you output a sequence of bytes it must not have any (sub)sequences
  27281.  within it. It must be a
  27282.  <font color=\"#993333\"><b>sequence of atoms</b></font> only.
  27283.  (Typically a string of ASCII codes)."
  27284.  >
  27285. <_2clist
  27286.   name="Example 1:"
  27287.   description=""
  27288.  >
  27289. <_eucode>
  27290. puts(SCREEN, "Enter your first name: ")
  27291.  
  27292.  </_eucode>
  27293. <_2clist
  27294.   name="Example 2:"
  27295.   description=""
  27296.  >
  27297. <_eucode>
  27298. puts(output, 'A')  -- the single byte 65 will be sent to output
  27299.  
  27300.  </_eucode>
  27301. <_2clist
  27302.   name="See Also:"
  27303.   description="<a href=\"lib_p_r.htm#printf\">printf</a>,
  27304. <a href=\"lib_e_g.htm#gets\">gets</a>,
  27305. <a href=\"lib_h_o.htm#open\">open</a>"
  27306.  >
  27307. </table>
  27308.  
  27309.  
  27310. <_routine name="rand">
  27311. <table border=0 cellspacing=2 cellpadding=2>
  27312.  
  27313.  
  27314.  <_2clist
  27315.   name="Syntax:"
  27316.   description="<font face = \"Arial, Helvetica\"> x2 = rand(x1)
  27317. </font>"
  27318.  >
  27319.  <_2clist
  27320.   name="Description:"
  27321.   description=
  27322. "Return a random integer from 1 to x1, where x1 may be from 1 to
  27323.  the largest positive value of type integer (1073741823)."
  27324.  >
  27325. <_2clist
  27326.   name="Comments:"
  27327.   description=
  27328. " This function may be applied to an atom or to all elements
  27329.  of a sequence."
  27330.  >
  27331. <_2clist
  27332.   name="Example:"
  27333.   description=""
  27334.  >
  27335. <_eucode>
  27336. s = rand({10, 20, 30})
  27337. -- s might be: {5, 17, 23} or {9, 3, 12} etc.
  27338.  
  27339.  </_eucode>
  27340. <_2clist
  27341.   name="See Also:"
  27342.   description="<a href=\"lib_s_t.htm#set_rand\">set_rand</a>"
  27343.  >
  27344. </table>
  27345.  
  27346.  
  27347. <_routine name="read_bitmap">
  27348. <table border=0 cellspacing=2 cellpadding=2>
  27349.  
  27350.  
  27351.  <_2clist
  27352.   name="Syntax:"
  27353.   description="<font face =\"Arial, Helvetica\"> include image.e<BR>
  27354.  x = read_bitmap(st)
  27355. </font>"
  27356.  >
  27357.  <_2clist
  27358.   name="Description:"
  27359.   description=
  27360. "st is the name of a .bmp \"bitmap\" file. The file should be in
  27361.  the bitmap format. The most common variations of the format
  27362.  are supported. If the file is read successfully the result will
  27363.  be a 2-element sequence. The first element is the palette,
  27364.  containing intensity values in the range 0 to 255. The
  27365.  second element is a 2-d sequence of sequences containing a
  27366.  pixel-graphics image. You can pass the palette to all_palette()
  27367.  (after dividing it by 4 to scale it). The image can be passed
  27368.  to display_image().<P>
  27369. Bitmaps of 2, 4, 16 or 256 colors are supported. If the file is
  27370.  not in a good format, an error code (atom) is returned instead:"
  27371.  >
  27372.  
  27373. <_eucode>
  27374.     global constant BMP_OPEN_FAILED = 1,
  27375.                  BMP_UNEXPECTED_EOF = 2,
  27376.              BMP_UNSUPPORTED_FORMAT = 3
  27377. </_eucode>
  27378.  
  27379. <_2clist
  27380.   name="Comments:"
  27381.   description=
  27382. "You can create your own bitmap picture files using Windows
  27383.  Paintbrush and many other graphics programs. You can then
  27384.  incorporate these pictures into your Euphoria programs."
  27385.  >
  27386. <_2clist
  27387.   name="Example:"
  27388.   description=""
  27389.  >
  27390. <_eucode>
  27391. x = read_bitmap("c:\\windows\\arcade.bmp")
  27392. -- note: double backslash needed to get single backslash in
  27393. -- a string
  27394.  
  27395.  </_eucode>
  27396. <_2clist
  27397.   name="Example Program:"
  27398.   description="<font color=\"#5500FF\"><b>demo\dos32\bitmap.ex</b></font>"
  27399.  >
  27400.  
  27401.  <_2clist
  27402.   name="See Also:"
  27403.   description="<a href=\"lib_p_r.htm#palette\">palette</a>,
  27404. <a href=\"lib_a_b.htm#all_palette\">all_palette</a>,
  27405. <a href=\"lib_c_d.htm#display_image\">display_image</a>,
  27406. <a href=\"lib_s_t.htm#save_bitmap\">save_bitmap</a>"
  27407.  >
  27408. </table>
  27409.  
  27410. <_routine name="register_block">
  27411. <table border=0 cellspacing=2 cellpadding=2>
  27412.  
  27413. <_2clist
  27414.  name="Syntax:"
  27415.  description="<font face=\"Arial, Helvetica\"> include machine.e (or safe.e)<BR>
  27416.  register_block(a, i)</font>"
  27417. >
  27418. <_2clist
  27419.  name="Description:"
  27420.  description="Add a block of memory to the list of safe blocks maintained
  27421.  by <font color=\"#5500FF\"><b>safe.e</b></font> (the debug version of
  27422.  <font color=\"#5500FF\"><b>machine.e</b></font>). The block starts at
  27423.  address a. The length of the block is i bytes."
  27424. >
  27425. <_2clist
  27426.  name="Comments:"
  27427.  description="This routine is only meant to be used for <b>debugging
  27428.  purposes</b>. <font color=\"#5500FF\"><b>safe.e</b></font> tracks the
  27429.  blocks of memory that your program is allowed to
  27430.  <a href=\"lib_p_r.htm#peek\">peek()</a>,
  27431.  <a href=\"lib_p_r.htm#poke\">poke()</a>,
  27432.  <a href=\"lib_h_o.htm#mem_copy\">mem_copy()</a> etc. These are normally
  27433.  just the blocks that you have allocated using Euphoria's
  27434.  <a href=\"lib_a_b.htm#allocate\">allocate()</a> or
  27435.  <a href=\"lib_a_b.htm#allocate_low\">allocate_low()</a> routines, and which 
  27436.  you have not yet freed using Euphoria's
  27437.  <a href=\"lib_e_g.htm#free\">free()</a> or
  27438.  <a href=\"lib_e_g.htm#free_low\">free_low()</a>. In some cases, you may
  27439.  acquire additional, external, blocks of memory, perhaps as a result
  27440.  of calling a C routine. If you are debugging your program using
  27441.  <font color=\"#5500FF\"><b>safe.e</b></font>, you must register
  27442.  these external blocks of memory or
  27443.  <font color=\"#5500FF\"><b>safe.e</b></font> will prevent you from
  27444.  accessing them. When you are finished using an external block you can
  27445.  unregister it using unregister_block().
  27446.  <p>
  27447.  When you include <font color=\"#5500FF\"><b>machine.e</b></font>, you'll
  27448.  get different versions of register_block() and unregister_block()
  27449.  that do nothing. This makes it easy to switch back and forth between
  27450.  debug and non-debug runs of your program."
  27451. >
  27452. <_2clist
  27453.   name="Example 1:"
  27454.   description=""
  27455. >
  27456. <_eucode>
  27457. atom addr
  27458.  
  27459. addr = c_func(x, {})
  27460. register_block(addr, 5)
  27461. poke(addr, "ABCDE")
  27462. unregister_block(addr)
  27463. </_eucode>
  27464. <_2clist
  27465.   name="See Also:"
  27466.   description="<a href=\"lib_u_z.htm#unregister_block\">unregister_block</a>,
  27467.  <a href=\"library.htm#safe\"><font color=\"#5500FF\"><b>safe.e</b></font></a>"
  27468.  >
  27469. </table>
  27470.  
  27471. <_routine name="remainder">
  27472. <table border=0 cellspacing=2 cellpadding=2>
  27473.  
  27474.  
  27475.  <_2clist
  27476.   name="Syntax:"
  27477.   description="<font face=\"Arial, Helvetica\"> x3 = remainder(x1, x2)
  27478. </font>"
  27479.  >
  27480.  <_2clist
  27481.   name="Description:"
  27482.   description="Compute the remainder after dividing x1 by x2. The result will
  27483.  have the same sign as x1, and the magnitude of the result will
  27484.  be less than the magnitude of x2."
  27485.  >
  27486. <_2clist
  27487.   name="Comments:"
  27488.   description=
  27489. "The arguments to this function may be atoms or sequences. The
  27490.  rules for <a href=\"refman_2.htm#26\">operations on sequences</a> apply."
  27491.  >
  27492. <_2clist
  27493.   name="Example 1:"
  27494.   description=""
  27495.  >
  27496. <_eucode>
  27497. a = remainder(9, 4)
  27498. -- a is 1
  27499.  
  27500.  </_eucode>
  27501. <_2clist
  27502.   name="Example 2:"
  27503.   description=""
  27504.  >
  27505. <_eucode>
  27506. s = remainder({81, -3.5, -9, 5.5}, {8, -1.7, 2, -4})
  27507. -- s is {1, -0.1, -1, 1.5}
  27508.  
  27509.  </_eucode>
  27510. <_2clist
  27511.   name="Example 3:"
  27512.   description=""
  27513.  >
  27514. <_eucode>
  27515. s = remainder({17, 12, 34}, 16)
  27516. -- s is {1, 12, 2}
  27517.  
  27518.  </_eucode>
  27519. <_2clist
  27520.   name="Example 4:"
  27521.   description=""
  27522.  >
  27523. <_eucode>
  27524. s = remainder(16, {2, 3, 5})
  27525. -- s is {0, 1, 1}
  27526.   
  27527. </_eucode>
  27528. <_2clist
  27529.   name="See Also:"
  27530.   description="<a href=\"lib_e_g.htm#floor\">floor</a>"
  27531.  >
  27532. </table>
  27533.  
  27534.  
  27535. <_routine name="repeat">
  27536. <table border=0 cellspacing=2 cellpadding=2>
  27537.  
  27538.  
  27539.  <_2clist
  27540.   name="Syntax:"
  27541.   description="<font face = \"Arial, Helvetica\"> s = repeat(x, a)
  27542. </font>"
  27543.  >
  27544.  <_2clist
  27545.   name="Description:"
  27546.   description=
  27547. "  Create a sequence of length a where each element is x. "
  27548.  >
  27549. <_2clist
  27550.   name="Comments:"
  27551.   description=
  27552. " When you repeat a sequence or a floating-point number the
  27553.  interpreter does not actually make multiple copies in memory.
  27554.  Rather, a single copy is \"pointed to\" a number of times.
  27555.  "
  27556.  >
  27557. <_2clist
  27558.   name="Example 1:"
  27559.   description=""
  27560.  >
  27561. <_eucode>
  27562. repeat(0, 10)      -- {0,0,0,0,0,0,0,0,0,0}
  27563.  
  27564.  </_eucode>
  27565. <_2clist
  27566.   name="Example 2:"
  27567.   description=""
  27568.  >
  27569. <_eucode>
  27570. repeat("JOHN", 4)  -- {"JOHN", "JOHN", "JOHN", "JOHN"}
  27571. -- The interpreter will create only one copy of "JOHN"
  27572. -- in memory
  27573.  
  27574.  </_eucode>
  27575. <_2clist
  27576.   name="See Also:"
  27577.   description="<a href=\"lib_a_b.htm#append\">append</a>,
  27578.                <a href=\"lib_p_r.htm#prepend\">prepend</a>,
  27579.                <a href=\"refman_2.htm#28\">sequence-formation operator</a>"
  27580.  >
  27581. </table>
  27582.  
  27583.  
  27584. <_routine name="reverse">
  27585. <table border=0 cellspacing=2 cellpadding=2>
  27586.  
  27587.  
  27588.  <_2clist
  27589.   name="Syntax:"
  27590.   description="<font face = \"Arial, Helvetica\"> include misc.e<BR>
  27591.  s2 = reverse(s1)
  27592. </font>"
  27593.  >
  27594.  <_2clist
  27595.   name="Description:"
  27596.   description=
  27597. "  Reverse the order of elements in a sequence. "
  27598.  >
  27599. <_2clist
  27600.   name="Comments:"
  27601.   description=
  27602. " A new sequence is created where the top-level elements appear
  27603.  in reverse order compared to the original sequence.
  27604.  "
  27605.  >
  27606. <_2clist
  27607.   name="Example 1:"
  27608.   description=""
  27609.  >
  27610. <_eucode>
  27611. reverse({1,3,5,7})          -- {7,5,3,1}
  27612.  
  27613.  </_eucode>
  27614. <_2clist
  27615.   name="Example 2:"
  27616.   description=""
  27617.  >
  27618. <_eucode>
  27619. reverse({{1,2,3}, {4,5,6}}) -- {{4,5,6}, {1,2,3}}
  27620.  
  27621.  </_eucode>
  27622. <_2clist
  27623.   name="Example 3:"
  27624.   description=""
  27625.  >
  27626. <_eucode>
  27627. reverse({99})               -- {99}
  27628.  
  27629.  </_eucode>
  27630. <_2clist
  27631.   name="Example 4:"
  27632.   description=""
  27633.  >
  27634. <_eucode>
  27635. reverse({})                 -- {}
  27636.  
  27637.  </_eucode>
  27638. <_2clist
  27639.   name="See Also:"
  27640.   description="<a href=\"lib_a_b.htm#append\">append</a>,
  27641. <a href=\"lib_p_r.htm#prepend\">prepend</a>,
  27642. <a href=\"lib_p_r.htm#repeat\">repeat</a>"
  27643.  >
  27644. </table>
  27645.  
  27646.  
  27647. <_routine name="routine_id">
  27648. <table border=0 cellspacing=2 cellpadding=2>
  27649.  
  27650.  
  27651.  <_2clist
  27652.   name="Syntax:"
  27653.   description="<font face = \"Arial, Helvetica\"> i = routine_id(st)
  27654. </font>"
  27655.  >
  27656.  <_2clist
  27657.   name="Description:"
  27658.   description=
  27659. "Return an integer id number, known as a
  27660.  <font color=\"#993333\"><b>routine id</b></font>, for a user-defined Euphoria
  27661.  procedure or function. The name of the procedure or function
  27662.  is given by the string sequence st. -1 is returned if the named
  27663.  routine can't be found."
  27664.  >
  27665. <_2clist
  27666.   name="Comments:"
  27667.   description=
  27668. "The id number can be passed to call_proc() or call_func(), to indirectly
  27669.  call the routine named by st.
  27670. <P>
  27671.  The routine named by st must be visible, i.e. callable, at the
  27672.  place where routine_id() is used to get the id number. Indirect calls to the
  27673.  routine can appear earlier in the program than the definition
  27674.  of the routine, but the id number can only be obtained in code that 
  27675.  comes <i>after</i> the definition of the routine - see example 2 below.
  27676.  
  27677. <P> 
  27678.  Once obtained, a valid <font color=\"#993333\"><b>routine id</b></font>
  27679.  can be used at <font color=\"#CC0099\"><b><i>any</i></b></font> place 
  27680.  in the program to call a routine indirectly via call_proc()/call_func().
  27681. <p>
  27682.  Some typical uses of routine_id() are:<p>
  27683.  1. <a href=\"refman_2.htm#42\">Calling a routine that is defined later in
  27684.   a program.</a><br>
  27685.  2. Creating a subroutine that takes another routine as a parameter. (See
  27686.   Example 2 below)<br>
  27687.  3. Using a sequence of <font color=\"#993333\"><b>routine id's</b></font>
  27688.   to make a case (switch) statement.<br>
  27689.  4. Setting up an Object-Oriented system.<br>
  27690.  5. Getting a <font color=\"#993333\"><b>routine id</b></font> so you
  27691.   can pass it to call_back(). (See
  27692.  <a href=\"platform.htm#callback\"><font color=\"#5500FF\"><b>platform.doc</b></font></a>)
  27693.  <p>
  27694.  Note that C routines, callable by Euphoria, also have routine id's.
  27695.  See define_c_proc() and define_c_func()."
  27696.  >
  27697. <_2clist
  27698.   name="Example 1:"
  27699.   description=""
  27700.  >
  27701. <_eucode>
  27702. procedure foo()
  27703.     puts(1, "Hello World\n")
  27704. end procedure
  27705.  
  27706. integer foo_num
  27707. foo_num = routine_id("foo")
  27708.  
  27709. call_proc(foo_num, {})  -- same as calling foo()
  27710.  
  27711.  </_eucode>
  27712. <_2clist
  27713.   name="Example 2:"
  27714.   description=""
  27715.  >
  27716. <_eucode>
  27717. function apply_to_all(sequence s, integer f)
  27718.     -- apply a function to all elements of a sequence
  27719.     sequence result
  27720.     result = {}
  27721.     for i = 1 to length(s) do
  27722.         -- we can call add1() here although it comes later in the program
  27723.         result = append(result, call_func(f, {s[i]}))
  27724.     end for
  27725.     return result
  27726. end function
  27727.  
  27728. function add1(atom x)
  27729.     return x + 1
  27730. end function
  27731.  
  27732. -- add1() is visible here, so we can ask for its routine id
  27733. ? apply_to_all({1, 2, 3}, routine_id("add1"))
  27734. -- displays {2,3,4}
  27735.  
  27736.  </_eucode>
  27737. <_2clist
  27738.   name="See Also:"
  27739.   description="<a href=\"lib_c_d.htm#call_proc\">call_proc</a>,
  27740. <a href=\"lib_c_d.htm#call_func\">call_func</a>,
  27741. <a href=\"lib_c_d.htm#call_back\">call_back</a>,
  27742. <a href=\"lib_c_d.htm#define_c_func\">define_c_func</a>,
  27743. <a href=\"lib_c_d.htm#define_c_proc\">define_c_proc</a>,
  27744. <a href=\"platform.htm#callback\"><font color=\"#5500FF\"><b>platform.doc</b>
  27745. </font></a>"
  27746.  >
  27747. </table>
  27748.  
  27749. <_continue
  27750.   href="lib_s_t.htm"
  27751.   name="From S to T"
  27752. >
  27753.  
  27754. </body>
  27755. </html>
  27756. LIB_S_T.HTX
  27757. 38094
  27758. <_init_comment>
  27759. <html>
  27760. <head><title>Euphoria v2.2 Reference Manual Part II - Section 3</title>
  27761. </head>
  27762. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  27763. <br>
  27764.  
  27765.  
  27766. <_routine name="save_bitmap">
  27767. <table border=0 cellspacing=2 cellpadding=2>
  27768.  
  27769.  
  27770.  <_2clist
  27771.   name="Syntax:"
  27772.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  27773.  i = save_bitmap(s, st)
  27774. </font>"
  27775.  >
  27776.  <_2clist
  27777.   name="Description:"
  27778.   description=
  27779. "Create a bitmap (.bmp) file from a 2-element sequence s.
  27780.  st is the name of a .bmp \"bitmap\" file. s[1] is the palette:<P>
  27781. {{r,g,b}, {r,g,b}, ..., {r,g,b}}
  27782. <P>
  27783. Each red, green, or blue value is in the range 0 to 255. s[2]
  27784.  is a 2-d sequence of sequences containing a pixel-graphics image.
  27785.  The sequences contained in s[2] must all have the same length.
  27786.  s is in the same format as the value returned by read_bitmap().
  27787. <P>
  27788. The result will be one of the following codes:"
  27789.  >
  27790. <_eucode>
  27791.     global constant BMP_SUCCESS = 0,
  27792.                 BMP_OPEN_FAILED = 1,
  27793.                BMP_INVALID_MODE = 4 -- invalid graphics mode
  27794.                                     -- or invalid argument
  27795. </_eucode>
  27796.  
  27797. <_2clist
  27798.   name="Comments:"
  27799.   description=
  27800. "If you use get_all_palette() to get the palette before calling
  27801.  this function, you must multiply the returned intensity values
  27802.  by 4 before calling save_bitmap().
  27803. <p>
  27804. You might use save_image() to get the 2-d image for s[2].
  27805. <P>
  27806. save_bitmap() produces bitmaps of 2, 4, 16, or 256 colors and
  27807.  these can all be read with read_bitmap(). Windows Paintbrush
  27808.  and some other tools do not support 4-color bitmaps."
  27809.  >
  27810. <_2clist
  27811.   name="Example:"
  27812.   description=""
  27813.  >
  27814. <_eucode>
  27815. paletteData = get_all_palette() * 4
  27816. code = save_bitmap({paletteData, imageData},
  27817.                    "c:\\example\\a1.bmp")
  27818.  
  27819.  </_eucode>
  27820. <_2clist
  27821.   name="See Also:"
  27822.   description="<a href=\"lib_s_t.htm#save_image\">save_image</a>,
  27823. <a href=\"lib_p_r.htm#read_bitmap\">read_bitmap</a>,
  27824. <a href=\"lib_s_t.htm#save_screen\">save_screen</a>,
  27825. <a href=\"lib_e_g.htm#get_all_palette\">get_all_palette</a>"
  27826.  >
  27827. </table>
  27828.  
  27829.  
  27830. <_routine name="save_image">
  27831. <table border=0 cellspacing=2 cellpadding=2>
  27832.  
  27833.  
  27834.  <_2clist
  27835.   name="Platform:"
  27836.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  27837.  >
  27838.  
  27839.  <_2clist
  27840.   name="Syntax:"
  27841.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  27842.  s3 = save_image(s1, s2)
  27843. </font>"
  27844.  >
  27845.  <_2clist
  27846.   name="Description:"
  27847.   description=
  27848. "Save a rectangular image from a <font color=\"CC3366\">pixel-graphics</font>
  27849.  screen. The result is a 2-d sequence of sequences containing all the pixels
  27850.  in the image. You can redisplay the image using display_image().
  27851.  s1 is a 2-element sequence {x1,y1} specifying the top-left
  27852.  pixel in the image. s2 is a sequence {x2,y2} specifying the
  27853.  bottom-right pixel."
  27854.  >
  27855. <_2clist
  27856.   name="Example:"
  27857.   description=""
  27858.  >
  27859. <_eucode>
  27860. s = save_image({0,0}, {50,50})
  27861. display_image({100,200}, s)
  27862. display_image({300,400}, s)
  27863. -- saves a 51x51 square image, then redisplays it at {100,200}
  27864. -- and at {300,400}
  27865.  
  27866.  </_eucode>
  27867. <_2clist
  27868.   name="See Also:"
  27869.   description="<a href=\"lib_c_d.htm#display_image\">display_image</a>,
  27870. <a href=\"lib_s_t.htm#save_text_image\">save_text_image</a>"
  27871.  >
  27872. </table>
  27873.  
  27874.  
  27875. <_routine name="save_screen">
  27876. <table border=0 cellspacing=2 cellpadding=2>
  27877.  
  27878.  
  27879.  <_2clist
  27880.   name="Platform:"
  27881.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  27882.  >
  27883.  
  27884.  <_2clist
  27885.   name="Syntax:"
  27886.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  27887.  i = save_screen(x1, st)
  27888. </font>"
  27889.  >
  27890.  <_2clist
  27891.   name="Description:"
  27892.   description=
  27893. "Save the whole screen or a rectangular region of the screen as
  27894.  a Windows bitmap (.bmp) file. To save the whole screen, pass the
  27895.  integer 0 for x1. To save a rectangular region of the screen,
  27896.  x1 should be a sequence of 2 sequences:
  27897.  {{topLeftXPixel, topLeftYPixel}, 
  27898.  {bottomRightXPixel, bottomRightYPixel}}<P>
  27899. st is the name of a .bmp \"bitmap\" file.
  27900. <P>
  27901. The result will be one of the following codes:"
  27902.  >
  27903.  
  27904. <_eucode>
  27905.     global constant BMP_SUCCESS = 0,
  27906.                 BMP_OPEN_FAILED = 1,
  27907.                BMP_INVALID_MODE = 4 -- invalid graphics mode
  27908.                                     -- or invalid argument
  27909. </_eucode>
  27910.  
  27911. <_2clist
  27912.   name="Comments:"
  27913.   description=
  27914. "save_screen() produces bitmaps of 2, 4, 16, or 256 colors and
  27915.  these can all be read with read_bitmap(). Windows Paintbrush
  27916.  and some other tools do not support 4-color bitmaps.
  27917. <P>
  27918. save_screen() only works in
  27919.  <font color=\"#CC3366\">pixel-graphics modes</font>, not text modes."
  27920.  >
  27921. <_2clist
  27922.   name="Example 1:"
  27923.   description=""
  27924.  >
  27925. <_eucode>
  27926. -- save whole screen:
  27927. code = save_screen(0, "c:\\example\\a1.bmp")
  27928.  
  27929.  </_eucode>
  27930. <_2clist
  27931.   name="Example 2:"
  27932.   description=""
  27933.  >
  27934. <_eucode>
  27935. -- save part of screen:
  27936. err = save_screen({{0,0},{200, 15}}, "b1.bmp")
  27937.  
  27938.  </_eucode>
  27939. <_2clist
  27940.   name="See Also:"
  27941.   description="<a href=\"lib_s_t.htm#save_image\">save_image</a>,
  27942. <a href=\"lib_p_r.htm#read_bitmap\">read_bitmap</a>,
  27943. <a href=\"lib_s_t.htm#save_bitmap\">save_bitmap</a>"
  27944.  >
  27945. </table>
  27946.  
  27947.  
  27948. <_routine name="save_text_image">
  27949. <table border=0 cellspacing=2 cellpadding=2>
  27950.  
  27951.  
  27952.  <_2clist
  27953.   name="Platform:"
  27954.   description="<font color=\"#CC3366\"><b>DOS32, Linux</b></font>"
  27955.  >
  27956.  
  27957.  <_2clist
  27958.   name="Syntax:"
  27959.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  27960.  s3 = save_text_image(s1, s2)
  27961. </font>"
  27962.  >
  27963.  <_2clist
  27964.   name="Description:"
  27965.   description=
  27966. "Save a rectangular region of text from a
  27967.  <font color=\"#CC3366\">text-mode</font> screen.
  27968.  The result is a sequence of sequences containing ASCII characters
  27969.  and attributes from the screen. You can redisplay this text using
  27970.  display_text_image(). s1 is a 2-element sequence {line1, column1}
  27971.  specifying the top-left character. s2 is a sequence
  27972.  {line2, column2} specifying the bottom right character."
  27973.  >
  27974. <_2clist
  27975.   name="Comments:"
  27976.   description=
  27977. "Because the character attributes are also saved, you will get
  27978.  the correct foreground color, background color and other properties
  27979.  for each character when you redisplay the text.
  27980. <P>
  27981. On DOS32, an attribute byte is made up of two 4-bit fields that
  27982.  encode the foreground and background color of a character.
  27983.  The high-order 4 bits determine the background color, while
  27984.  the low-order 4 bits determine the foreground color.
  27985. <P>
  27986. This routine only works in <font color=\"#CC3366\">text modes</font>.
  27987. <P>
  27988. You might use this function in a text-mode graphical user
  27989.  interface to save a portion of the screen before displaying a
  27990.  drop-down menu, dialog box, alert box etc.
  27991. <P>
  27992. On DOS32, if you are flipping video pages, note that this function reads
  27993.  from the current active page."
  27994.  >
  27995. <_2clist
  27996.   name="Example:"
  27997.   description=" If the top 2 lines of the screen have:"
  27998.  >
  27999. <_eucode>
  28000.    Hello
  28001.    World
  28002. </_eucode>
  28003.  
  28004. <_2clist
  28005.   name=""
  28006.   description=
  28007. "And you execute:"
  28008. >
  28009. <_eucode>
  28010. s = save_text_image({1,1}, {2,5})
  28011. </_eucode>
  28012.  
  28013. <_2clist
  28014.   name=""
  28015.   description=
  28016. "Then s is something like:"
  28017. >
  28018. <_eucode>
  28019.     {"H-e-l-l-o-",
  28020.      "W-o-r-l-d-"}
  28021. where '-' indicates the attribute bytes
  28022.  
  28023.  </_eucode>
  28024. <_2clist
  28025.   name="See Also:"
  28026.   description=
  28027. "<a href=\"lib_c_d.htm#display_text_image\">display_text_image</a>,
  28028. <a href=\"lib_s_t.htm#save_image\">save_image</a>,
  28029. <a href=\"lib_s_t.htm#set_active_page\">set_active_page</a>,
  28030. <a href=\"lib_e_g.htm#get_screen_char\">get_screen_char</a>"
  28031.  >
  28032. </table>
  28033.  
  28034.  
  28035. <_routine name="scroll">
  28036. <table border=0 cellspacing=2 cellpadding=2>
  28037.  
  28038.  
  28039.  <_2clist
  28040.   name="Syntax:"
  28041.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  28042.  scroll(i1, i2, i3)
  28043. </font>"
  28044.  >
  28045.  
  28046. <_2clist
  28047.   name="Description:"
  28048.   description=
  28049. "Scroll a region of text on the screen either up (i1 positive) or
  28050.  down (i1 negative) by i1 lines. The region is the series of lines
  28051.  on the screen from i2 (top line) to i3 (bottom line), inclusive.
  28052.  New blank lines will appear at the top or bottom."
  28053. >
  28054.  
  28055. <_2clist
  28056.   name="Comments:"
  28057.   description=
  28058. "You could perform the scrolling operation using a series
  28059. of calls to puts(), but scroll() is much faster.
  28060. <p>
  28061. The position of the cursor after scrolling is not defined."
  28062. >
  28063.  
  28064. <_2clist
  28065.   name="Example Program:"
  28066.   description="<font color=\"#5500FF\"><b>bin\ed.ex</b></font>"
  28067. >
  28068.  
  28069.  <_2clist
  28070.   name="See Also:"
  28071.   description="<a href=\"lib_c_d.htm#clear_screen\">clear_screen</a>,
  28072. <a href=\"lib_s_t.htm#text_rows\">text_rows</a>"
  28073.  >
  28074. </table>
  28075.  
  28076.  
  28077. <_routine name="seek">
  28078. <table border=0 cellspacing=2 cellpadding=2>
  28079.  
  28080.  
  28081.  <_2clist
  28082.   name="Syntax:"
  28083.   description="<font face = \"Arial, Helvetica\"> include file.e<BR>
  28084.  i1 = seek(fn, i2)
  28085. </font>"
  28086.  >
  28087.  <_2clist
  28088.   name="Description:"
  28089.   description=
  28090. "  Seek (move) to any byte position in the file fn or to the end of
  28091.  file if i2 is -1. For each open file there is a current byte
  28092.  position that is updated as a result of I/O operations on the
  28093.  file. The initial file position is 0 for files opened for read,
  28094.  write or update. The initial position is the end of file for
  28095.  files opened for append. The value returned by seek() is 0 if the
  28096.  seek was successful, and non-zero if it was unsuccessful. It is
  28097.  possible to seek past the end of a file. In this case undefined
  28098.  bytes will be added to the file to make it long enough for the
  28099.  seek. "
  28100.  >
  28101. <_2clist
  28102.   name="Example:"
  28103.   description=""
  28104.  >
  28105. <_eucode>
  28106. include file.e
  28107.  
  28108. integer fn
  28109. fn = open("mydata", "r")
  28110. -- read and display first line of file 3 times:
  28111. for i = 1 to 3 do
  28112.     puts(1, gets(fn))
  28113.     if seek(fn, 0) then
  28114.         puts(1, "rewind failed!\n")
  28115.     end if
  28116. end for
  28117.  
  28118.  </_eucode>
  28119. <_2clist
  28120.   name="See Also:"
  28121.   description="<a href=\"lib_u_z.htm#where\">where</a>,
  28122. <a href=\"lib_h_o.htm#open\">open</a>"
  28123.  >
  28124. </table>
  28125.  
  28126.  
  28127. <_routine name="sequence">
  28128. <table border=0 cellspacing=2 cellpadding=2>
  28129.  
  28130.  
  28131.  <_2clist
  28132.   name="Syntax:"
  28133.   description="<font face = \"Arial, Helvetica\"> i = sequence(x)
  28134. </font>"
  28135.  >
  28136.  <_2clist
  28137.   name="Description:"
  28138.   description=
  28139. "  Return 1 if x is a sequence else return 0. "
  28140.  >
  28141. <_2clist
  28142.   name="Comments:"
  28143.   description=
  28144. " This serves to define the sequence type. You can also call
  28145.  it like an ordinary function to determine if an object is
  28146.  a sequence.
  28147.  "
  28148.  >
  28149. <_2clist
  28150.   name="Example 1:"
  28151.   description=""
  28152.  >
  28153. <_eucode>
  28154. sequence s
  28155. s = {1,2,3}
  28156.  
  28157.  </_eucode>
  28158. <_2clist
  28159.   name="Example 2:"
  28160.   description=""
  28161.  >
  28162. <_eucode>
  28163. if sequence(x) then
  28164.     sum = 0
  28165.     for i = 1 to length(x) do
  28166.         sum = sum + x[i]
  28167.     end for
  28168. else
  28169.     -- x must be an atom
  28170.     sum = x
  28171. end if
  28172.  
  28173.  </_eucode>
  28174. <_2clist
  28175.   name="See Also:"
  28176.   description="<a href=\"lib_a_b.htm#atom\">atom</a>,
  28177.                <a href=\"lib_h_o.htm#object\">object</a>,
  28178.                <a href=\"lib_h_o.htm#integer\">integer</a>,
  28179.                <a href=\"refman_2.htm#1\">atoms and sequences</a>"
  28180.  >
  28181. </table>
  28182.  
  28183.  
  28184. <_routine name="set_active_page">
  28185. <table border=0 cellspacing=2 cellpadding=2>
  28186.  
  28187.  
  28188.  <_2clist
  28189.   name="Platform:"
  28190.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  28191.  >
  28192.  
  28193.  <_2clist
  28194.   name="Syntax:"
  28195.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  28196.  set_active_page(i)
  28197. </font>"
  28198.  >
  28199.  <_2clist
  28200.   name="Description:"
  28201.   description=
  28202. "Select video page i to send all screen output to."
  28203.  >
  28204. <_2clist
  28205.   name="Comments:"
  28206.   description=
  28207. "With multiple pages you can instantaneously change the entire
  28208.  screen without causing any visible \"flicker\". You can also
  28209.  save the screen and bring it back quickly.
  28210. <P>
  28211. video_config() will tell you how many pages are available in
  28212.  the current graphics mode.
  28213. <P>
  28214. By default, the active page and the display page are both 0.
  28215. <P>
  28216. This works under DOS, or in a full-screen DOS window. In a
  28217.  partial-screen window you cannot change the active page."
  28218.  >
  28219. <_2clist
  28220.   name="Example:"
  28221.   description=""
  28222.  >
  28223. <_eucode>
  28224. include image.e
  28225.  
  28226. -- active & display pages are initially both 0
  28227. puts(1, "\nThis is page 0\n")
  28228. set_active_page(1)     -- screen output will now go to page 1
  28229. clear_screen()
  28230. puts(1, "\nNow we've flipped to page 1\n")
  28231. if getc(0) then        -- wait for key-press
  28232. end if
  28233. set_display_page(1)    -- "Now we've ..." becomes visible
  28234. if getc(0) then        -- wait for key-press
  28235. end if
  28236. set_display_page(0)    -- "This is ..." becomes visible again
  28237. set_active_page(0)
  28238.  
  28239.  </_eucode>
  28240. <_2clist
  28241.   name="See Also:"
  28242.   description="<a href=\"lib_e_g.htm#get_active_page\">get_active_page</a>,
  28243. <a href=\"lib_s_t.htm#set_display_page\">set_display_page</a>,
  28244. <a href=\"lib_u_z.htm#video_config\">video_config</a>"
  28245.  >
  28246. </table>
  28247.  
  28248.  
  28249. <_routine name="set_display_page">
  28250. <table border=0 cellspacing=2 cellpadding=2>
  28251.  
  28252.  
  28253.  <_2clist
  28254.   name="Platform:"
  28255.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  28256.  >
  28257.  
  28258.  <_2clist
  28259.   name="Syntax:"
  28260.   description="<font face = \"Arial, Helvetica\"> include image.e<BR>
  28261.  set_display_page(i)
  28262. </font>"
  28263.  >
  28264.  <_2clist
  28265.   name="Description:"
  28266.   description=
  28267. "Set video page i to be mapped to the visible screen."
  28268.  >
  28269. <_2clist
  28270.   name="Comments:"
  28271.   description=
  28272. "With multiple pages you can instantaneously change the entire
  28273.  screen without causing any visible \"flicker\". You can also
  28274.  save the screen and bring it back quickly.
  28275. <P>
  28276. video_config() will tell you how many pages are available in
  28277.  the current graphics mode.
  28278. <P>
  28279. By default, the active page and the display page are both 0.
  28280. <P>
  28281. This works under DOS, or in a full-screen DOS window. In a
  28282.  partial-screen window you cannot change the active page."
  28283.  >
  28284. <_2clist
  28285.   name="Example:"
  28286.   description="See set_active_page() example."
  28287.  >
  28288.  
  28289. <_2clist
  28290.   name="See Also:"
  28291.   description="<a href=\"lib_e_g.htm#get_display_page\">get_display_page</a>,
  28292. <a href=\"lib_s_t.htm#set_active_page\">set_active_page</a>,
  28293. <a href=\"lib_u_z.htm#video_config\">video_config</a>"
  28294.  >
  28295. </table>
  28296.  
  28297.  
  28298. <_routine name="set_rand">
  28299. <table border=0 cellspacing=2 cellpadding=2>
  28300.  
  28301.  
  28302.  <_2clist
  28303.   name="Syntax:"
  28304.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  28305.  set_rand(i1)
  28306. </font>"
  28307.  >
  28308.  <_2clist
  28309.   name="Description:"
  28310.   description=
  28311. "Set the random number generator to a certain state, i1, so that
  28312.  you will get a known series of random numbers on subsequent
  28313.  calls to rand()."
  28314.  >
  28315. <_2clist
  28316.   name="Comments:"
  28317.   description=
  28318. "Normally the numbers returned by the rand() function are totally
  28319.  unpredictable, and will be different each time you run your
  28320.  program. Sometimes however you may wish to repeat the same
  28321.  series of numbers, perhaps because you are trying to debug
  28322.  your program, or maybe you want the ability to generate the
  28323.  same output (e.g. a random picture) for your user upon request."
  28324.  >
  28325. <_2clist
  28326.   name="Example:"
  28327.   description=""
  28328.  >
  28329. <_eucode>
  28330. sequence s, t
  28331. s = repeat(0, 3)
  28332. t = s
  28333.  
  28334. set_rand(12345)
  28335. s[1] = rand(10)
  28336. s[2] = rand(100)
  28337. s[3] = rand(1000)
  28338.  
  28339. set_rand(12345)  -- same value for set_rand()
  28340. t[1] = rand(10)  -- same arguments to rand() as before
  28341. t[2] = rand(100)
  28342. t[3] = rand(1000)
  28343. -- at this point s and t will be identical
  28344.  
  28345.  </_eucode>
  28346. <_2clist
  28347.   name="See Also:"
  28348.   description="<a href=\"lib_p_r.htm#rand\">rand</a>"
  28349.  >
  28350. </table>
  28351.  
  28352.  
  28353. <_routine name="set_vector">
  28354. <table border=0 cellspacing=2 cellpadding=2>
  28355.  
  28356.  
  28357.  <_2clist
  28358.   name="Platform:"
  28359.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  28360.  >
  28361.  
  28362.  <_2clist
  28363.   name="Syntax:"
  28364.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  28365.  set_vector(i, s)
  28366. </font>"
  28367.  >
  28368.  <_2clist
  28369.   name="Description:"
  28370.   description=
  28371. "Set s as the new address for handling interrupt number i.
  28372.  s must be a protected mode <b>far address</b> in the form:
  28373.  {16-bit segment, 32-bit offset}. "
  28374.  >
  28375. <_2clist
  28376.   name="Comments:"
  28377.   description=
  28378. "Before calling set_vector() you must store a machine-code
  28379.  interrupt handling routine at location s in memory.
  28380. <P>
  28381. The 16-bit segment can be the code segment used by Euphoria.
  28382.  To get the value of this segment see
  28383.  <font color=\"#5500FF\"><b>demo\dos32\hardint.ex</b></font>.
  28384.  The offset can be the 32-bit value returned by allocate().
  28385.  Euphoria runs in <b>protected mode</b> with the code segment
  28386.  and data segment pointing to the same physical memory,
  28387.  but with different access modes.
  28388. <P>
  28389. Interrupts occurring in either <b>real mode</b> or <b>protected mode</b>
  28390.  will be passed to your handler. Your interrupt handler
  28391.  should immediately load the correct data segment before it
  28392.  tries to reference memory.
  28393. <P>
  28394. Your handler might return from the interrupt using the
  28395.  iretd instruction, or jump to the original interrupt handler.
  28396.  It should save and restore any registers that it modifies.
  28397. <P>
  28398. You should lock the memory used by your handler to ensure
  28399.  that it will never be swapped out. See lock_memory().
  28400. <P>
  28401. It is highly recommended that you study
  28402.  <font color=\"#5500FF\"><b>demo\dos32\hardint.ex</b></font>
  28403.  before trying to set up your own interrupt handler.
  28404. <P>
  28405. You should have a good knowledge of machine-level programming
  28406.  before attempting to write your own handler.
  28407. <P>
  28408. You can call set_vector() with the far address returned by
  28409.  get_vector(), when you want to restore the original handler."
  28410.  >
  28411. <_2clist
  28412.   name="Example:"
  28413.   description=""
  28414.  >
  28415. <_eucode>
  28416. set_vector(#1C, {code_segment, my_handler_address})
  28417.  
  28418.  </_eucode>
  28419. <_2clist
  28420.   name="Example Program:"
  28421.   description="<font color=\"#5500FF\"><b>demo\dos32\hardint.ex</b></font>"
  28422.  >
  28423.  
  28424.  <_2clist
  28425.   name="See Also:"
  28426.   description="<a href=\"lib_e_g.htm#get_vector\">get_vector</a>,
  28427. <a href=\"lib_h_o.htm#lock_memory\">lock_memory</a>,
  28428. <a href=\"lib_a_b.htm#allocate\">allocate</a>"
  28429.  >
  28430. </table>
  28431.  
  28432.  
  28433. <_routine name="sin">
  28434. <table border=0 cellspacing=2 cellpadding=2>
  28435.  
  28436.  
  28437.  <_2clist
  28438.   name="Syntax:"
  28439.   description="<font face = \"Arial, Helvetica\"> x2 = sin(x1)
  28440. </font>"
  28441.  >
  28442.  <_2clist
  28443.   name="Description:"
  28444.   description=
  28445. "Return the sine of x1, where x1 is in radians."
  28446.  >
  28447. <_2clist
  28448.   name="Comments:"
  28449.   description=
  28450. "This function may be applied to an atom or to all elements of a sequence."
  28451.  >
  28452. <_2clist
  28453.   name="Example:"
  28454.   description=""
  28455.  >
  28456. <_eucode>
  28457. sin_x = sin({.5, .9, .11})
  28458. -- sin_x is {.479, .783, .110}
  28459.  
  28460.  </_eucode>
  28461. <_2clist
  28462.   name="See Also:"
  28463.   description="<a href=\"lib_c_d.htm#cos\">cos</a>,
  28464. <a href=\"lib_s_t.htm#tan\">tan</a>"
  28465.  >
  28466. </table>
  28467.  
  28468.  
  28469. <_routine name="sleep">
  28470. <table border=0 cellspacing=2 cellpadding=2>
  28471.  
  28472.  
  28473.  <_2clist
  28474.   name="Syntax:"
  28475.   description="<font face = \"Arial, Helvetica\">include misc.e<BR>
  28476.   sleep(i)
  28477. </font>"
  28478.  >
  28479.  <_2clist
  28480.   name="Description:"
  28481.   description=
  28482. "Suspend execution for i seconds." 
  28483.  >
  28484. <_2clist
  28485.   name="Comments:"
  28486.   description=
  28487. "On WIN32 and Linux, the operating
  28488.  system will suspend your process and schedule other processes. 
  28489.  On DOS32, your program will go into a busy loop
  28490.   for i seconds, during which time other processes may run, but 
  28491.   they will compete with your process for the CPU."
  28492.  >
  28493. <_2clist
  28494.   name="Example:"
  28495.   description=""
  28496.  >
  28497. <_eucode>
  28498. puts(1, "Waiting 15 seconds...\n")
  28499. sleep(15)
  28500. puts(1, "Done.\n")
  28501. </_eucode>
  28502. <_2clist
  28503.   name="See Also:"
  28504.   description="<a href=\"lib_h_o.htm#lock_file\">lock_file</a>,
  28505. <a href=\"lib_a_b.htm#abort\">abort</a>,
  28506. <a href=\"lib_s_t.htm#time\">time</a>"
  28507.  >
  28508. </table>
  28509.  
  28510.  
  28511. <_routine name="sort">
  28512. <table border=0 cellspacing=2 cellpadding=2>
  28513.  
  28514.  
  28515.  <_2clist
  28516.   name="Syntax:"
  28517.   description="<font face = \"Arial, Helvetica\"> include sort.e<BR>
  28518.  s2 = sort(s1)
  28519. </font>"
  28520.  >
  28521.  <_2clist
  28522.   name="Description:"
  28523.   description=
  28524. "Sort s1 into ascending order using a fast sorting algorithm. The
  28525.  elements of s1 can be any mix of atoms or sequences. Atoms come
  28526.  before sequences, and sequences are sorted \"alphabetically\" where
  28527.  the first elements are more significant than the later elements."
  28528.  >
  28529. <_2clist
  28530.   name="Example 1:"
  28531.   description=""
  28532.  >
  28533. <_eucode>
  28534. x = 0 & sort({7,5,3,8}) & 0
  28535. -- x is set to {0, 3, 5, 7, 8, 0}
  28536.  
  28537.  </_eucode>
  28538. <_2clist
  28539.   name="Example 2:"
  28540.   description=""
  28541.  >
  28542. <_eucode>
  28543. y = sort({"Smith", "Jones", "Doe", 5.5, 4, 6})
  28544. -- y is {4, 5.5, 6, "Doe", "Jones", "Smith"}
  28545.  
  28546.  </_eucode>
  28547. <_2clist
  28548.   name="Example 3:"
  28549.   description=""
  28550.  >
  28551. <_eucode>
  28552. database = sort({{"Smith",   95.0, 29},
  28553.                  {"Jones",   77.2, 31},
  28554.                  {"Clinton", 88.7, 44}})
  28555.  
  28556. -- The 3 database "records" will be sorted by the first "field"
  28557. -- i.e. by name. Where the first field (element) is equal it
  28558. -- will be sorted by the second field etc.
  28559.  
  28560. -- after sorting, database is:
  28561.                {{"Clinton", 88.7, 44},
  28562.                 {"Jones",   77.2, 31},
  28563.                 {"Smith",   95.0, 29}}
  28564.  
  28565.  </_eucode>
  28566. <_2clist
  28567.   name="See Also:"
  28568.   description="<a href=\"lib_c_d.htm#custom_sort\">custom_sort</a>,
  28569.     <a href=\"lib_c_d.htm#compare\">compare</a>,
  28570.     <a href=\"lib_h_o.htm#match\">match</a>,
  28571.     <a href=\"lib_e_g.htm#find\">find</a>"
  28572.  >
  28573. </table>
  28574.  
  28575.  
  28576. <_routine name="sound">
  28577. <table border=0 cellspacing=2 cellpadding=2>
  28578.  
  28579.  
  28580.  <_2clist
  28581.   name="Platform:"
  28582.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  28583.  >
  28584.  
  28585.  <_2clist
  28586.   name="Syntax:"
  28587.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  28588.  sound(i)
  28589. </font>"
  28590.  >
  28591.  <_2clist
  28592.   name="Description:"
  28593.   description=
  28594. "Turn on the PC speaker at frequency i. If i is 0 the speaker
  28595.  will be turned off."
  28596.  >
  28597. <_2clist
  28598.   name="Comments:"
  28599.   description=
  28600. "On <font color=\"#CC3366\"><b>WIN32</b></font> and 
  28601.      <font color=\"#CC3366\"><b>Linux</b></font> 
  28602. no sound will be made."
  28603.  >
  28604. <_2clist
  28605.   name="Example:"
  28606.   description=""
  28607.  >
  28608. <_eucode>
  28609. sound(1000) -- starts a fairly high pitched sound
  28610.  
  28611. </_eucode>
  28612. </table>
  28613.  
  28614.  
  28615. <_routine name="sprint">
  28616. <table border=0 cellspacing=2 cellpadding=2>
  28617.  
  28618.  
  28619.  <_2clist
  28620.   name="Syntax:"
  28621.   description="<font face = \"Arial, Helvetica\"> include misc.e<BR>
  28622.  s = sprint(x)
  28623. </font>"
  28624.  >
  28625.  <_2clist
  28626.   name="Description:"
  28627.   description=
  28628. "The representation of x as a string of characters is returned.
  28629.  This is exactly the same as <b>print(fn, x)</b>, except that the output
  28630.  is returned as a sequence of characters, rather than being
  28631.  sent to a file or device. x can be any Euphoria object."
  28632.  >
  28633. <_2clist
  28634.   name="Comments:"
  28635.   description=
  28636. "The atoms contained within x will be displayed to a maximum of
  28637.  10 significant digits, just as with print()."
  28638.  >
  28639. <_2clist
  28640.   name="Example 1:"
  28641.   description=""
  28642.  >
  28643. <_eucode>
  28644. s = sprint(12345)
  28645. -- s is "12345"
  28646.  
  28647.  </_eucode>
  28648. <_2clist
  28649.   name="Example 2:"
  28650.   description=""
  28651.  >
  28652. <_eucode>
  28653. s = sprint({10,20,30}+5)
  28654. -- s is "{15,25,35}"
  28655.  
  28656.  </_eucode>
  28657. <_2clist
  28658.   name="See Also:"
  28659.   description="<a href=\"lib_p_r.htm#print\">print</a>,
  28660. <a href=\"lib_s_t.htm#sprintf\">sprintf</a>,
  28661. <a href=\"lib_u_z.htm#value\">value</a>,
  28662. <a href=\"lib_e_g.htm#get\">get</a>"
  28663.  >
  28664. </table>
  28665.  
  28666.  
  28667. <_routine name="sprintf">
  28668. <table border=0 cellspacing=2 cellpadding=2>
  28669.  
  28670.  
  28671.  <_2clist
  28672.   name="Syntax:"
  28673.   description="<font face = \"Arial, Helvetica\"> s = sprintf(st, x)
  28674. </font>"
  28675.  >
  28676.  <_2clist
  28677.   name="Description:"
  28678.   description=
  28679. "This is exactly the same as <b>printf()</b>, except that the output
  28680.  is returned as a sequence of characters, rather than being
  28681.  sent to a file or device. st is a format string, x is the
  28682.  value or sequence of values to be formatted. <b>printf(fn, st, x)</b>
  28683.  is equivalent to <b>puts(fn, sprintf(st, x))</b>."
  28684.  >
  28685. <_2clist
  28686.   name="Comments:"
  28687.   description=
  28688. "Some typical uses of sprintf() are:
  28689. <P>
  28690.  1. Converting numbers to strings.<BR>
  28691.  2. Creating strings to pass to system().<BR>
  28692.  3. Creating formatted error messages that can be passed to
  28693.     a common error message handler."
  28694.  >
  28695. <_2clist
  28696.   name="Example:"
  28697.   description=""
  28698.  >
  28699. <_eucode>
  28700. s = sprintf("%08d", 12345)
  28701. -- s is "00012345"
  28702.  
  28703.  </_eucode>
  28704. <_2clist
  28705.   name="See Also:"
  28706.   description="<a href=\"lib_p_r.htm#printf\">printf</a>,
  28707. <a href=\"lib_u_z.htm#value\">value</a>,
  28708. <a href=\"lib_s_t.htm#sprint\">sprint</a>,
  28709. <a href=\"lib_e_g.htm#get\">get</a>,
  28710. <a href=\"lib_s_t.htm#system\">system</a>"
  28711.  >
  28712. </table>
  28713.  
  28714.  
  28715. <_routine name="sqrt">
  28716. <table border=0 cellspacing=2 cellpadding=2>
  28717.  
  28718.  
  28719.  <_2clist
  28720.   name="Syntax:"
  28721.   description="<font face = \"Arial, Helvetica\"> x2 = sqrt(x1)
  28722. </font>"
  28723.  >
  28724.  <_2clist
  28725.   name="Description:"
  28726.   description=
  28727. "Calculate the square root of x1. "
  28728.  >
  28729. <_2clist
  28730.   name="Comments:"
  28731.   description=
  28732. "This function may be applied to an atom or to all elements
  28733.  of a sequence.
  28734. <P>
  28735. Taking the square root of a negative number will abort your
  28736.  program with a run-time error message."
  28737.  >
  28738. <_2clist
  28739.   name="Example:"
  28740.   description=""
  28741.  >
  28742. <_eucode>
  28743. r = sqrt(16)
  28744. -- r is 4
  28745.  
  28746.  </_eucode>
  28747. <_2clist
  28748.   name="See Also:"
  28749.   description="<a href=\"lib_h_o.htm#log\">log</a>,
  28750. <a href=\"lib_p_r.htm#power\">power</a>"
  28751.  >
  28752. </table>
  28753.  
  28754.  
  28755. <_routine name="system">
  28756. <table border=0 cellspacing=2 cellpadding=2>
  28757.  
  28758.  
  28759.  <_2clist
  28760.   name="Syntax:"
  28761.   description="<font face = \"Arial, Helvetica\"> system(st, i)
  28762. </font>"
  28763.  >
  28764.  <_2clist
  28765.   name="Description:"
  28766.   description=
  28767. "Pass a command string st to the operating system command interpreter.
  28768.  The argument i indicates the manner in which to
  28769.  return from the call to system():<P>
  28770. When i is 0, the previous graphics mode is restored and the
  28771.  screen is cleared.
  28772. <P>
  28773. When i is 1, a beep sound will be made and the program will wait
  28774.  for the user to press a key before the previous graphics mode
  28775.  is restored.
  28776. <P>
  28777. When i is 2, the graphics mode is not restored and the screen
  28778.  is not cleared."
  28779.  >
  28780. <_2clist
  28781.   name="Comments:"
  28782.   description=
  28783. "i = 2 should only be used when it is known that the command executed by
  28784.  system() will not change the graphics mode.
  28785. <P>
  28786. You can use Euphoria as a sophisticated \"batch\" (.bat) language
  28787.  by making calls to system() and system_exec().
  28788. <P>
  28789. system() will start a new DOS or Linux shell.
  28790. <P>
  28791. system() allows you to use command-line redirection of standard
  28792.  input and output in the command string st.
  28793. <P>
  28794. Under <font color=\"#CC3366\"><b>DOS32</b></font>, a Euphoria program
  28795.  will start off using extended
  28796.  memory. If extended memory runs out the program will consume
  28797.  conventional memory. If conventional memory runs out it will use
  28798.  virtual memory, i.e. swap space on disk. The DOS command run by
  28799.  system() will fail if there is not enough conventional memory
  28800.  available. To avoid this situation you can reserve some
  28801.  conventional (low) memory by typing:"
  28802.  >
  28803. <_eucode>
  28804.     SET CAUSEWAY=LOWMEM:xxx
  28805. </_eucode>
  28806.  
  28807. <_2clist
  28808.   name=""
  28809.   description=
  28810. "where xxx is the number of K of conventional memory to reserve. Type this
  28811.  before running your program. You can also put this in <b>autoexec.bat</b>,
  28812.  or in a <b>.bat</b> file that runs your program. For example:"
  28813.  >
  28814.  
  28815. <_eucode>
  28816.     SET CAUSEWAY=LOWMEM:80
  28817.     ex myprog.ex
  28818. </_eucode>
  28819.  
  28820. <_2clist
  28821.   name=""
  28822.   description=
  28823. "This will reserve 80K of conventional memory, which should be
  28824.  enough to run simple DOS commands like COPY, MOVE, MKDIR etc."
  28825.  >
  28826. <_2clist
  28827.   name="Example 1:"
  28828.   description=""
  28829.  >
  28830. <_eucode>
  28831. system("copy temp.txt a:\\temp.bak", 2)
  28832. -- note use of double backslash in literal string to get
  28833. -- single backslash
  28834.  
  28835.  </_eucode>
  28836. <_2clist
  28837.   name="Example 2:"
  28838.   description=""
  28839.  >
  28840. <_eucode>
  28841. system("ex \\test\\myprog.ex < indata > outdata", 2)
  28842. -- executes myprog by redirecting standard input and
  28843. -- standard output
  28844.  
  28845.  </_eucode>
  28846. <_2clist
  28847.   name="Example Program:"
  28848.   description="<font color=\"#5500FF\"><b>bin\install.ex</b></font>"
  28849.  >
  28850.  
  28851.  <_2clist
  28852.   name="See Also:"
  28853.   description="<a href=\"lib_s_t.htm#system_exec\">system_exec</a>,
  28854. <a href=\"lib_c_d.htm#dir\">dir</a>,
  28855. <a href=\"lib_c_d.htm#current_dir\">current_dir</a>,
  28856. <a href=\"lib_e_g.htm#getenv\">getenv</a>,
  28857. <a href=\"lib_c_d.htm#command_line\">command_line</a>"
  28858.  >
  28859. </table>
  28860.  
  28861.  
  28862. <_routine name="system_exec">
  28863. <table border=0 cellspacing=2 cellpadding=2>
  28864.  
  28865.  
  28866.  <_2clist
  28867.   name="Syntax:"
  28868.   description="<font face = \"Arial, Helvetica\"> i1 = system_exec(st, i2)
  28869. </font>"
  28870.  >
  28871.  <_2clist
  28872.   name="Description:"
  28873.   description=
  28874. "Try to run the command given by st. st must be a command to run an
  28875.  executable program, 
  28876.  possibly with some command-line arguments.
  28877.  If the program can be run, i1 will be the exit code from the
  28878.  program. If it is not possible to run the program, system_exec()
  28879.  will return -1. i2 is a code that indicates what to do about the
  28880.  graphics mode when system_exec() is finished. These codes are
  28881.  the same as for system():<P>
  28882. When i2 is 0, the previous graphics mode is restored and the
  28883.  screen is cleared.
  28884. <P>
  28885. When i2 is 1, a beep sound will be made and the program will wait
  28886.  for the user to press a key before the previous graphics mode
  28887.  is restored.
  28888. <P>
  28889. When i2 is 2, the graphics mode is not restored and the screen
  28890.  is not cleared."
  28891.  >
  28892. <_2clist
  28893.   name="Comments:"
  28894.   description=
  28895. "On DOS32 or WIN32, system_exec() will only run <b>.exe</b> and <b>.com</b> 
  28896.  programs. To run
  28897.  <b>.bat</b> files, or built-in DOS commands, you need system().
  28898.  Some commands, such as DEL, are not programs, they are
  28899.  actually built-in to the command interpreter.
  28900. <P>
  28901. system_exec() does not allow the use of command-line redirection
  28902.  in the command string st.
  28903. <P>
  28904. exit codes from DOS or Windows programs are normally in the
  28905.  range 0 to 255, with 0 indicating \"success\".
  28906. <P>
  28907. You can run a Euphoria program using system_exec(). A Euphoria
  28908.  program can return an exit code using abort().
  28909. <P>
  28910. system_exec() does not start a new DOS shell."
  28911.  >
  28912. <_2clist
  28913.   name="Example 1:"
  28914.   description=""
  28915.  >
  28916. <_eucode>
  28917. integer exit_code
  28918. exit_code = system_exec("xcopy temp1.dat temp2.dat", 2)
  28919.  
  28920. if exit_code = -1 then
  28921.     puts(2, "\n couldn't run xcopy.exe\n")
  28922. elsif exit_code = 0 then
  28923.     puts(2, "\n xcopy succeeded\n")
  28924. else
  28925.     printf(2, "\n xcopy failed with code %d\n", exit_code)
  28926. end if
  28927.  
  28928.  </_eucode>
  28929. <_2clist
  28930.   name="Example 2:"
  28931.   description=""
  28932.  >
  28933. <_eucode>
  28934. -- executes myprog with two file names as arguments
  28935. if system_exec("ex \\test\\myprog.ex indata outdata", 2) then
  28936.     puts(2, "failure!\n")
  28937. end if
  28938.  
  28939.  </_eucode>
  28940. <_2clist
  28941.   name="See Also:"
  28942.   description="<a href=\"lib_s_t.htm#system\">system</a>,
  28943. <a href=\"lib_a_b.htm#abort\">abort</a>"
  28944.  >
  28945. </table>
  28946.  
  28947.  
  28948. <_routine name="tan">
  28949. <table border=0 cellspacing=2 cellpadding=2>
  28950.  
  28951.  
  28952.  <_2clist
  28953.   name="Syntax:"
  28954.   description="<font face = \"Arial, Helvetica\"> x2 = tan(x1)
  28955. </font>"
  28956.  >
  28957.  <_2clist
  28958.   name="Description:"
  28959.   description=
  28960. "Return the tangent of x1, where x1 is in radians."
  28961.  >
  28962. <_2clist
  28963.   name="Comments:"
  28964.   description=
  28965. "This function may be applied to an atom or to all elements
  28966.  of a sequence."
  28967.  >
  28968. <_2clist
  28969.   name="Example:"
  28970.   description=""
  28971.  >
  28972. <_eucode>
  28973. t = tan(1.0)
  28974. -- t is 1.55741
  28975.  
  28976.  </_eucode>
  28977. <_2clist
  28978.   name="See Also:"
  28979.   description="<a href=\"lib_s_t.htm#sin\">sin</a>,
  28980. <a href=\"lib_c_d.htm#cos\">cos</a>,
  28981. <a href=\"lib_a_b.htm#arctan\">arctan</a>"
  28982.  >
  28983. </table>
  28984.  
  28985.  
  28986. <_routine name="text_color">
  28987. <table border=0 cellspacing=2 cellpadding=2>
  28988.  
  28989.  
  28990.  <_2clist
  28991.   name="Syntax:"
  28992.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  28993.  text_color(i)
  28994. </font>"
  28995.  >
  28996.  <_2clist
  28997.   name="Description:"
  28998.   description=
  28999. "Set the foreground text color. Add 16 to get blinking text in some modes.
  29000.  See <font color=\"#5500FF\"><b>graphics.e</b></font> for a list
  29001.  of possible colors."
  29002.  >
  29003. <_2clist
  29004.   name="Comments:"
  29005.   description=
  29006. "Text that you print <b><i>after</i></b> calling text_color() will have the
  29007.  desired color.
  29008. <P>
  29009. When your program terminates, the last color that you selected
  29010.  and actually printed on the screen will remain in effect.
  29011.  Thus you may have to print something, maybe just '\n', in
  29012.  WHITE to restore white text, especially if you are at the
  29013.  bottom line of the screen, ready to scroll up."
  29014.  >
  29015. <_2clist
  29016.   name="Example:"
  29017.   description=""
  29018.  >
  29019. <_eucode>
  29020. text_color(BRIGHT_BLUE)
  29021.  
  29022.  </_eucode>
  29023. <_2clist
  29024.   name="See Also:"
  29025.   description="<a href=\"lib_a_b.htm#bk_color\">bk_color</a>"
  29026.  >
  29027. </table>
  29028.  
  29029.  
  29030. <_routine name="text_rows">
  29031. <table border=0 cellspacing=2 cellpadding=2>
  29032.  
  29033.  
  29034.  <_2clist
  29035.   name="Platform:"
  29036.   description="<font color=\"#CC3366\"><b>DOS32, WIN32</b></font>"
  29037.  >
  29038.  <_2clist
  29039.   name="Syntax:"
  29040.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  29041.  i2 = text_rows(i1)
  29042. </font>"
  29043.  >
  29044.  <_2clist
  29045.   name="Description:"
  29046.   description=
  29047. "Set the number of lines on a <font color=\"#CC3366\">text-mode</font> screen
  29048.  to i1 if possible. i2 will be set to the actual new number of lines."
  29049.  >
  29050. <_2clist
  29051.   name="Comments:"
  29052.   description=
  29053. "Values of 25, 28, 43 and 50 lines are supported by most video
  29054.  cards."
  29055.  >
  29056. <_2clist
  29057.   name="See Also:"
  29058.   description="<a href=\"lib_e_g.htm#graphics_mode\">graphics_mode</a>"
  29059.  >
  29060. </table>
  29061.  
  29062.  
  29063. <_routine name="tick_rate">
  29064. <table border=0 cellspacing=2 cellpadding=2>
  29065.  
  29066.  
  29067.  <_2clist
  29068.   name="Platform:"
  29069.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  29070.  >
  29071.  <_2clist
  29072.   name="Syntax:"
  29073.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  29074.  tick_rate(a)
  29075. </font>"
  29076.  >
  29077.  <_2clist
  29078.   name="Description:"
  29079.   description=
  29080. "Specify the number of clock-tick interrupts per second.
  29081.  This determines the precision of the time() library
  29082.  routine. It also affects the sampling rate for time
  29083.  profiling."
  29084.  >
  29085. <_2clist
  29086.   name="Comments:"
  29087.   description=
  29088. "tick_rate() is ignored on 
  29089.    <font color=\"#CC3366\"><b>WIN32</b></font> and
  29090.    <font color=\"#CC3366\"><b>Linux</b></font>.
  29091.  The time resolution on WIN32 is always 100 ticks/second.
  29092. <P>
  29093. On a PC the clock-tick interrupt normally occurs at 18.2
  29094.  interrupts per second. tick_rate() lets you increase
  29095.  that rate, but not decrease it.
  29096. <P>
  29097. tick_rate(0) will restore the rate to the normal 18.2 rate.
  29098.  Euphoria will also restore the rate automatically when it exits,
  29099.  even when it finds an error in your program.
  29100. <P>
  29101. If a program runs in a DOS window with a tick rate other
  29102.  than 18.2, the time() function will not advance unless the
  29103.  window is the active window.
  29104. <P>
  29105. While <font color=\"#993333\"><b>ex.exe</b></font> is running,
  29106.  the system will maintain the correct time of day. However if
  29107.  <font color=\"#993333\"><b>ex.exe</b></font> should crash (e.g. you see
  29108.  a \"CauseWay...\" error) while the tick rate is high, you (or
  29109.  your user) may need to reboot the machine to restore the
  29110.  proper rate. If you don't, the system time may advance too
  29111.  quickly. This problem does not occur on
  29112.  <font color=\"#CC3366\"><b>Windows 95/98/NT</b></font>, only on
  29113.  <font color=\"#CC3366\"><b>DOS</b></font> or
  29114.  <font color=\"#CC3366\"><b>Windows 3.1</b></font>. You will always get
  29115.  back the correct time of day from the battery-operated clock in your
  29116.  system when you boot up again."
  29117.  >
  29118. <_2clist
  29119.   name="Example:"
  29120.   description=""
  29121.  >
  29122. <_eucode>
  29123. tick_rate(100)
  29124. -- time() will now advance in steps of .01 seconds
  29125. -- instead of the usual .055 seconds
  29126.  
  29127.  </_eucode>
  29128. <_2clist
  29129.   name="See Also:"
  29130.   description="<a href=\"lib_s_t.htm#time\">time</a>,
  29131. <a href=\"refman_3.htm#21\">time profiling</a>"
  29132.  >
  29133. </table>
  29134.  
  29135.  
  29136. <_routine name="time">
  29137. <table border=0 cellspacing=2 cellpadding=2>
  29138.  
  29139.  
  29140.  <_2clist
  29141.   name="Syntax:"
  29142.   description="<font face = \"Arial, Helvetica\"> a = time()
  29143. </font>"
  29144.  >
  29145.  <_2clist
  29146.   name="Description:"
  29147.   description=
  29148. "Return the number of seconds since some fixed point in the past."
  29149.  >
  29150. <_2clist
  29151.   name="Comments:"
  29152.   description=
  29153. "Take the difference between two readings of time(), to
  29154.  measure, for example, how long a section of code takes to
  29155.  execute.
  29156. <P>
  29157. The resolution with <font color=\"#CC3366\"><b>DOS32</b></font> is normally
  29158.  about 0.05 seconds. On <font color=\"#CC3366\"><b>WIN32 and Linux</b></font> 
  29159.  it's about 0.01 seconds.
  29160. <P>
  29161. Under <font color=\"#CC3366\"><b>DOS32</b></font> you can improve
  29162.  the resolution by calling tick_rate().
  29163. <P>
  29164. Under <font color=\"#CC3366\"><b>DOS32</b></font> the period of time that 
  29165. you can measure is limited to 24 hours. After that, the value returned 
  29166. by time() will reset and start over."
  29167.  >
  29168. <_2clist
  29169.   name="Example:"
  29170.   description=""
  29171.  >
  29172. <_eucode>
  29173. constant ITERATIONS = 1000000
  29174. integer p
  29175. atom t0, loop_overhead
  29176.  
  29177. t0 = time()
  29178. for i = 1 to ITERATIONS do
  29179.     -- time an empty loop
  29180. end for
  29181. loop_overhead = time() - t0
  29182.  
  29183. t0 = time()
  29184. for i = 1 to ITERATIONS do
  29185.     p = power(2, 20)
  29186. end for
  29187. ? (time() - t0 - loop_overhead)/ITERATIONS
  29188. -- calculates time (in seconds) for one call to power
  29189.  
  29190.  </_eucode>
  29191. <_2clist
  29192.   name="See Also:"
  29193.   description="<a href=\"lib_c_d.htm#date\">date</a>,
  29194. <a href=\"lib_s_t.htm#tick_rate\">tick_rate</a>"
  29195.  >
  29196. </table>
  29197.  
  29198.  
  29199. <_routine name="trace">
  29200. <table border=0 cellspacing=2 cellpadding=2>
  29201.  
  29202.  
  29203.  <_2clist
  29204.   name="Syntax:"
  29205.   description="<font face = \"Arial, Helvetica\"> with trace<BR>
  29206.  trace(i)
  29207. </font>"
  29208.  >
  29209.  <_2clist
  29210.   name="Description:"
  29211.   description=
  29212. "If i is 1 or 2, turn on full-screen statement tracing. If i
  29213.  is 0, turn off tracing. When i is 2 a monochrome trace display
  29214.  is used. Tracing can only occur in routines that were
  29215.  compiled \"<b>with trace</b>\". trace() has no effect unless it is
  29216.  executed in a \"<b>with trace</b>\" <b>section</b> of your program. See
  29217.  <a href=\"refman_3.htm#1\">Part I - 3.1 Debugging</a> for more details."
  29218.  >
  29219. <_2clist
  29220.   name="Comments:"
  29221.   description=
  29222. "Use trace(2) if the color display is hard to view on your system."
  29223.  >
  29224. <_2clist
  29225.   name="Example:"
  29226.   description=""
  29227.  >
  29228. <_eucode>
  29229. if x < 0 then
  29230.     -- ok, here's the case I want to debug...
  29231.     trace(1)
  29232.     -- etc.
  29233.     ...
  29234. end if
  29235.  
  29236.  </_eucode>
  29237. <_2clist
  29238.   name="See Also:"
  29239.   description="<a href=\"lib_p_r.htm#profile\">profile</a>,
  29240.                <a href=\"refman_3.htm\">debugging and profiling</a>"
  29241.  >
  29242. </table>
  29243.  
  29244. <_continue
  29245.   href="lib_u_z.htm"
  29246.   name="From U to Z"
  29247. >
  29248.  
  29249. </body>
  29250. </html>
  29251. LIB_U_Z.HTX
  29252. 18181
  29253. <_init_comment>
  29254. <html>
  29255. <head><title>Euphoria v2.2 Reference Manual Part II - Section 3</title>
  29256. </head>
  29257. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  29258. <br>
  29259.  
  29260. <_routine name="unlock_file">
  29261. <table border=0 cellspacing=2 cellpadding=2>
  29262.  
  29263. <_2clist
  29264.  name="Syntax:"
  29265.  description="<font face=\"Arial, Helvetica\"> include file.e<BR>
  29266.  unlock_file(fn, s)</font>"
  29267. >
  29268. <_2clist
  29269.  name="Description:"
  29270.  description="Unlock an open file fn, or a portion of file fn. 
  29271.  You must have previously locked the file using lock_file(). 
  29272.  On DOS32 and WIN32 you can unlock a range of bytes within a file by
  29273.  specifying the s parameter as {first_byte, last_byte}.
  29274.  The same range of bytes must have been locked by a previous call 
  29275.  to lock_file(). On Linux
  29276.  you can currently only lock or unlock an entire file. The s
  29277.  parameter should be {} when you want to unlock an entire file. On Linux,
  29278.  s must always be {}." 
  29279. >
  29280. <_2clist
  29281.   name="Comments:"
  29282.   description="
  29283.   You should unlock a file as soon as possible so other processes 
  29284.   can use it."
  29285. >  
  29286. <_2clist
  29287.  name=""
  29288.  description="Any files that you have 
  29289.   locked, will automatically be unlocked when your program terminates."
  29290. >
  29291. <_2clist
  29292.  name=""
  29293.  description="See lock_file() for further comments and an example."
  29294. >
  29295. <_2clist
  29296.   name="See Also:"
  29297.   description="<a href=\"lib_h_o.htm#lock_file\">lock_file</a>"
  29298. >
  29299. </table>
  29300.  
  29301. <_routine name="unregister_block">
  29302. <table border=0 cellspacing=2 cellpadding=2>
  29303.  
  29304. <_2clist
  29305.  name="Syntax:"
  29306.  description="<font face=\"Arial, Helvetica\"> include machine.e (or safe.e)<BR>
  29307.  unregister_block(a)</font>"
  29308. >
  29309. <_2clist
  29310.  name="Description:"
  29311.  description="Remove a block of memory from the list of safe blocks maintained
  29312.  by <font color=\"#5500FF\"><b>safe.e</b></font> (the debug version of
  29313.  <font color=\"#5500FF\"><b>machine.e</b></font>). The block starts at
  29314.  address a."
  29315. >
  29316. <_2clist
  29317.   name="Comments:"
  29318.   description="This routine is only meant to be used for <b>debugging
  29319.   purposes</b>. Use it to unregister blocks of memory that you have
  29320.   previously registered using register_block(). By unregistering a block,
  29321.   you remove it from the list of safe blocks maintained by
  29322.   <font color=\"#5500FF\"><b>safe.e</b></font>. This prevents your program
  29323.   from performing any further reads or writes of memory within the block."
  29324. >  
  29325. <_2clist
  29326.  name=""
  29327.  description="See register_block() for further comments and an example."
  29328. >
  29329. <_2clist
  29330.   name="See Also:"
  29331.   description="<a href=\"lib_p_r.htm#register_block\">register_block</a>,
  29332.  <a href=\"library.htm#safe\"><font color=\"#5500FF\"><b>safe.e</b></font></a>"
  29333. >
  29334. </table>
  29335.   
  29336. <_routine name="upper">
  29337. <table border=0 cellspacing=2 cellpadding=2>
  29338.  
  29339.  <_2clist
  29340.   name="Syntax:"
  29341.   description="<font face = \"Arial, Helvetica\"> include wildcard.e<BR>
  29342.  x2 = upper(x1)
  29343. </font>"
  29344.  >
  29345.  <_2clist
  29346.   name="Description:"
  29347.   description=
  29348. "  Convert an atom or sequence to upper case. "
  29349.  >
  29350. <_2clist
  29351.   name="Example:"
  29352.   description=""
  29353.  >
  29354. <_eucode>
  29355. s = upper("Euphoria")
  29356. -- s is "EUPHORIA"
  29357.  
  29358. a = upper('g')
  29359. -- a is 'G'
  29360.  
  29361. s = upper({"Euphoria", "Programming"})
  29362. -- s is {"EUPHORIA", "PROGRAMMING"}
  29363.  
  29364.  </_eucode>
  29365. <_2clist
  29366.   name="See Also:"
  29367.   description="<a href=\"lib_h_o.htm#lower\">lower</a>"
  29368.  >
  29369. </table>
  29370.  
  29371.  
  29372. <_routine name="use_vesa">
  29373. <table border=0 cellspacing=2 cellpadding=2>
  29374.  
  29375.  
  29376.  <_2clist
  29377.   name="Platform:"
  29378.   description="<font color=\"#CC3366\"><b>DOS32</b></font>"
  29379.  >
  29380.  
  29381.  <_2clist
  29382.   name="Syntax:"
  29383.   description="<font face = \"Arial, Helvetica\"> include machine.e<BR>
  29384.  use_vesa(i)
  29385. </font>"
  29386.  >
  29387.  <_2clist
  29388.   name="Description:"
  29389.   description=
  29390. "use_vesa(1) will force Euphoria to use the VESA graphics
  29391.  standard. This may cause Euphoria programs to work better
  29392.  in SVGA graphics modes with certain video cards.
  29393.  use_vesa(0) will restore Euphoria's original method of
  29394.  using the video card."
  29395.  >
  29396. <_2clist
  29397.   name="Comments:"
  29398.   description=
  29399. "Most people can ignore this. However if you experience
  29400.  difficulty in SVGA graphics modes you should try calling
  29401.  use_vesa(1) at the start of your program before any calls
  29402.  to graphics_mode().
  29403. <P>
  29404. Arguments to use_vesa() other than 0 or 1 should not be used."
  29405.  >
  29406. <_2clist
  29407.   name="Example:"
  29408.   description=""
  29409.  >
  29410. <_eucode>
  29411. use_vesa(1)
  29412. fail = graphics_mode(261)
  29413.  
  29414.  </_eucode>
  29415. <_2clist
  29416.   name="See Also:"
  29417.   description="<a href=\"lib_e_g.htm#graphics_mode\">graphics_mode</a>"
  29418.  >
  29419. </table>
  29420.  
  29421.  
  29422. <_routine name="value">
  29423. <table border=0 cellspacing=2 cellpadding=2>
  29424.  
  29425.  
  29426.  <_2clist
  29427.   name="Syntax:"
  29428.   description="<font face = \"Arial, Helvetica\"> include get.e<BR>
  29429.  s = value(st)
  29430. </font>"
  29431.  >
  29432.  <_2clist
  29433.   name="Description:"
  29434.   description=
  29435. "Read the string representation of a Euphoria object, and compute
  29436.  the value of that object. A 2-element sequence,
  29437.  <b>{error_status, value}</b> is actually returned, where error_status
  29438.  can be one of:"
  29439.  >
  29440. <_eucode>
  29441.     GET_SUCCESS -- a valid object representation was found
  29442.     GET_EOF     -- end of string reached too soon
  29443.     GET_FAIL    -- syntax is wrong
  29444. </_eucode>
  29445.  
  29446. <_2clist
  29447.   name="Comments:"
  29448.   description=
  29449. "This works the same as <b>get()</b>, but it reads from a string
  29450.  that you supply, rather than from a file or device.
  29451.  <p>
  29452.  After reading one valid representation of a Euphoria object, value() will
  29453.  stop reading and ignore any additional characters in the string. For 
  29454.  example, \"36\" and \"36P\" will both give you {GET_SUCCESS, 36}."
  29455.  >
  29456. <_2clist
  29457.   name="Example 1:"
  29458.   description=""
  29459.  >
  29460. <_eucode>
  29461. s = value("12345"}
  29462. -- s is {GET_SUCCESS, 12345}
  29463.  
  29464.  </_eucode>
  29465. <_2clist
  29466.   name="Example 2:"
  29467.   description=""
  29468.  >
  29469. <_eucode>
  29470. s = value("{0, 1, -99.9}")
  29471. -- s is {GET_SUCCESS, {0, 1, -99.9}}
  29472.  
  29473.  </_eucode>
  29474. <_2clist
  29475.   name="Example 3:"
  29476.   description=""
  29477.  >
  29478. <_eucode>
  29479. s = value("+++")
  29480. -- s is {GET_FAIL, 0}
  29481.  
  29482.  </_eucode>
  29483. <_2clist
  29484.   name="See Also:"
  29485.   description="<a href=\"lib_e_g.htm#get\">get</a>,
  29486. <a href=\"lib_s_t.htm#sprintf\">sprintf</a>,
  29487. <a href=\"lib_p_r.htm#print\">print</a>"
  29488.  >
  29489. </table>
  29490.  
  29491.  
  29492. <_routine name="video_config">
  29493. <table border=0 cellspacing=2 cellpadding=2>
  29494.  
  29495.  
  29496.  <_2clist
  29497.   name="Platform:"
  29498.   description="<font color=\"#CC3366\"><b>DOS32, Linux</b></font>"
  29499.  >
  29500.  
  29501.  <_2clist
  29502.   name="Syntax:"
  29503.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  29504.  s = video_config()
  29505. </font>"
  29506.  >
  29507.  <_2clist
  29508.   name="Description:"
  29509.   description=
  29510. "Return a sequence of values describing the current video
  29511.  configuration:<br>
  29512.  {color monitor?, graphics mode, text rows, text columns,
  29513.  xpixels, ypixels, number of colors, number of pages}<P>
  29514. The following constants are defined in
  29515.  <font color=\"#5500FF\"><b>graphics.e</b></font>:"
  29516.  >
  29517. <_eucode>
  29518.     global constant VC_COLOR   = 1,
  29519.                     VC_MODE    = 2,
  29520.                     VC_LINES   = 3,
  29521.                     VC_COLUMNS = 4,
  29522.                     VC_XPIXELS = 5,
  29523.                     VC_YPIXELS = 6,
  29524.                     VC_NCOLORS = 7,
  29525.                     VC_PAGES   = 8
  29526. </_eucode> 
  29527.  
  29528. <_2clist
  29529.   name="Comments:"
  29530.   description=
  29531. "This routine makes it easy for you to parameterize a program
  29532.  so it will work in many different graphics modes.
  29533. <P>
  29534. On the PC there are two types of graphics mode. The first type,
  29535.  <font color=\"#CC3366\">text mode</font>, lets you print text only.
  29536.  The second type, <font color=\"#CC3366\">pixel-graphics mode</font>,
  29537.  lets you plot pixels, or points, in various colors, as well as text.
  29538.  You can tell that you are in a <font color=\"#CC3366\">text mode</font>,
  29539.  because the VC_XPIXELS and VC_YPIXELS fields will be 0. Library routines
  29540.  such as <a href=\"lib_p_r.htm#polygon\">polygon()</a>,
  29541.  <a href=\"lib_c_d.htm#draw_line\">draw_line()</a>, and
  29542.  <a href=\"lib_e_g.htm#ellipse\">ellipse()</a>
  29543.  only work in a <font color=\"#CC3366\">pixel-graphics mode</font>."
  29544.  >
  29545. <_2clist
  29546.   name="Example:"
  29547.   description=""
  29548.  >
  29549. <_eucode>
  29550. vc = video_config()  -- in mode 3 with 25-lines of text:
  29551. -- vc is {1, 3, 25, 80, 0, 0, 32, 8}
  29552.  
  29553.  </_eucode>
  29554. <_2clist
  29555.   name="See Also:"
  29556.   description="<a href=\"lib_e_g.htm#graphics_mode\">graphics_mode</a>"
  29557.  >
  29558. </table>
  29559.  
  29560.  
  29561. <_routine name="wait_key">
  29562. <table border=0 cellspacing=2 cellpadding=2>
  29563.  
  29564.  
  29565.  <_2clist
  29566.   name="Syntax:"
  29567.   description="<font face = \"Arial, Helvetica\"> include get.e<BR>
  29568.  i = wait_key()
  29569. </font>"
  29570.  >
  29571.  <_2clist
  29572.   name="Description:"
  29573.   description=
  29574. "Return the next key pressed by the user. Don't return until
  29575.  a key is pressed."
  29576.  >
  29577. <_2clist
  29578.   name="Comments:"
  29579.   description=
  29580. "You could achieve the same result using <b>get_key()</b> as follows:"
  29581. >
  29582. <_eucode>
  29583.     while 1 do
  29584.         k = get_key()
  29585.         if k != -1 then
  29586.             exit
  29587.         end if
  29588.     end while
  29589. </_eucode>
  29590. <_2clist
  29591.   name=""
  29592.   description=
  29593. "However, on multi-tasking systems like
  29594.  <font color=\"#CC3366\"><b>Windows</b></font>
  29595.  or <font color=\"#CC3366\"><b>Linux</b></font>, this \"busy waiting\"
  29596.  would tend to slow the system down.
  29597.  wait_key() lets the operating system do other useful work
  29598.  while your program is waiting for the user to press a key.
  29599. <P>
  29600. You could also use <b>getc(0)</b>, assuming file number 0 was input
  29601.  from the keyboard, except that you wouldn't pick up the special
  29602.  codes for function keys, arrow keys etc."
  29603.  >
  29604. <_2clist
  29605.   name="See Also:"
  29606.   description="<a href=\"lib_e_g.htm#get_key\">get_key</a>,
  29607. <a href=\"lib_e_g.htm#getc\">getc</a>"
  29608.  >
  29609. </table>
  29610.  
  29611.  
  29612. <_routine name="walk_dir">
  29613. <table border=0 cellspacing=2 cellpadding=2>
  29614.  
  29615.  
  29616.  <_2clist
  29617.   name="Syntax:"
  29618.   description="<font face = \"Arial, Helvetica\"> include file.e<BR>
  29619.  i1 = walk_dir(st, i2, i3)
  29620. </font>"
  29621.  >
  29622.  <_2clist
  29623.   name="Description:"
  29624.   description=
  29625. "This routine will \"walk\" through a directory with path name
  29626.  given by st. i2 is the <font color=\"#993333\"><b>routine id</b></font>
  29627.  of a routine that you supply.
  29628.  walk_dir() will call your routine once for each file and
  29629.  subdirectory in st. If i3 is non-zero (TRUE), then the
  29630.  subdirectories in st will be walked through recursively.<P>
  29631. The routine that you supply should accept the path name and 
  29632.  <a href=\"lib_c_d.htm#dir_entry\">dir() entry</a> for each file and
  29633.  subdirectory. It should return 0 to keep going, or
  29634.  non-zero to stop walk_dir()."
  29635.  >
  29636. <_2clist
  29637.   name="Comments:"
  29638.   description=
  29639. "This mechanism allows you to write a simple function that handles
  29640.  one file at a time, while walk_dir() handles the
  29641.  process of walking through all the files and subdirectories.
  29642. <P>
  29643. By default, the files and subdirectories will be visited in
  29644.  alphabetical order. To use a different order, set the global
  29645.  integer <b>my_dir</b> to the <font color=\"#993333\"><b>routine id</b></font>
  29646.  of your own <i>modified</i> dir()
  29647.  function that sorts the directory entries differently. See the default
  29648.  dir() function in <font color=\"#5500FF\"><b>file.e</b></font>."
  29649.  >
  29650. <_2clist
  29651.   name="Example:"
  29652.   description=""
  29653.  >
  29654. <_eucode>
  29655. function look_at(sequence path_name, sequence entry)
  29656. -- this function accepts two sequences as arguments
  29657.     printf(1, "%s\\%s: %d\n",
  29658.            {path_name, entry[D_NAME], entry[D_SIZE]})
  29659.     return 0 -- keep going
  29660. end function
  29661.  
  29662. exit_code = walk_dir("C:\\MYFILES", routine_id("look_at"), TRUE)
  29663.  
  29664.  </_eucode>
  29665. <_2clist
  29666.   name="Example Program:"
  29667.   description="<font color=\"#5500FF\"><b>euphoria\bin\search.ex</b></font>"
  29668.  >
  29669.  
  29670.  <_2clist
  29671.   name="See Also:"
  29672.   description="<a href=\"lib_c_d.htm#dir\">dir</a>,
  29673. <a href=\"lib_c_d.htm#current_dir\">current_dir</a>"
  29674.  >
  29675. </table>
  29676.  
  29677.  
  29678. <_routine name="where">
  29679. <table border=0 cellspacing=2 cellpadding=2>
  29680.  
  29681.  
  29682.  <_2clist
  29683.   name="Syntax:"
  29684.   description="<font face = \"Arial, Helvetica\"> include file.e<BR>
  29685.  i = where(fn)
  29686. </font>"
  29687.  >
  29688.  <_2clist
  29689.   name="Description:"
  29690.   description=
  29691. "  This function returns the current byte position in the file fn.
  29692.  This position is updated by reads, writes and seeks on the file.
  29693.  It is the place in the file where the next byte will be read
  29694.  from, or written to. "
  29695.  >
  29696. <_2clist
  29697.   name="See Also:"
  29698.   description="<a href=\"lib_s_t.htm#seek\">seek</a>,
  29699. <a href=\"lib_h_o.htm#open\">open</a>"
  29700.  >
  29701. </table>
  29702.  
  29703.  
  29704. <_routine name="wildcard_file">
  29705. <table border=0 cellspacing=2 cellpadding=2>
  29706.  
  29707.  
  29708.  <_2clist
  29709.   name="Syntax:"
  29710.   description="<font face = \"Arial, Helvetica\"> include wildcard.e<BR>
  29711.  i = wildcard_file(st1, st2)
  29712. </font>"
  29713.  >
  29714.  <_2clist
  29715.   name="Description:"
  29716.   description=
  29717. "Return 1 (true) if the filename st2 matches the wild card pattern
  29718.  st1. Return 0 (false) otherwise. This is similar to DOS wildcard
  29719.  matching, but better in some cases. * matches any 0 or more
  29720.  characters, ? matches any single character. Character comparisons
  29721.  are not case sensitive."
  29722.  >
  29723. <_2clist
  29724.   name="Comments:"
  29725.   description=
  29726. "You might use this function to check the output of the dir()
  29727.  routine for file names that match a pattern supplied by the
  29728.  user of your program.
  29729. <P>
  29730. In DOS \"*ABC.*\" will match <b><i>all</i></b> files.
  29731.  wildcard_file(\"*ABC.*\", s) will only match when the file name part
  29732.  has \"ABC\" at the end (as you would expect)."
  29733.  >
  29734. <_2clist
  29735.   name="Example 1:"
  29736.   description=""
  29737.  >
  29738. <_eucode>
  29739. i = wildcard_file("AB*CD.?", "aB123cD.e")
  29740. -- i is set to 1
  29741.  
  29742.  </_eucode>
  29743. <_2clist
  29744.   name="Example 2:"
  29745.   description=""
  29746.  >
  29747. <_eucode>
  29748. i = wildcard_file("AB*CD.?", "abcd.ex")
  29749. -- i is set to 0, because the file type has 2 letters not 1
  29750.  
  29751.  </_eucode>
  29752. <_2clist
  29753.   name="Example Program:"
  29754.   description="<font color=\"#5500FF\"><b>bin\search.ex</b></font>"
  29755.  >
  29756.  
  29757.  <_2clist
  29758.   name="See Also:"
  29759.   description="<a href=\"lib_u_z.htm#wildcard_match\">wildcard_match</a>,
  29760. <a href=\"lib_c_d.htm#dir\">dir</a>"
  29761.  >
  29762. </table>
  29763.  
  29764.  
  29765. <_routine name="wildcard_match">
  29766. <table border=0 cellspacing=2 cellpadding=2>
  29767.  
  29768.  
  29769.  <_2clist
  29770.   name="Syntax:"
  29771.   description="<font face = \"Arial, Helvetica\"> include wildcard.e<BR>
  29772.  i = wildcard_match(st1, st2)
  29773. </font>"
  29774.  >
  29775.  <_2clist
  29776.   name="Description:"
  29777.   description=
  29778. "This function performs a general matching of a string against a
  29779.  pattern containing * and ? wildcards. It returns 1 (true) if
  29780.  string st2 matches pattern st1. It returns 0 (false) otherwise.
  29781.  * matches any 0 or more characters. ? matches any
  29782.  single character. Character comparisons are case sensitive."
  29783.  >
  29784. <_2clist
  29785.   name="Comments:"
  29786.   description=
  29787. "If you want case insensitive comparisons, pass both st1 and st2
  29788.  through upper(), or both through lower() before calling
  29789.  wildcard_match().
  29790. <P>
  29791. If you want to detect a pattern anywhere within a string,
  29792.  add * to each end of the pattern:"
  29793.  >
  29794. <_eucode>
  29795. i = wildcard_match('*' & pattern & '*', string)
  29796. </_eucode>
  29797.  
  29798. <_2clist
  29799.   name=""
  29800.   description=
  29801. "There is currently no way to treat * or ? literally in a pattern."
  29802.  >
  29803. <_2clist
  29804.   name="Example 1:"
  29805.   description=""
  29806.  >
  29807. <_eucode>
  29808. i = wildcard_match("A?B*", "AQBXXYY")
  29809. -- i is 1 (TRUE)
  29810.  
  29811.  </_eucode>
  29812. <_2clist
  29813.   name="Example 2:"
  29814.   description=""
  29815.  >
  29816. <_eucode>
  29817. i = wildcard_match("*xyz*", "AAAbbbxyz")
  29818. -- i is 1 (TRUE)
  29819.  
  29820.  </_eucode>
  29821. <_2clist
  29822.   name="Example 3:"
  29823.   description=""
  29824.  >
  29825. <_eucode>
  29826. i = wildcard_match("A*B*C", "a111b222c")
  29827. -- i is 0 (FALSE) because upper/lower case doesn't match
  29828.  
  29829.  </_eucode>
  29830. <_2clist
  29831.   name="Example Program:"
  29832.   description="<font color=\"#5500FF\"><b>bin\search.ex</b></font>"
  29833.  >
  29834.  
  29835.  <_2clist
  29836.   name="See Also:"
  29837.   description="<a href=\"lib_u_z.htm#wildcard_file\">wildcard_file</a>,
  29838. <a href=\"lib_h_o.htm#match\">match</a>,
  29839. <a href=\"lib_u_z.htm#upper\">upper</a>,
  29840. <a href=\"lib_h_o.htm#lower\">lower</a>,
  29841. <a href=\"lib_c_d.htm#compare\">compare</a>"
  29842.  >
  29843. </table>
  29844.  
  29845.  
  29846. <_routine name="wrap">
  29847. <table border=0 cellspacing=2 cellpadding=2>
  29848.  
  29849.  
  29850.  <_2clist
  29851.   name="Syntax:"
  29852.   description="<font face = \"Arial, Helvetica\"> include graphics.e<BR>
  29853.  wrap(i)
  29854. </font>"
  29855.  >
  29856.  <_2clist
  29857.   name="Description:"
  29858.   description=
  29859. "Allow text to wrap at the right margin (i = 1) or get truncated
  29860.  (i = 0)."
  29861.  >
  29862. <_2clist
  29863.   name="Comments:"
  29864.   description=
  29865. "By default text will wrap.
  29866. <P>
  29867. Use wrap() in <font color=\"#CC3366\">text modes</font> or
  29868.  <font color=\"#CC3366\">pixel-graphics modes</font> when you
  29869.  are displaying long lines of text."
  29870.  >
  29871. <_2clist
  29872.   name="Example:"
  29873.   description=""
  29874.  >
  29875. <_eucode>
  29876. puts(1, repeat('x', 100) & "\n\n")
  29877. -- now have a line of 80 'x' followed a line of 20 more 'x'
  29878. wrap(0)
  29879. puts(1, repeat('x', 100) & "\n\n")
  29880. -- creates just one line of 80 'x'
  29881.  
  29882.  </_eucode>
  29883. <_2clist
  29884.   name="See Also:"
  29885.   description="<a href=\"lib_p_r.htm#puts\">puts</a>,
  29886. <a href=\"lib_p_r.htm#position\">position</a>"
  29887.  >
  29888. </table>
  29889.  
  29890.  
  29891. <_routine name="xor_bits">
  29892. <table border=0 cellspacing=2 cellpadding=2>
  29893.  
  29894.  
  29895.  <_2clist
  29896.   name="Syntax:"
  29897.   description="<font face = \"Arial, Helvetica\"> x3 = xor_bits(x1, x2)
  29898. </font>"
  29899.  >
  29900.  <_2clist
  29901.   name="Description:"
  29902.   description=
  29903. "Perform the logical XOR (exclusive OR) operation on
  29904.  corresponding bits in x1 and x2. A bit in x3 will be 1
  29905.  when one of the two corresponding bits in x1 or x2 is 1,
  29906.  and the other is 0."
  29907.  >
  29908. <_2clist
  29909.   name="Comments:"
  29910.   description=
  29911. "The arguments to this function may be atoms or sequences. The
  29912.  rules for <a href=\"refman_2.htm#26\">operations on sequences</a> apply.
  29913. <P>
  29914. The arguments must be representable as 32-bit numbers,
  29915.  either signed or unsigned.
  29916. <P>
  29917. If you intend to manipulate full 32-bit values, you should
  29918.  declare your variables as
  29919.  <font color=\"#993333\"><b>atom</b></font>, rather than integer. Euphoria's
  29920.  integer type is limited to 31-bits.
  29921. <P>
  29922. Results are treated as signed numbers. They will be
  29923.  negative when the highest-order bit is 1."
  29924.  >
  29925. <_2clist
  29926.   name="Example 1:"
  29927.   description=""
  29928.  >
  29929. <_eucode>
  29930. a = xor_bits(#0110, #1010)
  29931. -- a is #1100
  29932.  
  29933.  </_eucode>
  29934. <_2clist
  29935.   name="See Also:"
  29936.   description="<a href=\"lib_a_b.htm#and_bits\">and_bits</a>,
  29937. <a href=\"lib_h_o.htm#or_bits\">or_bits</a>,
  29938. <a href=\"lib_h_o.htm#not_bits\">not_bits</a>,
  29939. <a href=\"lib_h_o.htm#int_to_bits\">int_to_bits</a>,
  29940. <a href=\"lib_h_o.htm#int_to_bytes\">int_to_bytes</a>"
  29941.  >
  29942.  
  29943. </table>
  29944. </body>
  29945. </html>
  29946. OVERVIEW.HTX
  29947. 4605
  29948. <_init_comment>
  29949. <html>
  29950. <head><title>Guide to Documentation Files</title>
  29951. </head>
  29952. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  29953. <_width>
  29954. <_center><font face="Arial, Helvetica" color="#FF0099" size=+2>
  29955. <br>
  29956.                       Guide to Documentation Files
  29957. </font></_center>
  29958. <p> <br>
  29959.  
  29960.  The Euphoria documentation is spread over several plain text files in the
  29961.  <font color="#5500FF"><b>euphoria\doc</b></font> directory. For each
  29962.  <b>.doc</b> file in the <font color="#5500FF"><b>euphoria\doc</b></font>
  29963.  directory, there is a corresponding <b>.htm</b> file in the
  29964.  <font color="#5500FF"><b>euphoria\html</b></font> directory. You can also
  29965.  type <font color="#993333"><b>guru</b></font> to quickly search for relevant
  29966.  information from all directories under
  29967.  <font color="#5500FF"><b>\euphoria</b></font>. 
  29968.  
  29969. <p>
  29970.  Everyone should start with 
  29971.  <font color="#5500FF"><b>euphoria\readme.doc</b></font>
  29972.  (<font color="#5500FF"><b>euphoria\readme.htm</b></font>).
  29973. <p> 
  29974.  <_sul>If you are having trouble installing Euphoria read:</_sul>
  29975. <p>
  29976. <table border=0 cellspacing=2 cellpadding=2>
  29977.  
  29978. <_4clist
  29979.   href="install.htm"
  29980.   name="<font color=\"#5500FF\">install.doc</font>"
  29981.   pos=18
  29982.   description="Instructions for installing Euphoria"
  29983. >
  29984.  
  29985. </table>
  29986.  
  29987. <p>
  29988.  <_sul>Read the following files first, if you want to learn to program in
  29989.  Euphoria:</_sul>
  29990. <p>
  29991. <table border=0 cellspacing=2 cellpadding=2>
  29992.  
  29993. <_4clist
  29994.   href="refman.htm"
  29995.   name="<font color=\"#5500FF\">refman.doc</font>"
  29996.   pos=18
  29997.   description="The manual for the Euphoria core language"
  29998. >
  29999.  
  30000. <_4clist
  30001.   href="library.htm"
  30002.   name="<font color=\"#5500FF\">library.doc</font>"
  30003.   pos=18
  30004.   description="Documentation for all of the Euphoria library routines"
  30005. >
  30006.  
  30007. <_4clist
  30008.   href="what2do.htm"
  30009.   name="<font color=\"#5500FF\">what2do.doc</font>"
  30010.   pos=18
  30011.   description="Some things you can do to get started with Euphoria"
  30012. >
  30013.  
  30014. <_4clist
  30015.   href="platform.htm"
  30016.   name="<font color=\"#5500FF\">platform.doc</font>"
  30017.   pos=18
  30018.   description="A discussion of the differences between the three
  30019.    <font color=\"#993333\"><b><i>platforms</i></b></font>
  30020.    that Euphoria runs on, i.e.
  30021.    <font color=\"#CC3366\"><b>DOS32</b></font>
  30022.    (<font color=\"#993333\"><b>ex.exe</b></font>)
  30023.    vs. 
  30024.    <font color=\"#CC3366\"><b>WIN32</b></font>
  30025.    (<font color=\"#993333\"><b>exw.exe</b></font>)
  30026.    vs. 
  30027.    <font color=\"#CC3366\"><b>Linux</b></font>
  30028.    (<font color=\"#993333\"><b>exu</b></font>)."
  30029. >
  30030. </table>
  30031.  
  30032. <p>
  30033.  <_sul>The rest of the files can be read any time, as needed:</_sul>
  30034. <p>
  30035. <table border=0 cellspacing=2 cellpadding=2>
  30036.  
  30037. <_4clist
  30038.   href="ed.htm"
  30039.   name="<font color=\"#5500FF\">ed.doc</font>"
  30040.   pos=18
  30041.   description="Documentation for the standard Euphoria editor,
  30042.    <font color=\"#993333\"><b>ed</b></font>"
  30043. >
  30044.  
  30045. <_4clist
  30046.   href="trouble.htm"
  30047.   name="<font color=\"#5500FF\">trouble.doc</font>"
  30048.   pos=18
  30049.   description="A list of the most common problems and their solutions"
  30050. >
  30051.  
  30052. <_4clist
  30053.   href="bind.htm"
  30054.   name="<font color=\"#5500FF\">bind.doc</font>"
  30055.   pos=18
  30056.   description="Describes <font color=\"#5500FF\"><b>bind.bat</b></font> and
  30057.    <font color=\"#5500FF\"><b>shroud.bat</b></font> options for
  30058.    <font color=\"#993333\"><b>binding</b></font> and
  30059.    <font color=\"#993333\"><b>shrouding</b></font>"
  30060. >
  30061.  
  30062. <_4clist
  30063.   href="perform.htm"
  30064.   name="<font color=\"#5500FF\">perform.doc</font>"
  30065.   pos=18
  30066.   description="Performance tips"
  30067. >
  30068.  
  30069. <_4clist
  30070.   href="web.htm"
  30071.   name="<font color=\"#5500FF\">web.doc</font>"
  30072.   pos=18
  30073.   description="A list of Euphoria resources available on the World Wide Web"
  30074. >
  30075.  
  30076. <_4clist
  30077.   href="relnotes.htm"
  30078.   name="<font color=\"#5500FF\">relnotes.doc</font>"
  30079.   pos=18
  30080.   description="A description of what's new in the current release and
  30081.    a summary of previous releases of Euphoria"
  30082. >
  30083.  
  30084. <_4clist
  30085.   href="basic.htm"
  30086.   name="<font color=\"#5500FF\">basic.doc</font>"
  30087.   pos=18
  30088.   description="Propaganda aimed at BASIC programmers"
  30089. >
  30090.  
  30091. <_4clist
  30092.   href="c.htm"
  30093.   name="<font color=\"#5500FF\">c.doc</font>"
  30094.   pos=18
  30095.   description="Propaganda aimed at C/C++ programmers"
  30096. >
  30097.  
  30098. </table>
  30099.  
  30100. <p>
  30101.  Most subdirectories under <font color="#5500FF"><b>\euphoria</b></font> have
  30102.  a <b>.doc</b> file that describes the files in that subdirectory. The
  30103.  <font color="#5500FF"><b>euphoria\register</b></font> subdirectory contains
  30104.  <a href="register.htm"><font color="#5500FF"><b>register.doc</b></font></a>.
  30105.  Read it when you are thinking of registering.
  30106.  
  30107. <p> 
  30108.  
  30109. </_width>
  30110. </body>
  30111. </html>
  30112.  
  30113. PERFORM.HTX
  30114. 19675
  30115. <_init_comment>
  30116. <html>
  30117. <head><title>Euphoria Performance Tips</title>
  30118. </head>
  30119. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  30120. <_width>
  30121. <_center><font face="Arial, Helvetica" color="#FF0099" size=+2>
  30122. <br>
  30123.                        Euphoria Performance Tips
  30124. </font></_center>
  30125. <p>
  30126.  
  30127. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30128. <br>
  30129.  
  30130. <_sul>General Tips</_sul>
  30131.  
  30132. </font>
  30133. <ul>
  30134. <li>
  30135.  If your program is fast enough, forget about speeding it up.
  30136.    Just make it simple and readable.
  30137. <p>
  30138. <li>
  30139.  If your program is way too slow, the tips below will probably not solve 
  30140.    your problem. You should find a better overall algorithm.
  30141. <p>
  30142. <li>
  30143.  
  30144.  The easiest way to gain a bit of speed is to turn off run-time 
  30145.  type-checking. Insert the line:
  30146.  
  30147. <_eucode>
  30148.            without type_check
  30149. </_eucode>
  30150.    at the top of your main <b>.ex</b> file, ahead of any include statements.
  30151.    You'll typically gain between 0 and 20 percent depending on the
  30152.    types you have defined, and the files that you are including.
  30153.    Most of the standard include files do some user-defined type-checking.
  30154.    A program that is completely without user-defined type-checking
  30155.    might still be speeded up slightly.
  30156.  <p>
  30157.    Also, be <font color="#CC0099"><_ba><i>sure</i></_ba></font> to remove,
  30158.    or comment-out, any
  30159. <_eucode>
  30160.            with trace
  30161.            with profile
  30162.            with profile_time
  30163. </_eucode>
  30164.    statements. <font color="#993333"><b>with trace</b></font> (even without
  30165.    any calls to <font color="#006699">trace()</font>), and
  30166.    <font color="#993333"><b>with profile</b></font> can easily slow you down
  30167.    by 10% or more. <font color="#993333"><b>with profile_time</b></font>
  30168.    might slow you down by 1%. Each of these options will consume extra
  30169.    memory as well.
  30170. <p>
  30171. <li>
  30172.  Calculations using integer values are faster than calculations using
  30173.    floating-point numbers
  30174. <p>
  30175. <li>
  30176.  Declare variables as integer rather than atom where possible,
  30177.    and as sequence rather than object where possible. This usually gains
  30178.    you a few percent in speed.
  30179. <p>
  30180. <li>
  30181.  In an expression involving floating-point calculations it's usually faster
  30182.    to write constant numbers in floating point form, e.g. when x has a
  30183.    floating-point value, say, x = 9.9<br><br>
  30184.    change:
  30185. <_eucode>
  30186.            x = x * 5
  30187. </_eucode>
  30188.    to:
  30189. <_eucode>
  30190.            x = x * 5.0
  30191. </_eucode>
  30192.    This saves the interpreter from having to convert integer 5 to
  30193.    floating-point 5.0 each time.
  30194. <p>
  30195. <li>
  30196.  Euphoria does <_bq><i>short-circuit</i></_bq> evaluation of
  30197.   <font color="#993333"><_bq>if</_bq></font>,
  30198.   <font color="#993333"><_bq>elsif</_bq></font>, and
  30199.   <font color="#993333"><_bq>while</_bq></font> conditions involving
  30200.   <font color="#993333"><_bq>and</_bq></font> and
  30201.   <font color="#993333"><_bq>or</_bq></font>. Euphoria will stop evaluating
  30202.   any condition once it determines if the condition is true or not.
  30203.   For instance in the <font color="#006699">if-statement</font>:
  30204. <_eucode>
  30205.         if x > 20 and y = 0 then
  30206.             ...
  30207.         end if
  30208. </_eucode>
  30209.    The "y = 0" test will only be made when "x > 20" is true.
  30210.  <p>
  30211.    For maximum speed, you can order your tests. Do "x > 20" first if it is
  30212.    more likely to be false than "y = 0". 
  30213.  <p>
  30214.    In general, with a condition "A and B", Euphoria will not evaluate the 
  30215.    expression B, when A is false (zero). Similarly, with a condition like 
  30216.    "A or B", B will not be evaluated when A is true (non-zero).
  30217.  <p>
  30218.    Simple if-statements are highly optimized. 
  30219.    With the current version of the interpreter, 
  30220.    nested simple if's that compare integers are usually a bit faster 
  30221.    than a single short-circuit if-statement e.g.:
  30222. <_eucode>
  30223.        if x > 20 then
  30224.            if y = 0 then
  30225.                ...
  30226.            end if
  30227.        end if
  30228. </_eucode>
  30229.  
  30230. <p>
  30231. <li>
  30232.  The speed of access to private variables, local variables and global
  30233.    variables is the same.
  30234. <p>
  30235. <li>
  30236.  There is no performance penalty for defining constants versus plugging
  30237.    in hard-coded literal numbers. The speed of:
  30238. <_eucode>
  30239.            y = x * MAX
  30240. </_eucode>
  30241.    is exactly the same as:
  30242. <_eucode>
  30243.            y = x * 1000
  30244. </_eucode>
  30245.    where you've previously defined:
  30246. <_eucode>
  30247.            constant MAX = 1000
  30248. </_eucode>
  30249.  
  30250. <li>
  30251.  There is no performance penalty for having lots of comments in your 
  30252.    program. Comments are completely ignored. They are not executed in any way.
  30253.    It might take a few milliseconds longer for the initial load of your
  30254.    program, but that's a very small price to pay for future maintainability,
  30255.    and when you <font color="#993333"><b>bind</b></font> your program, all
  30256.    comments are stripped out, so the cost becomes absolute zero.
  30257.  
  30258. </ul>
  30259.  
  30260. <p>
  30261.  
  30262. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30263. <br>
  30264.  
  30265. <_sul>Measuring Performance</_sul>
  30266.  
  30267. </font>
  30268. <p>
  30269.  In any programming language, and especially in Euphoria,
  30270.  <font color="#006633"><b>you really have to make measurements before
  30271.  drawing conclusions about performance</b></font>.
  30272. <p>
  30273.  Euphoria provides both <font color="#993333"><b>execution-count
  30274.  profiling</b></font>, as well as
  30275.  <font color="#993333"><b>time profiling</b></font>
  30276.  (<font color="#CC3366"><b>DOS32</b></font> only). See
  30277.  <a href="refman_3.htm#2"><font color="#5500FF"><b>refman.doc</b></font></a>.
  30278.  You will often be surprised by the results of these profiles. Concentrate
  30279.  your efforts on the places in your program that are using a high percentage
  30280.  of the total time (or at least are executed a large number of times.)
  30281.  There's no point to rewriting a section of code that uses 0.01% of the total
  30282.  time. Usually there will be one place, or just a few places where code
  30283.  tweaking will make a significant difference.
  30284. <p>
  30285.  You can also measure the speed of code by using the
  30286.  <font color="#006699"><b>time()</b></font> function. e.g.
  30287. <_eucode>
  30288.         atom t
  30289.         t = time()
  30290.         for i = 1 to 10000 do
  30291.             -- small chunk of code here
  30292.         end for
  30293.         ? time() - t
  30294. </_eucode>
  30295. <p>
  30296.  You might rewrite the small chunk of code in different ways to see which way 
  30297.  is faster.
  30298.  
  30299. <p>
  30300.  
  30301. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30302. <br>
  30303.  
  30304. <_sul>How to Speed-Up Loops</_sul>
  30305.  
  30306. </font>
  30307. <p>
  30308.  <font color="#993333"><b>Profiling</b></font> will show you the
  30309.  <font color="#CC0099"><_bq><i>hot spots</i></_bq></font> in your program.
  30310.  These are usually inside loops. Look at each calculation inside the loop
  30311.  and ask yourself if it really needs to happen every time through the loop,
  30312.  or could it be done just once, prior to the loop.
  30313.  
  30314. <p>
  30315.  
  30316. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30317. <br>
  30318.  
  30319. <_sul>Converting Multiplies to Adds in a Loop</_sul>
  30320.  
  30321. </font>
  30322. <p>
  30323.  Addition is faster than multiplication. Sometimes you can replace a
  30324.  multiplication by the loop variable, with an addition. Something like:
  30325. <_eucode>
  30326.         for i = 0 to 199 do
  30327.             poke(screen_memory+i*320, 0)
  30328.         end for
  30329. </_eucode>
  30330.   
  30331.   becomes:
  30332. <_eucode>
  30333.         x = screen_memory
  30334.         for i = 0 to 199 do
  30335.             poke(x, 0)
  30336.             x = x + 320 
  30337.         end for
  30338. </_eucode>
  30339.  
  30340. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30341. <br>
  30342.  
  30343. <_sul>Saving Results in Variables</_sul>
  30344.  
  30345. </font>
  30346. <ul>
  30347. <li>
  30348.  It's faster to save the result of a calculation in a variable, than it is to
  30349.    recalculate it later. Even something as simple as a subscript operation, 
  30350.    or adding 1 to a variable is worth saving.
  30351. <p>
  30352. <li>
  30353.  When you have a sequence with multiple levels of subscripting,
  30354.    it is faster to change code like:
  30355. <_eucode>
  30356.            for i = 1 to 1000 do
  30357.                y[a][i] = y[a][i]+1
  30358.            end for
  30359. </_eucode>
  30360.  
  30361.    to:
  30362. <_eucode>
  30363.            ya = y[a]
  30364.            for i = 1 to 1000 do
  30365.                ya[i] = ya[i] + 1
  30366.            end for
  30367.            y[a] = ya
  30368. </_eucode>
  30369.  
  30370.     So you are doing 2 subscript operations per iteration of the loop, rather 
  30371.     than 4. The operations, ya = y[a] and y[a] = ya are very cheap.
  30372.     <font color="#006633"><b>They just copy a pointer.</b></font> They
  30373.     don't copy a whole sequence.
  30374. <p>
  30375. <li>
  30376.  There is a slight cost when you create a new sequence using <b>{a,b,c}</b>.
  30377.    If possible, move this operation out of a critical loop by storing it 
  30378.    in a variable before the loop, and referencing the variable inside the
  30379.    loop.
  30380.  
  30381. </ul>
  30382.  
  30383. <p>
  30384.  
  30385. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30386. <br>
  30387.  
  30388. <_sul>In-lining of Routine Calls</_sul>
  30389.  
  30390. </font>
  30391. <p>
  30392.  If you have a routine that is rather small and fast, but is called a huge 
  30393.  number of times, you will save time by doing the operation
  30394.  <_bq><i>in-line</i></_bq>, rather than calling the routine. Your code may
  30395.  become less readable, so it might be better to in-line only at places that
  30396.  generate a lot of calls to the routine.
  30397.  
  30398. <p>
  30399.  
  30400. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30401. <br>
  30402.  
  30403. <_sul>Operations on Sequences</_sul>
  30404.  
  30405. </font>
  30406. <p>
  30407.  Euphoria lets you operate on a large sequence of data using a single
  30408.  statement. This saves you from writing a loop where you process one element
  30409.  at-a-time. e.g.
  30410. <_eucode>
  30411.         x = {1,3,5,7,9}
  30412.         y = {2,4,6,8,10}
  30413.  
  30414.         z = x + y
  30415. </_eucode>
  30416.  
  30417.  versus:
  30418. <_eucode>
  30419.         z = repeat(0, 5)  -- if necessary
  30420.         for i = 1 to 5 do
  30421.             z[i] = x[i] + y[i]
  30422.         end for
  30423. </_eucode>
  30424. <p>
  30425.  In most interpreted languages, it is much faster to process a whole sequence 
  30426.  (array) in one statement, than it is to perform scalar operations
  30427.  in a loop. This is because the 
  30428.  interpreter has a large amount of overhead for each statement it executes.
  30429.  Euphoria is different. Euphoria is very lean, with little 
  30430.  interpretive overhead, so operations on sequences don't always win. 
  30431.  The only solution is to time it both ways. The per-element cost is usually
  30432.  lower when you process a sequence in one statement, but there are overheads 
  30433.  associated with allocation and deallocation of sequences that 
  30434.  may tip the scale the other way.
  30435.  
  30436. <p>
  30437.  
  30438. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30439. <br>
  30440.  
  30441. <_sul>Some Special Case Optimizations</_sul>
  30442.  
  30443. </font>
  30444. <p>
  30445.  Euphoria automatically optimizes certain special cases. x and y below could 
  30446.  be variables or arbitrary expressions.
  30447. <_eucode>
  30448.         x + 1      -- faster than general x + y
  30449.         1 + x      -- faster than general y + x
  30450.         x * 2      -- faster than general x * y
  30451.         2 * x      -- faster than general y * x
  30452.         x / 2      -- faster than general x / y
  30453.         floor(x/y) -- where x and y are integers, is faster than x/y
  30454.         floor(x/2) -- faster than floor(x/y)
  30455. </_eucode>
  30456. <p>
  30457.  x below is a simple variable, y is any variable or expression:  
  30458. <_eucode>
  30459.         x = append(x, y)   -- faster than general z = append(x, y)
  30460.         x = prepend(x, y)  -- faster than general z = prepend(x, y)
  30461.  
  30462.         x = x & y          -- where x is much larger than y,
  30463.                            -- is faster than general z = x & y
  30464. </_eucode>
  30465.  
  30466. When you write a loop that "grows" a sequence, by appending or
  30467. concatenating data onto it, the time will, in general, grow in proportion
  30468. to the <b>square</b> of the number (N) of elements you are adding.
  30469. However, if you can use one of the special optimized forms of append(),
  30470. prepend() or concatenation listed above, the time will grow in proportion
  30471. to just N (roughly). This could save you a <b>huge</b> amount of time
  30472. when creating an extremely long sequence.
  30473. (You could also use repeat() to establish the maximum size
  30474. of the sequence, and then fill in the elements in a loop, as discussed
  30475. below.)
  30476. <p>
  30477. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30478. <br>
  30479.  
  30480. <_sul>Assignment with Operators</_sul>
  30481.  
  30482. </font>
  30483. <p>
  30484.  For greater speed, convert:
  30485. <pre>
  30486.         <b>left-hand-side = left-hand-side op expression</b>
  30487. </pre>
  30488.  to:
  30489. <pre>
  30490.         <b>left-hand-side op= expression</b>
  30491. </pre>
  30492.  
  30493.  whenever left-hand-side contains at least 2 subscripts, or at least
  30494.  one subscript and a slice. In all simpler cases the two forms run at 
  30495.  the same speed (or very close to the same).
  30496.  
  30497. <p>
  30498.  
  30499. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30500. <br>
  30501.  
  30502. <_sul>Pixel-Graphics Tips</_sul>
  30503.  
  30504. </font>
  30505. <ul>
  30506. <li>
  30507.  Mode 19 is the fastest mode for
  30508.  <font color="#009999"><b>animated graphics</b></font> and
  30509.  <font color="#009999"><b>games</b></font>.
  30510. <p>
  30511. <li>
  30512.  The video memory (in mode 19) is not cached by the CPU. It usually takes longer
  30513.    to read or write data to the screen than to a general area of memory that
  30514.    you allocate. This adds to the efficiency of
  30515.    <font color="#CC0099"><_bq><i>virtual</i></_bq> <b>screens</b></font>, where
  30516.    you do all of your image updating in a <b>block of memory</b> that you
  30517.    get from <font color="#006699"><b>allocate()</b></font>, and then you
  30518.    periodically <font color="#006699"><b>mem_copy()</b></font> the resulting
  30519.    image to the real <b>screen memory</b>. In this way you never have to
  30520.    read the (slow) screen memory.
  30521. <p>
  30522. <li>
  30523.  When plotting pixels, you may find that modes 257 and higher are fast near
  30524.    the top of the screen, but slow near the bottom.
  30525.  
  30526. </ul>
  30527.  
  30528. <p>
  30529.  
  30530. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30531. <br>
  30532.  
  30533. <_sul>Text-Mode Tips</_sul>
  30534.  
  30535. </font>
  30536. <p>
  30537.  Writing text to the screen using <font color="#006699"><b>puts()</b></font>
  30538.  or <font color="#006699"><b>printf()</b></font> is rather slow.
  30539.  If necessary, in <font color="#CC3366"><b>DOS32</b></font>, you can do it much faster by poking into the
  30540.  <b>video memory</b>, or by using
  30541.  <font color="#006699"><b>display_text_image()</b></font>. There is a very
  30542.  large overhead on each puts() to the screen, and a relatively small
  30543.  incremental cost per character. The overhead with
  30544.  <font color="#993333"><b>exw</b></font> is especially high (on Windows 95/98
  30545.  at least). Linux is somewhere between DOS32 and WIN32 in text output
  30546.  speed. It therefore makes sense
  30547.  to build up a long string before calling puts(), rather than calling it 
  30548.  for each character. There is no advantage to building up a string 
  30549.  longer than one line however. 
  30550.  <p>  
  30551.  The slowness of text output is mainly due to operating system overhead. 
  30552.  
  30553. <p>
  30554.  
  30555. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30556. <br>
  30557.  
  30558. <_sul>Library Routines</_sul>
  30559.  
  30560. </font>
  30561. <p>
  30562.  Some common routines are extremely fast. You probably couldn't do the job 
  30563.  faster any other way, even if you used C or assembly language. Some of these 
  30564.  are:
  30565. <ul>
  30566. <li>
  30567.      <font color="#006699"><b>mem_copy()</b></font>
  30568. <li>
  30569.      <font color="#006699"><b>mem_set()</b></font>
  30570. <li>
  30571.      <font color="#006699"><b>repeat()</b></font>
  30572. </ul>
  30573. <p>
  30574.  Other routines are reasonably fast, but you might be able
  30575.  to do the job faster in some cases if speed was crucial.
  30576. <_eucode>
  30577.         x = repeat(0,100)
  30578.         for i = 1 to 100 do
  30579.             x[i] = i
  30580.         end for
  30581. </_eucode>
  30582.  
  30583.  is somewhat faster than:
  30584. <_eucode>
  30585.         x = {}
  30586.         for i = 1 to 100 do
  30587.             x = append(x, i)
  30588.         end for
  30589. </_eucode>
  30590.  
  30591.  because <font color="#006699">append()</font> has to allocate and reallocate
  30592.  space as x grows in size. With <font color="#006699">repeat()</font>, the
  30593.  space for x is allocated once at the beginning. (append() is smart enough
  30594.  not to allocate space with <_ba><i>every</i></_ba> append to x.
  30595.  It will allocate somewhat more than it needs, to reduce the number of
  30596.  reallocations.)
  30597. <p>
  30598.  You can replace:
  30599. <_eucode>
  30600.         remainder(x, p)
  30601. </_eucode>
  30602.  
  30603.  with:
  30604. <_eucode>
  30605.         and_bits(x, p-1)
  30606. </_eucode>
  30607.  
  30608.  for greater speed when p is a positive power of 2. x must be a non-negative
  30609.  integer that fits in 32-bits.
  30610. <p>
  30611.  <font color="#006699"><b>arctan()</b></font> is faster than
  30612.  <font color="#006699"><b>arccos()</b></font> or
  30613.  <font color="#006699"><b>arcsin()</b></font>.
  30614.  
  30615. <p>
  30616.  
  30617. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30618. <br>
  30619.  
  30620. <_sul>Searching</_sul>
  30621.  
  30622. </font>
  30623. <p>
  30624.  Euphoria's <font color="#006699"><b>find()</b></font> is the fastest way
  30625.  to search for a value in a sequence up to about 50 elements. Beyond that,
  30626.  you might consider a <i>hash table</i>
  30627.  (<font color="#5500FF"><b>demo\hash.ex</b></font>) or a
  30628.  <i>binary tree</i> (<font color="#5500FF"><b>demo\tree.ex</b></font>).
  30629.  
  30630. <p>
  30631.  
  30632. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30633. <br>
  30634.  
  30635. <_sul>Sorting</_sul>
  30636.  
  30637. </font>
  30638. <p>
  30639.  In most cases you can just use the <i>shell sort</i> routine in
  30640.  <font color="#5500FF"><b>include\sort.e</b></font>. 
  30641. <p>
  30642.  If you have a huge amount of data to sort, you might try one of the sorts 
  30643.  in <font color="#5500FF"><b>demo\allsorts.e</b></font> (e.g.
  30644.  <i><_bq>great</_bq> sort</i>). If your data is too big to fit in 
  30645.  memory, don't rely on Euphoria's automatic memory swapping capability. 
  30646.  Instead, sort a few thousand records at a time, and write them out to a 
  30647.  series of temporary files. Then merge all the sorted temporary files into 
  30648.  one big sorted file. 
  30649. <p>
  30650.  If your data consists of integers only, and they are all in a fairly 
  30651.  narrow range, try the <i>bucket sort</i> in
  30652.  <font color="#5500FF"><b>demo\allsorts.e</b></font>.
  30653.  
  30654. <p>
  30655.  
  30656. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30657. <br>
  30658.  
  30659. <_sul>Taking Advantage of Cache Memory</_sul>
  30660.  
  30661. </font>
  30662. <p>
  30663.  As CPU speeds increase, the gap between the speed of the on-chip cache 
  30664.  memory and the speed of the main memory or DRAM (dynamic random access memory)
  30665.  becomes ever greater. You might have 32 Mb of DRAM on your computer, but the 
  30666.  on-chip cache is likely to be only 8K (data) plus 8K (instructions) on a 
  30667.  Pentium, or 16K (data) plus 16K (instructions) on a Pentium with MMX or a
  30668.  Pentium II/III. Most machines will also have a "level-2" cache of 256K or 512K.
  30669. <p>
  30670.  An algorithm that steps through a long sequence of a couple of thousand
  30671.  (4-byte) elements or more, many times, from beginning to end, performing one 
  30672.  small operation on each element, will not make good use of the on-chip data 
  30673.  cache. It might be better to go through once, applying several operations to 
  30674.  each element, before moving on to the next element. The same argument holds 
  30675.  when your program starts swapping, and the least-recently-used data is moved 
  30676.  out to disk.
  30677. <p>
  30678.  These cache effects aren't as noticeable in Euphoria as they are in
  30679.  lower-level compiled languages, but they are measurable.
  30680.  
  30681. <p>
  30682.  
  30683. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30684. <br>
  30685.  
  30686. <_sul>Using Machine Code and C</_sul>
  30687.  
  30688. </font>
  30689. <p>
  30690.  Euphoria lets you call routines written in 32-bit Intel machine code. On
  30691.  <font color="#CC3366"><b>WIN32</b></font> and
  30692.  <font color="#CC3366"><b>Linux</b></font> 
  30693.  you can call C routines in
  30694.  <b>.</b>dll or <b>.</b>so files, and these C routines can call your Euphoria routines.
  30695.  You might need to call C or machine code because of something that can't be
  30696.  done directly in Euphoria, or you might do it for improved speed.
  30697. <p>
  30698.  To boost speed, the machine code or C routine needs to do a significant 
  30699.  amount of work on each call, otherwise the overhead of setting up the 
  30700.  arguments and making the call will dominate the time, and it might not 
  30701.  gain you much.
  30702. <p>
  30703.  Many programs have some inner core operation that consumes most of the
  30704.  CPU time. If you can code this in C or machine code, while leaving the
  30705.  bulk of the program in Euphoria, you might achieve a speed comparable
  30706.  to C, without sacrificing Euphoria's safety and flexibility.
  30707.  
  30708. <p> 
  30709.  
  30710. </_width>
  30711. </body>
  30712. </html>
  30713. PLATFORM.HTX
  30714. 24395
  30715. <_init_comment>
  30716. <html>
  30717. <head><title>Platform-Specific Issues for Euphoria</title>
  30718. </head>
  30719. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  30720. <_width>
  30721. <_center><font face="Arial, Helvetica" color="#FF0099" size=+2>
  30722. <br>
  30723.                   Platform-Specific Issues for Euphoria
  30724. </font></_center>
  30725. <p>
  30726.  
  30727. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30728. <br>
  30729.  
  30730. <_dul>1. Introduction</_dul>
  30731.  
  30732. </font>
  30733. <p>
  30734.  Euphoria programs can currently run on three different
  30735.  <font color="#993333"><_bq><i>platforms</i></_bq></font>. More 
  30736.  platforms will be added in the future. The first platform is called
  30737.  <font color="#CC3366"><b>DOS32</b></font>, 
  30738.  since it depends on the DOS operating system, but with the CPU operating 
  30739.  in 32-bit (protected) mode. 
  30740.  
  30741. <p>
  30742.  The second platform is called <font color="#CC3366"><b>WIN32</b></font>,
  30743.  since the underlying operating system is Microsoft Windows, in particular,
  30744.  the 32-bit version of Windows that is used on Windows 95/98 and Windows NT. 
  30745.  
  30746. <p>
  30747.  The third platform is <font color="#CC3366"><b>Linux</b></font>. Linux is
  30748.  based on the UNIX operating system. It has recently become very popular 
  30749.  on PCs. Linux on the PC is also a 32-bit system.
  30750.  
  30751. <p> 
  30752.  The Euphoria for DOS32+WIN32 .zip file contains two <b>.exe</b> files. 
  30753.  The first is called <font color="#993333"><b>ex.exe</b></font>.
  30754.  It runs Euphoria programs on the DOS32 platform. The second is
  30755.  <font color="#993333"><b>exw.exe</b></font>.
  30756.  It runs Euphoria programs on the WIN32 platform. 
  30757.  Euphoria programs that are
  30758.  meant to be run on the WIN32 platform have a <b>.exw</b> file type,
  30759.  while programs that are meant to be run on the DOS32 platform have a
  30760.  <b>.ex</b> file type.
  30761.  <p> 
  30762.  The Euphoria for Linux .tar file contains only 
  30763.  <font color="#993333"><b>exu</b></font>. It runs
  30764.  Euphoria programs on the Linux platform.
  30765.  Euphoria programs intended for Linux have a <b>.exu</b> file type. 
  30766.  <p>
  30767.  Many Euphoria programs can be run on two, or all three platforms without
  30768.  change. The file type should indicate the preferred platform for the program.
  30769.  Any Euphoria interpreter will try to run any Euphoria file. You just
  30770.  have to specify the full name of the file, including the type.
  30771.  <p>
  30772.  Sometimes you'll find that the majority of your code will be the 
  30773.  same on all platforms, but some small parts will have to be 
  30774.  written differently for each platform. Use the
  30775.  <a href=lib_p_r.htm#platform>platform()</a> built-in function to 
  30776.  tell you which platform you are currently running on.
  30777.  
  30778.  
  30779. <p>
  30780.  
  30781. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30782. <br>
  30783.  
  30784. <_dul>2. The DOS32 Platform</_dul>
  30785.  
  30786. </font>
  30787. <p>
  30788.  If you are new to programming, you should start off with
  30789.  <font color="#993333"><b>ex.exe</b></font> on the
  30790.  DOS32 platform, or perhaps
  30791.  <font color="#993333"><b>exu</b></font>
  30792.  on the Linux platform. Windows programming is somewhat more complicated, no 
  30793.  matter which language you use.
  30794.  
  30795. <p> 
  30796.  <font color="#006633"><b>Programs run in 32-bit (protected) mode and
  30797.  have access to all of the megabytes of memory on the machine.</b></font>
  30798.  Most programming languages for DOS limit 
  30799.  you to 16-bit <_bq>real</_bq> mode. This makes it impossible to
  30800.  access more than 640K 
  30801.  of memory at one time. Your machine might have 32Mb of memory, but your 
  30802.  program will run out of memory after using 640K. QBasic is even worse. It 
  30803.  limits you to just 160K.
  30804.  
  30805.  <p>
  30806.  DOS32 programs are typically run with the screen in either
  30807.  <font color="#CC3366">text mode</font> or 
  30808.  <font color="#CC3366">pixel graphics mode</font>, and there is a large
  30809.  library of Euphoria routines that 
  30810.  you can call. There is rarely any need to call DOS directly, but you can do 
  30811.  this using the <a href="lib_c_d.htm#dos_interrupt">dos_interrupt()</a>
  30812.  routine. You can also <a href="lib_p_r.htm#peek">peek</a> and
  30813.  <a href="lib_p_r.htm#poke">poke</a> into 
  30814.  special memory locations to achieve high-speed graphics and get access 
  30815.  to low-level details of the system.
  30816.  
  30817.  <p>
  30818.  Under <font color="#CC3366"><b>DOS32 for Windows 95/98</b></font>,
  30819.  Euphoria files can have long filenames, and 
  30820.  programs can open long filename files for reading and writing, but not for 
  30821.  creating a new file.
  30822.  
  30823.  <p>
  30824.  <a name=swapfile></a>
  30825.  Under <font color="#CC3366"><b>pure DOS, outside of Windows</b></font>,
  30826.  there is no system <a href="refman_1.htm#32">swap file</a> so the
  30827.  DOS-extender built in to <font color="#993333"><b>ex.exe</b></font> will
  30828.  create one for possible use by your program. 
  30829.  This file is created when your Euphoria program starts up under DOS,
  30830.  and is deleted when your program terminates. It starts as a 0-byte file and 
  30831.  grows only if actual swapping is needed. It is created in the directory on 
  30832.  your hard disk pointed to by the TEMP or TMP environment variable. If neither
  30833.  of these variables have been set, it is created in the directory containing 
  30834.  either <font color="#993333"><b>ex.exe</b></font> or your
  30835.  <font color="#993333"><_bq>bound</_bq></font> Euphoria <b>.exe</b> file.
  30836.  You can force it to be created in a particular directory by setting the
  30837.  CAUSEWAY environment variable as follows:
  30838.      
  30839. <_eucode>
  30840.         SET CAUSEWAY=SWAP:path
  30841. </_eucode>
  30842.  
  30843.  where   <b>path</b>   is the full path to the directory. You can
  30844.  prevent the creation of a DOS swap file with:
  30845.  
  30846. <_eucode>
  30847.         SET CAUSEWAY=NOVM
  30848. </_eucode>
  30849.  
  30850. <p>
  30851.  When disk swapping activity occurs, your program will run correctly but will 
  30852.  slow down. A better approach might be to free up more extended memory by 
  30853.  cutting back on SMARTDRV and other programs that reserve large amounts of 
  30854.  extended memory for themselves.
  30855.  
  30856. <p>
  30857.  When your free disk space is less than the amount of RAM in your machine,
  30858.  no swap file will be created.
  30859.  
  30860. <p>
  30861. <a name=win32plat></a>
  30862. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30863. <br>
  30864.  
  30865. <_dul>3. The WIN32 Platform</_dul>
  30866.  
  30867. </font>
  30868. <p>
  30869.  Euphoria for WIN32 (<font color="#993333"><b>exw.exe</b></font>) has a
  30870.  lot in common with Euphoria for DOS32. 
  30871.  With WIN32 you also have access to all of the memory on your machine.
  30872.  Most library routines work the same way on each platform. Many existing 
  30873.  DOS32 <font color="#CC3366">text mode</font> programs can be run using
  30874.  <font color="#993333"><b>exw</b></font> without any change. With
  30875.  <font color="#993333"><b>exw</b></font> you can run programs from the
  30876.  command line, and display text on a standard 
  30877.  (typically 25 line x 80 column) DOS window. The DOS window is known as the
  30878.  <_bq><i>console</i></_bq> in Windows terminology. Euphoria makes the
  30879.  transition from DOS32 <font color="#CC3366">text mode</font> programming,
  30880.  to simple WIN32 console programming, trivial.
  30881.  <font color="#006633"><b>You can add calls to WIN32 C functions and later,
  30882.  if desired, you can create real Windows GUI windows.</b></font>
  30883.  
  30884.  <p>
  30885.  A console window will be created automatically when a WIN32 Euphoria program 
  30886.  first outputs something to the screen or reads from the keyboard. Currently,
  30887.  you will also see a console window when you read standard input or write to 
  30888.  standard output, even when these have been redirected to files. The console
  30889.  will disappear when your program finishes execution, or via a call to 
  30890.  <a href="lib_e_g.htm#free_console">free_console()</a>.
  30891.  If there is something on the console that you want your
  30892.  user to read, you should prompt him and wait for his input before terminating.
  30893.  To prevent the console from quickly disappearing you might include a statement
  30894.  such as:
  30895.  
  30896. <_eucode>
  30897.         if getc(0) then
  30898.         end if
  30899. </_eucode>
  30900.  which will wait for the user enter something.
  30901.  
  30902. <p>
  30903.  Under WIN32, long filenames are fully supported for reading and writing and
  30904.  creating.
  30905.  
  30906. <p>
  30907.  
  30908. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30909. <br>
  30910.  
  30911. <_sul>3.1 High-Level WIN32 Programming</_sul>
  30912.  
  30913. </font>
  30914. <p>
  30915.  Thanks to <b>David Cuny</b>, there is a package called <b>Win32Lib</b> that
  30916.  you can use to develop Windows GUI applications in Euphoria. It is
  30917.  remarkably easy to learn and use, and comes with good documentation and
  30918.  many small example programs. You can download the file win32lib.zip from
  30919.  the Euphoria <a href="http://www.RapidEuphoria.com">Web site</a>.
  30920.  David has also developed a compatible package for DOS32, called
  30921.  <b>Dos32Lib</b>. In many cases you can write a simple program that will
  30922.  work using Win32Lib on Windows, and by changing one include statement,
  30923.  the program will also run on DOS.
  30924.  
  30925. <p>
  30926.  
  30927. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30928. <br>
  30929.  
  30930. <_sul>3.2 Low-Level WIN32 Programming</_sul>
  30931.  
  30932. </font>
  30933. <p>
  30934.  <font color="#006633"><b>To allow access to WIN32 at a lower level, Euphoria
  30935.  provides a mechanism for calling any C function in any WIN32 API .dll file,
  30936.  or indeed in any 32-bit Windows .dll file that you create or someone else
  30937.  creates. There is also a call-back mechanism that lets Windows call your
  30938.  Euphoria routines. Call-backs are necessary when you create a graphical
  30939.  user interface.</b></font>
  30940.  
  30941. <p>
  30942.  To make full use of the WIN32 platform, you need documentation on 32-bit 
  30943.  Windows programming, in particular the WIN32 Application Program Interface 
  30944.  (API), including the C structures defined by the API. There is a large 
  30945.  WIN32.HLP file (c) Microsoft that is available with many programming tools
  30946.  for Windows 95/98 or Windows NT. There are numerous books available on the
  30947.  subject of WIN32 programming for C/C++. You can adapt most of what you find
  30948.  in those books to the world of Euphoria programming for WIN32.
  30949.  A good book is:<p>
  30950.  
  30951. <_center>
  30952.                    <i>Programming Windows 95</i><br>
  30953.                      by Charles Petzold<br>
  30954.                        Microsoft Press<br>
  30955. </_center>
  30956.       
  30957. <p>
  30958.  A WIN32 API Windows help file (8 Mb) can be downloaded from Borland's 
  30959.  Web site:<br>
  30960.         
  30961.  <a href="ftp://ftp.inprise.com/pub/delphi/techpubs/delphi2/win32.zip">
  30962.     ftp://ftp.inprise.com/pub/delphi/techpubs/delphi2/win32.zip</a>
  30963.  
  30964. <p>
  30965.  See also the Euphoria
  30966.  <a href="http://www.RapidEuphoria.com/exestuff.htm">Archive Web
  30967.  page - "documentation"</a>.
  30968.  
  30969. <p>
  30970. <a name=linuxplat></a>
  30971. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  30972. <br>
  30973.  
  30974. <_dul>4. The Linux Platform</_dul>
  30975.  
  30976. </font>
  30977. <p>
  30978. Euphoria for Linux shares certain features with Euphoria for DOS32,
  30979. and shares other features with Euphoria for WIN32. 
  30980. <p>
  30981. As with WIN32 and DOS32, you can write text on a console, or xterm window, 
  30982. in multiple colors and at any line or column position. 
  30983. <p>
  30984. Just as in WIN32, you can call C routines in shared libraries 
  30985. and C code can call back to your Euphoria routines.
  30986. <p>
  30987. Euphoria for Linux does not have integrated support for pixel graphics
  30988. like DOS32, but Pete Eberlein has created a Euphoria interface to 
  30989. <b>svgalib</b>. 
  30990. <p>
  30991. X windows GUI programming is currently possible using Irv Mullin's 
  30992. interface to the <b>graphapp</b> package. David Cuny is planning to port
  30993. his new Llama GUI package from WIN32 to Linux.
  30994. <p>
  30995. When porting code from DOS or Windows to Linux, you'll notice the following
  30996. differences:
  30997. <ul>
  30998. <p>
  30999. <li>Some of the numbers assigned to the 16 main colors in graphics.e 
  31000. are different. If you use the constants defined in graphics.e you won't
  31001. have a problem. If you hard-code your color numbers you will see
  31002. that blue and red have been switched etc.
  31003. <p>
  31004. <li>The key codes for special keys such as Home, End, arrow keys
  31005. are different, and there are some additional differences when you run
  31006. under XTERM.
  31007. <p>
  31008. <li>The Enter key is code 10 (line-feed) on Linux, where on DOS/Windows
  31009. it was 13 (carriage-return).
  31010. <p>
  31011. <li>Linux uses '/' (slash) on file paths. DOS/Windows uses '\\' (backslash).
  31012. <p>
  31013. <li>Highly specialized things such as dos_interrupt() obviously won't
  31014. work on Linux.
  31015. <p>
  31016. <li>Calls to system() and system_exec() that contain DOS commands
  31017. will obviously have to be changed to the corresponding Linux command.
  31018. e.g. "DEL" becomes "rm", and "MOVE" becomes "mv".
  31019. </ul>
  31020.  
  31021.  
  31022. <p>
  31023. <a name=call_cfunc></a>
  31024. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  31025. <br>
  31026. <_dul>5. Interfacing with C Code (WIN32 and Linux)</_dul>
  31027. </font>
  31028. <p>
  31029. On WIN32 and Linux it's possible to interface Euphoria code
  31030. and C code. Your Euphoria program can call C routines and 
  31031. read and write C variables.
  31032. C routines can even call your Euphoria routines. The C code must
  31033. reside in a WIN32 dynamic link library (.dll file), or a Linux
  31034. shared library (.so file).
  31035.  
  31036. By interfacing with .dll's and shared libraries, you can 
  31037. access the full programming interface on both of these systems.
  31038. <p>
  31039.  
  31040. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  31041. <br>
  31042.  
  31043. <_sul>5.1 Calling C Functions</_sul>
  31044.  
  31045. </font>
  31046. <p>
  31047.  To call a C function in a <b>.</b>dll or <b>.</b>so file
  31048.  you must perform the following steps:
  31049.  
  31050. <p>
  31051. <table border=0 cellspacing=2 cellpadding=2>
  31052.  
  31053.  <_2clist
  31054.   name="1."
  31055.   pos=5
  31056.   description="Open the <b>.</b>dll or <b>.</b>so file that contains the C function by
  31057.      calling <a href=\"lib_h_o.htm#open_dll\">open_dll()</a> contained in
  31058.      <font color=\"#5500FF\"><b>euphoria\include\dll.e</b></font>."
  31059.  >
  31060.  
  31061. <_2clist
  31062.   name="2."
  31063.   pos=5
  31064.   description="Define the C function, by calling
  31065.       <a href=\"lib_c_d.htm#define_c_func\">define_c_func()</a> or
  31066.       <a href=\"lib_c_d.htm#define_c_proc\">define_c_proc()</a> in
  31067.       <font color=\"#5500FF\"><b>dll.e</b></font>. This tells Euphoria the
  31068.       number and type of the arguments as well as the type of value returned. 
  31069.       <p>
  31070.       Euphoria currently supports all C integer and pointer types as 
  31071.       arguments and return values. It also supports floating-point arguments 
  31072.       and return values (C double type). It is currently not possible to 
  31073.       pass C structures by value or receive a structure as a function 
  31074.       result, although you can certainly pass a pointer to a structure
  31075.       and get a pointer to a structure as a return value. Passing C
  31076.       structures by value is hardly ever required in Linux or the WIN32 API."
  31077. >
  31078.  
  31079. <_2clist
  31080.   name="3."
  31081.   pos=5
  31082.   description="Call the C function by calling
  31083.       <a href=\"lib_c_d.htm#c_func\">c_func()</a> or
  31084.       <a href=\"lib_c_d.htm#c_proc\">c_proc()</a>."
  31085. >
  31086.  
  31087. </table>
  31088.  
  31089. <p>
  31090. <table border=0 cellspacing=2 cellpadding=2>
  31091.  
  31092. <_2clist
  31093.   name="Example:"
  31094.   pos=13
  31095.   description=""
  31096. >
  31097. <_eucode>
  31098. include dll.e
  31099.  
  31100. atom user32
  31101. integer LoadIcon, icon
  31102.  
  31103. user32 = open_dll("user32.dll")
  31104.  
  31105. -- The name of the routine in user32.dll is "LoadIconA".
  31106. -- It takes a pointer and an int as arguments, 
  31107. -- and it returns an int.
  31108. LoadIcon = define_c_func(user32, "LoadIconA",
  31109.                          {C_POINTER, C_INT}, C_INT)
  31110.  
  31111. icon = c_func(LoadIcon, {NULL, IDI_APPLICATION})
  31112. </_eucode>
  31113.  
  31114. </table>
  31115.  
  31116. <p> 
  31117.  See <a href="library.htm#call_c_func"><font color="#5500FF"><b>library.doc</b>
  31118.  </font></a> for descriptions of c_func(), c_proc(), define_c_func(), 
  31119.  define_c_proc(), open_dll() etc.
  31120.  See 
  31121.  <font color="#5500FF"><b>demo\win32</b></font> or
  31122.  <font color="#5500FF"><b>demo\linux</b></font> 
  31123.  for example programs.
  31124.  
  31125. <p> 
  31126.  You can examine a <b>.</b>dll file by right-clicking on it, and choosing
  31127.  "QuickView" (if it's on your system). You will see a list of all the C
  31128.  routines that the <b>.</b>dll exports.
  31129. <p>
  31130.  To find out which <b>.</b>dll file contains a particular WIN32 C function,
  31131.  run <font color="#5500FF"><b>euphoria\demo\win32\dsearch.exw</b></font>.
  31132.  
  31133. <p>
  31134.  
  31135. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  31136. <br>
  31137.  
  31138. <_sul>5.2 Accessing C Variables</_sul>
  31139.  
  31140. </font>
  31141. <p>
  31142. In Linux, you can get the address of a C variable using 
  31143. <a href="lib_c_d.htm#define_c_var">define_c_var()</a>.
  31144. You can then use poke() and peek() to access the value of the variable.
  31145.  
  31146. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  31147. <p>
  31148. <br>
  31149.  
  31150. <_sul>5.3 Accessing C Structures</_sul>
  31151.  
  31152. </font>
  31153. <p>
  31154.  Many C routines require that you pass pointers to structures. You can
  31155.  simulate C structures using allocated blocks of memory. The address
  31156.  returned by <a href="lib_a_b.htm#allocate">allocate()</a> can be passed
  31157.  as if it were a C pointer.
  31158. <p>
  31159.  You can read and write members of C structures using peek() and poke(), or
  31160.  <a href="lib_p_r.htm#peek4u">peek4u()</a>,
  31161.  <a href="lib_p_r.htm#peek4s">peek4s()</a>, and
  31162.  <a href="lib_p_r.htm#poke4">poke4()</a>. You can allocate space for
  31163.  structures using <a href="lib_a_b.htm#allocate">allocate()</a>.
  31164.  You must calculate the offset of a member of a C structure. This is usually
  31165.  easy, because anything in C that needs 4 bytes will be assigned 4 
  31166.  bytes in the structure. Thus C int's, char's, unsigned int's, pointers to 
  31167.  anything, etc. will all take 4 bytes. If the C declaration looks like:
  31168. <pre>
  31169.         // Warning C code ahead!
  31170.  
  31171.         struct example {
  31172.             int a;           // offset  0
  31173.             char *b;         // offset  4
  31174.             char c;          // offset  8
  31175.             long d;          // offset 12
  31176.         };
  31177. </pre>
  31178.  
  31179. <p>
  31180.  To allocate space for "struct example" you would need:
  31181. <_eucode>
  31182.         atom p
  31183.  
  31184.         p = allocate(16) -- size of "struct example"
  31185. </_eucode>
  31186.  
  31187. <p>
  31188.  The address that you get from allocate() is always at least 4-byte aligned.
  31189.  This is useful, since WIN32 structures are supposed to start on a 
  31190.  4-byte boundary. Fields within a C structure that are 4-bytes or more in size 
  31191.  must start on a 4-byte boundary in memory. 2-byte fields must start on a 
  31192.  2-byte boundary. To achieve this you may have to leave small gaps within
  31193.  the structure. In practice it is not hard to align most structures since
  31194.  90% of the fields are 4-byte pointers or 4-byte integers.
  31195.  
  31196. <p>
  31197.  You can set the fields using something like:
  31198. <_eucode>
  31199.         poke4(p + 0, a)
  31200.         poke4(p + 4, b)
  31201.         poke4(p + 8, c)
  31202.         poke4(p +12, d)
  31203. </_eucode>
  31204.  
  31205.  You can read a field with something like:
  31206. <_eucode>
  31207.         d = peek4(p+12)
  31208. </_eucode>
  31209.  
  31210. <dl>
  31211. <dt>
  31212.   <b><font color="#006633"><_sul>Tip:</_sul></font></b>
  31213. <dd>
  31214.   For readability, make up Euphoria constants for the field offsets.
  31215.   See Example below.
  31216.  
  31217. </dl>
  31218.  
  31219. <p>
  31220. <table border=0 cellspacing=2 cellpadding=2>
  31221.  
  31222. <_2clist
  31223.   name="Example:"
  31224.   pos=13
  31225.   description=""
  31226. >
  31227. <_eucode>
  31228. constant RECT_LEFT = 0,
  31229.          RECT_TOP  = 4,
  31230.          RECT_RIGHT = 8,
  31231.          RECT_BOTTOM = 12
  31232.          
  31233. atom rect
  31234. rect = allocate(16)
  31235.  
  31236. poke4(rect + RECT_LEFT,    10)
  31237. poke4(rect + RECT_TOP,     20)
  31238. poke4(rect + RECT_RIGHT,   90)
  31239. poke4(rect + RECT_BOTTOM, 100)
  31240.      
  31241. -- pass rect as a pointer to a C structure
  31242. -- hWnd is a "handle" to the window
  31243. if not c_func(InvalidateRect, {hWnd, rect, 1}) then
  31244.     puts(2, "InvalidateRect failed\n")
  31245. end if
  31246. </_eucode>
  31247.  
  31248. </table>
  31249.  
  31250. The Euphoria code that accesses C routines and data structures
  31251. may look a bit ugly, but it will typically form just a small
  31252. part of your program, especially if you use Win32Lib, 
  31253. VEL, or Irv Mullin's X Windows library. 
  31254. Most of your program will be written in pure Euphoria,
  31255. which will give you a big advantage over C.
  31256. <p>
  31257.  
  31258. <a name=callback></a>
  31259. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  31260. <br>
  31261.  
  31262. <_sul>5.4 Call-backs to your Euphoria routines</_sul>
  31263.  
  31264. </font>
  31265. <p>
  31266.  When you create a window, the Windows operating system will need to call your 
  31267.  Euphoria routine. This is a strange concept for DOS programmers who are used
  31268.  to calling operating system routines, but are not used to having the operating
  31269.  system call <font color="#CC0099"><_ba><i>their</i></_ba></font> routine.
  31270.  To set this up, you must get a 32-bit "call-back" 
  31271.  address for your routine and give it to Windows. For example (taken from 
  31272.  <font color="#5500FF"><b>demo\win32\window.exw</b></font>):
  31273. <_eucode>
  31274.         integer id
  31275.         atom WndProcAddress
  31276.         
  31277.         id = routine_id("WndProc") 
  31278.  
  31279.         WndProcAddress = call_back(id)
  31280. </_eucode>
  31281.  
  31282.  <a href="lib_p_r.htm#routine_id">routine_id()</a> uniquely identifies a
  31283.  Euphoria procedure or function by returning a small integer value. This
  31284.  value can be used later to call the routine. You can also use it as an
  31285.  argument to the <a href="lib_c_d.htm#call_back">call_back()</a>
  31286.  function.
  31287.  
  31288. <p>
  31289.  In the example above, The 32-bit <i>call-back address</i>, WndProcAddress, 
  31290.  can be stored in a C structure and passed to Windows via the
  31291.  RegisterClass() C API function.
  31292.  <font color="#006633"><b>This gives Windows the ability to 
  31293.  call the Euphoria routine, WndProc(), whenever the user performs an action on 
  31294.  a certain class of window.</b></font> Actions include clicking the mouse,
  31295.  typing a key, resizing the window etc.</i> See the
  31296.  <font color="#5500FF"><b>window.exw</b></font> demo program for the whole 
  31297.  story. 
  31298.  
  31299. <dl>
  31300. <dt>
  31301.         <b><font color="#006633"><_sul>Note:</_sul></font></b>
  31302. <dd>
  31303.  It is possible to get a <i>call-back address</i> for
  31304.  <font color="#CC0099"><b><i>any</i></b></font> Euphoria
  31305.  routine that meets the following conditions:
  31306.  
  31307. <ul>
  31308. <li>
  31309.         the routine must be a function, not a procedure
  31310. <li>
  31311.         it must have from 0 to 8 parameters
  31312. <li>
  31313.         the parameters should all be of type atom (or integer etc.),
  31314.         not sequence
  31315. <li>
  31316.         the return value should be an integer value up to 32-bits in size
  31317. </ul>
  31318. </dl>
  31319.  
  31320.  You can create as many call-back addresses as you like, but you should
  31321.  not call <a href="lib_c_d.htm#call_back">call_back()</a> for the same
  31322.  Euphoria routine multiple times - each call-back address that
  31323.  you create requires a small block of memory.
  31324.  
  31325. <p>
  31326.  The values that are passed to your Euphoria routine can be any 32-bit
  31327.  <_bq>unsigned</_bq> atoms, i.e. non-negative. Your routine could
  31328.  choose to interpret large positive numbers as negative if that is desirable.
  31329.  For instance,
  31330.  if a C routine tried to pass you -1, it would appear as hex FFFFFFFF.
  31331.  If a value is passed that does not fit the type you have chosen for a 
  31332.  given parameter, a Euphoria type-check error may occur (depending on 
  31333.  <a href="refman_2.htm#62">
  31334.  <_bq><font color="#993333">with/without type_check</font></_bq></a> etc.) 
  31335.  No error will occur if you declare all
  31336.  parameters as <font color="#993333"><_bq>atom</_bq></font>.
  31337.  
  31338. <p>
  31339.  Normally, as in the case of WndProc() above, Windows initiates these
  31340.  call-backs to your routines. <font color="#006633"><b>It is also
  31341.  possible for a C routine in any .dll to call one of your Euphoria
  31342.  routines.</b></font> You just have to declare the C routine properly,
  31343.  and pass it the call-back address. 
  31344.  
  31345. <p>
  31346.  Here's an example of a WATCOM C routine that takes your call-back address as 
  31347.  its only parameter, and then calls your 3-parameter Euphoria routine:
  31348.  
  31349. <pre>
  31350.         /* 1-parameter C routine that you call from Euphoria */
  31351.         unsigned EXPORT APIENTRY test1(
  31352.                  LRESULT CALLBACK (*eu_callback)(unsigned a,
  31353.                                                  unsigned b,
  31354.                                                  unsigned c))
  31355.         {
  31356.             /* Your 3-parameter Euphoria routine is called here 
  31357.                via eu_callback pointer */
  31358.             return (*eu_callback)(111, 222, 333); 
  31359.         }
  31360. </pre>
  31361.  
  31362.  The C declaration above declares test1 as an externally-callable C 
  31363.  routine that takes a single parameter. The single parameter is a pointer 
  31364.  to a routine that takes 3 unsigned parameters - i.e. your Euphoria routine.
  31365.  
  31366. <p>
  31367.  In WATCOM C, "CALLBACK" is the same as "__stdcall", i.e "standard call".
  31368.  This is the calling convention that's used to call WIN32 API routines,
  31369.  and the C pointer to your Euphoria routine must be declared this way too,
  31370.  or you'll get an error when your Euphoria routine tries to return to 
  31371.  your .DLL.
  31372.  Note that the <i>default</i> calling convention for Windows C compilers is 
  31373.  something different, called "__cdecl".
  31374.  
  31375. <p>
  31376.  In the example above, your Euphoria routine will be passed the 
  31377.  three values 111, 222 and 333 
  31378.  as arguments. Your routine will return a value to test1. That value will then 
  31379.  be immediately returned to the caller of test1 (which could be at some 
  31380.  other place in your Euphoria program).
  31381.  
  31382. <p> 
  31383.  
  31384. </_width>
  31385. </body>
  31386. </html>
  31387.  
  31388. README.HTX
  31389. 20408
  31390. <_init_comment>
  31391. <html>
  31392. <head><title>Euphoria v2.2 Readme</title>
  31393. </head>
  31394. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  31395. <_width>
  31396.  
  31397. <b><pre>
  31398.  ---> <font color="#FF0099">Is this the latest version of Euphoria?</font>
  31399.       Visit:  <a href="http://www.RapidEuphoria.com">http://www.RapidEuphoria.com</a>
  31400.       
  31401.  ---> To install Euphoria see <a href="html/install.htm">install.doc</a>
  31402.       
  31403.  ---> <font color="#FF0099">What's new in this release?</font>
  31404.       See <a href="html/relnotes.htm">relnotes.doc</a> (after installing)
  31405. </pre></b>
  31406.  
  31407. <_center><font face="Arial, Helvetica" color="#006633" size=+2>
  31408. <br>
  31409.                             Euphoria version 2.2<br>
  31410.                              for WIN32 + DOS32<br>
  31411.                              January 14, 2000<br>
  31412. </font></_center>
  31413.  
  31414. <p> <br>
  31415.  
  31416. <table border=0 cellspacing=2 cellpadding=2>
  31417.  
  31418. <_2clist
  31419.   name="<font face=\"Arial, Helvetica\" color=\"#003366\">Welcome to
  31420.    Euphoria! ...</font>"
  31421.   description="<b><font face=\"Arial, Helvetica\" color=\"#FF0099\">E</font><font face=\"Arial, Helvetica\" color=\"#003366\">nd</font>
  31422. <font face=\"Arial, Helvetica\" color=\"#FF0099\">U</font><font face=\"Arial, Helvetica\" color=\"#003366\">ser</font>
  31423. <font face=\"Arial, Helvetica\" color=\"#FF0099\">P</font><font face=\"Arial, Helvetica\" color=\"#003366\">rogramming with</font>
  31424. <font face=\"Arial, Helvetica\" color=\"#FF0099\">H</font><font face=\"Arial, Helvetica\" color=\"#003366\">ierarchical</font>
  31425. <font face=\"Arial, Helvetica\" color=\"#FF0099\">O</font><font face=\"Arial, Helvetica\" color=\"#003366\">bjects for</font>
  31426. <font face=\"Arial, Helvetica\" color=\"#FF0099\">R</font><font face=\"Arial, Helvetica\" color=\"#003366\">obust</font>
  31427. <font face=\"Arial, Helvetica\" color=\"#FF0099\">I</font><font face=\"Arial, Helvetica\" color=\"#003366\">nterpreted</font>
  31428. <font face=\"Arial, Helvetica\" color=\"#FF0099\">A</font><font face=\"Arial, Helvetica\" color=\"#003366\">pplications</font></b>"
  31429. >
  31430.  
  31431. </table>
  31432.  
  31433. <p>
  31434.  Euphoria has come a long way since v1.0 was released in July 1993. There are
  31435.  now several hundred registered users, located in 45 countries around the 
  31436.  world. There are several thousand non-registered users. 
  31437.  Each year has seen significantly more registrations than the year before.
  31438.  There is a Euphoria 
  31439.  <b>newsgroup</b>, alt.lang.euphoria, as well as an automated
  31440.  <b>mailing list</b> with hundreds of users subscribed.
  31441.  The <a href="http://www.RapidEuphoria.com">Euphoria Web site</a> contains
  31442.  over 500 contributed <b>.</b>zip files packed with Euphoria source programs
  31443.  and library routines. Dozens of people have set up their own independent Web
  31444.  pages with Euphoria-related content. Euphoria has been used in a variety of
  31445.  <font color="#009999"><b>commercial programs</b></font>. The
  31446.  <font color="#CC3366"><b>32-bit DOS</b></font> version has been used to create
  31447.  many exciting <font color="#009999"><b>high-speed action games</b></font>,
  31448.  complete with <b>Sound Blaster</b> sound effects.
  31449.  The <font color="#CC3366"><b>32-bit Windows</b></font> version has been used
  31450.  to create numerous <font color="#009999"><b>GUI, utility and
  31451.  Internet-related programs</b></font>. The
  31452.  <font color="#CC3366"><b>Linux</b></font> version has been used to
  31453.  write <font color="#009999"><b>X Windows GUI programs, CGI programs</b></font>, and lots of 
  31454.  useful tools and utilities.
  31455.  
  31456. <p>
  31457.  
  31458. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  31459. <br>
  31460.  
  31461. <_dul>Yet Another Programming Language?</_dul>
  31462.  
  31463. </font>
  31464. <p>
  31465.  Euphoria is a very-high-level programming language with several features that
  31466.  set it apart from the crowd:
  31467. <ul>
  31468. <li>
  31469.  Euphoria programs run on <font color="#CC3366"><b>32-bit extended
  31470.  DOS</b></font>, <font color="#CC3366"><b>32-bit Windows</b></font> and
  31471.  now <font color="#CC3366"><b>Linux</b></font>.
  31472. <p>
  31473. <li>
  31474.  The language is flexible, powerful, and easier to learn than BASIC.
  31475. <p>
  31476. <li>
  31477.  There is no waiting for compiles and links - just edit and run. 
  31478. <p>
  31479. <li>
  31480.  You can create and distribute a royalty-free,
  31481.  <font color="#CC0099"><b>stand-alone .exe</b></font> file.
  31482. <p>
  31483. <li>
  31484.  <font color="#CC0099"><b>Dynamic storage allocation</b></font> is
  31485.  fundamental to Euphoria. Variables grow or shrink in size without the
  31486.  programmer having to worry about allocating and freeing chunks of memory.
  31487.  Elements of an array (Euphoria sequence) can be a dynamic mixture of
  31488.  different types and sizes of data.
  31489. <p>
  31490. <li>
  31491.  Variable types can be as rigid or as flexible as you like. You can specify
  31492.  the precise set of legal values that may be assigned to any variable.
  31493.  <font color="#CC0099"><b>You can easily write generic code that works on any
  31494.  type of data.</b></font>
  31495. <p>
  31496. <li>
  31497.  Euphoria is not a true object-oriented language, but has features that
  31498.  support object-oriented programming. Euphoria is simple, but very powerful.
  31499.  Problems that require dozens of obscure statements in C++, can often be
  31500.  solved in Euphoria with just a few simple statements.
  31501. <p>
  31502. <li>
  31503.  Euphoria provides <font color="#CC0099"><b>extensive run-time error
  31504.  checking</b></font> for<b>:</b> out-of-bounds subscripts, uninitialized
  31505.  variables, bad parameter values for library routines, illegal value assigned
  31506.  to a variable, and many more. If something goes wrong you'll get a full error
  31507.  message, with a traceback and a dump of variable values - no mysterious
  31508.  machine "lockups" or crashes.
  31509. <p>
  31510. <li>
  31511.  Program execution speed is <font color="#CC0099"><b>10 to 20 times
  31512.  faster</b></font> than Microsoft QBasic, and
  31513.  <font color="#CC0099"><b>34 times faster</b></font> than either Perl 
  31514.  or Python.
  31515. <p>
  31516. <li>
  31517.  Euphoria programs are not constrained by any 640K or 64K memory restrictions
  31518.  for which MS-DOS is infamous. The
  31519.  <font color="#CC3366"><b>DOS32</b></font>,
  31520.  <font color="#CC3366"><b>WIN32</b></font> and
  31521.  <font color="#CC3366"><b>Linux</b></font> 
  31522.  versions of Euphoria let you use
  31523.  all of the megabytes of memory on your system seamlessly, and if that isn't
  31524.  enough, a swap file on disk will provide additional virtual memory.
  31525. <p>
  31526. <li>
  31527.  An integrated, easy-to-use, <font color="#993333"><b>full-screen
  31528.  source-level debugger/tracer</b></font> is included.
  31529. <p>
  31530. <li>
  31531.  Both an <font color="#993333"><b>execution-count profiler</b></font>, and a
  31532.  <font color="#993333"><b>time profiler</b></font> are available.
  31533. <p>
  31534. <li>
  31535.  A <font color="#993333"><b>full-screen, multi-file editor</b></font> with
  31536.  color syntax highlighting and auto-completion of Euphoria statements is
  31537.  provided, complete with Euphoria source code that you are free to modify.
  31538. <p>
  31539. <li>
  31540.  A large collection of interesting demo programs written in Euphoria
  31541.  is provided.
  31542. <p>
  31543. <li>
  31544.  There is a large and rapidly growing collection of excellent 3rd party
  31545.  programs and libraries, most with full source code. 
  31546. <p>
  31547. <li>
  31548.  The <font color="#CC3366"><b>DOS32</b></font> implementation of Euphoria
  31549.  on MS-DOS is full and complete. If necessary, you can access DOS
  31550.  software interrupts. You can call machine-code routines. You can even
  31551.  set up your own hardware interrupt handlers. Several high-speed action
  31552.  games, complete with Sound Blaster sound effects have been developed 100%
  31553.  in Euphoria, without the need for any machine code. Some of these games
  31554.  are now in commercial distribution. 
  31555. <p>
  31556. <li>
  31557.  The <font color="#CC3366"><b>WIN32</b></font> implementation of Euphoria
  31558.  lets you access WIN32 API routines, as well as C routines in 32-bit
  31559.  DLLs created by yourself or a 3rd party. With <b>David Cuny</b>'s
  31560.  <b>Win32Lib</b> and other free 3rd-party packages you can easily create
  31561.  Windows GUI and Internet programs in Euphoria.
  31562. <p>
  31563. <li>
  31564.  The <font color="#CC3366"><b>Linux</b></font> implementation of Euphoria
  31565.  lets you access C routines and variables in Linux shared libraries, 
  31566.  for tasks ranging from graphics, to X windows GUI programming, to 
  31567.  Internet CGI programming. The good news is, you'll be 
  31568.  programming in Euphoria, not C.
  31569.  
  31570. </ul>
  31571.  
  31572. <p>
  31573.  
  31574. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  31575. <br>
  31576.  
  31577. <_dul>Who Would Benefit from Using Euphoria?</_dul>
  31578.  
  31579. </font>
  31580. <p>
  31581. <table border=0 cellspacing=2 cellpadding=2>
  31582.  
  31583. <_4clist
  31584.   name="<font color=\"#006699\">novices / students</font>"
  31585.   pos=23
  31586.   description="Euphoria is one of the simplest and easiest of all languages
  31587.    to learn."
  31588. >
  31589.  
  31590. <_4clist
  31591.   name="<font color=\"#006699\">hobbyists</font>"
  31592.   pos=23
  31593.   description="Take a look at some of the <b>games</b> and
  31594.    <b>high-speed graphics demos</b> we've written, then visit the Web site
  31595.    and download some <font color=\"#CC0099\"><b><i>much</i></b></font> better
  31596.    games and demos written by Euphoria users."
  31597. >
  31598.  
  31599. <_4clist
  31600.   name="<font color=\"#006699\">professionals</font>"
  31601.   pos=23
  31602.   description="You can develop a reliable, maintainable, fully-debugged
  31603.    program in <font color=\"#CC0099\"><b><i>much</i></b></font> less time
  31604.    in Euphoria than in C/C++."
  31605. >
  31606.  
  31607. <_4clist
  31608.   name=""
  31609.   pos=23
  31610.   description="Euphoria can be used as a sophisticated batch file language."
  31611. >
  31612.  
  31613. <_4clist
  31614.   name=""
  31615.   pos=23
  31616.   description="Euphoria is great for
  31617.    <font color=\"#CC0099\"><b><i>quick, easy</i></b></font> development of
  31618.    file filters and other <b>utilities</b>."
  31619. >
  31620.  
  31621. <_4clist
  31622.   name=""
  31623.   pos=23
  31624.   description="You can easily develop <b>GUI</b> and <b>Internet
  31625.    programs</b> without needing a 6-week training course."
  31626. >
  31627.  
  31628. <_4clist
  31629.   name=""
  31630.   pos=23
  31631.   description="You can distribute your program royalty-free as a <b>.exe</b>
  31632.    file."
  31633. >
  31634.  
  31635. </table>
  31636.  
  31637. <p>
  31638.  
  31639. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  31640. <br>
  31641.  
  31642. <_dul>Platforms and Editions</_dul>
  31643.  
  31644. </font>
  31645. <p>
  31646.  Euphoria runs on three different platforms,
  31647.  <font color="#CC3366"><b>DOS32</b></font>,
  31648.  <font color="#CC3366"><b>WIN32</b></font> and
  31649.  <font color="#CC3366"><b>Linux</b></font>, 
  31650.  and comes in two different
  31651.  editions: a <font color="#993333"><b>Public Domain Edition</b></font> and
  31652.  a <font color="#993333"><b>Complete Edition</b></font>.
  31653.  Both editions will run any Euphoria program of any size at full speed,
  31654.  and will report all "compile-time" errors such as syntax errors,
  31655.  undeclared variables etc. The Complete (registered) Edition has these
  31656.  <font color="#CC0099"><b><i>extra</i></b></font> features: 
  31657.  
  31658. <ul>
  31659. <li>
  31660.  you can convert any Euphoria program into a
  31661.   <font color="#CC0099"><b>single, stand-alone, tamper-resistant
  31662.   .exe</b></font> file for easy distribution. (See
  31663.   <a href="html/bind.htm"><font color="#5500FF"><b>bind.doc</b></font></a>)
  31664. <p>
  31665. <li>
  31666.  you can <font color="#993333"><b>profile</b></font> any Euphoria program to
  31667.   determine the performance "hot spots" and to find logical errors. Both
  31668.   <font color="#993333"><b>execution-count profiling</b></font>
  31669.   and
  31670.   <font color="#993333"><b>time-profiling</b></font>
  31671.   (<font color="#CC3366"><b>DOS32</b></font> only) are provided.
  31672. <p>
  31673. <li>
  31674.  you can get full diagnostic information for run-time errors in any size of
  31675.   program. The Public Domain Edition provides full run-time diagnostics for
  31676.   programs up to 300 statements in size.
  31677. </ul>
  31678.  
  31679. <p>
  31680.  For programs over 300 statements, a run-time error in this
  31681.  <b>Public Domain Edition</b> will simply cause
  31682.  your program to halt with a brief message. The usual fully-detailed
  31683.  diagnostics, including a dump of all variable values and other debugging
  31684.  information, will not be provided. However, the excellent
  31685.  <font color="#993333"><b>source-level debugger</b></font> will remain fully
  31686.  operational, and you can insert debug print statements the way you would
  31687.  in C/C++ or other languages. Note that C/C++ and other compiled languages
  31688.  do very little checking for run-time errors, and provide very little
  31689.  diagnostic information when a run-time error occurs.
  31690.  <font color="#006633"><b>Your productivity will be much higher,
  31691.  programming in Euphoria.</b></font>
  31692.  
  31693. <dl>
  31694. <dt>
  31695.  <b><font face="Arial, Helvetica" color="#006633" size=-1><_sul>Regarding
  31696.  Statement Count:</_sul></font></b>
  31697. <dd>
  31698.  Blank-lines and comments are not counted, and the standard include files
  31699.  in <font color="#5500FF"><b>euphoria\include</b></font> are
  31700.  <font color="#CC0099"><b>free</b></font> (if not altered significantly).
  31701.  Useful <b>3rd party files</b> can be stamped by RDS, making them
  31702.  <font color="#CC0099"><b>free</b></font>, provided they are not altered
  31703.  significantly. You can put many statements on one line, or you can split
  31704.  a statement across many lines -- it won't affect your statement count.
  31705. </dl>
  31706.  
  31707. <p>
  31708.  We want you to enjoy writing some great programs in Euphoria. Later, when you 
  31709.  decide that you like the language, and want to take advantage of the
  31710.  <font color="#CC0099"><b>enhanced features</b></font> in the
  31711.  Complete Edition, we hope you will
  31712.  register. Registration costs only $39 (DOS32+WIN32) or $25 (Linux), and 
  31713.  you can reduce or even eliminate this cost by contributing useful code 
  31714.  for our Web site. See
  31715.  <a href="html/register.htm"><font color="#5500FF"><b>register\register.doc</b></font></a>
  31716.  for details, or run: <b>ex how2reg.ex</b> in the
  31717.  <font color="#5500FF"><b>register</b></font> subdirectory.
  31718.  
  31719. <p>
  31720.  The documentation contained in this package comes in both plain text and
  31721.  HTML form. The plain text (<b>.doc</b>) files can be viewed with any text
  31722.  editor, such as Windows NotePad or WordPad. The HTML (<b>.htm</b>) files
  31723.  can be viewed with your Web browser. A tool that we developed in Euphoria
  31724.  allows us to automatically generate both plain text and HTML files, from a
  31725.  common source. Thus the content of each file in the
  31726.  <font color="#5500FF"><b>doc</b></font> subdirectory should be identical
  31727.  to the content of the corresponding file in the
  31728.  <font color="#5500FF"><b>html</b></font> subdirectory, aside from the
  31729.  lack of links, fonts, colors, etc. See
  31730.  <font color="#5500FF"><b>doc\overview.doc</b></font>
  31731.  (or <a href="html/overview.htm"><b>html\overview.htm</b></a>) for a summary
  31732.  of the documentation files.
  31733.  
  31734. <p>
  31735.  There's over 20,000 lines of free Euphoria source code in this package. We 
  31736.  encourage you to use it, copy it, modify it, distribute it, upload it etc. 
  31737.  
  31738. <p>
  31739.  You can freely distribute this <b>Public Domain
  31740.  Edition</b>, in whole or in part, so anyone can run a Euphoria
  31741.  program that you have developed. You are completely free to distribute 
  31742.  any Euphoria programs that you write, royalty-free, even if 
  31743.  you don't register.
  31744.  
  31745. <p>
  31746.  You may <font color="#CC0099"><_ba><i>not</i></_ba></font> distribute the
  31747.  files <font color="#993333"><_bq>ex.exe</_bq></font>,
  31748.  <font color="#993333"><_bq>exw.exe</_bq></font>,
  31749.  <font color="#993333"><_bq>exu</_bq></font>,
  31750.  <font color="#993333"><_bq>bind.ex</_bq></font>,
  31751.  <font color="#993333"><_bq>bind.bat</_bq></font>,
  31752.  <font color="#993333"><_bq>bindw.bat</_bq></font>,
  31753.  <font color="#993333"><_bq>bindu</_bq></font>,
  31754.  <font color="#993333"><_bq>shroud</_bq></font> or
  31755.  <font color="#993333"><_bq>shroud.bat</_bq></font> that come with the
  31756.  <b>Complete Editions</b>.
  31757.  
  31758. <p>
  31759.  To run the <font color="#CC3366"><b>WIN32</b></font> version of Euphoria
  31760.  you need Windows 95, Windows 98, Windows NT, or (soon) Windows 2000.
  31761.  
  31762. <p>
  31763.  To run the <font color="#CC3366"><b>DOS32</b></font> version you need
  31764.  MS-DOS (or PC-DOS etc.) on any 386 or higher processor.
  31765.  <font color="#993333"><b>ex.exe</b></font> will use extended memory if it
  31766.  is available, but can run in 640K of conventional memory if that is all
  31767.  you have. It has been well tested under MS-DOS 4, 5, 6, 6.2 and 7.0, as well
  31768.  as DOS-prompt windows under Windows 3.1, Windows 3.11, Windows NT,
  31769.  Windows 95, Windows 98 and OS/2. Euphoria exploits the full 32-bit power of
  31770.  your PC. A <font color="#CC3366"><b>DOS32</b></font> Euphoria program will
  31771.  run under DOS, or as a DOS application under Windows or OS/2 - just
  31772.  <b><i>double-click</i></b> on the file name, or open a DOS prompt window.
  31773.  
  31774. <p>
  31775.  To run the <font color="#CC3366"><b>Linux</b></font> version of Euphoria
  31776.  you need any reasonably up-to-date Linux distribution, that has libc6 or 
  31777.  later. For example, Red Hat 5.2, 6.0 or later will work fine.
  31778.  
  31779. <p>
  31780.  
  31781. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  31782. <br>
  31783.  
  31784. <_dul>Getting Started</_dul>
  31785.  
  31786. </font>
  31787. <p>
  31788. <table border=0 cellspacing=2 cellpadding=2>
  31789.  
  31790. <_2clist
  31791.   name="1."
  31792.   pos=7
  31793.   description="On DOS/Windows install Euphoria by typing:"
  31794.  >
  31795. <_eucode>
  31796.         install
  31797. </_eucode>
  31798.  
  31799. <_2clist
  31800.   name=""
  31801.   pos=7
  31802.   description="Don't worry, it's easy to uninstall - see
  31803. <a href=\"html/install.htm\"><font color=\"#5500FF\">
  31804.  <b>install.doc</b></font></a>."
  31805.  >
  31806.  
  31807. <_2clist
  31808.   name=""
  31809.   pos=7
  31810.   description="On Linux see <a href=\"html/install.htm\"><font color=\"#5500FF\">
  31811.  <b>install.doc</b></font></a>."
  31812.  >
  31813.  
  31814.  
  31815. <_2clist
  31816.   name="2."
  31817.   pos=7
  31818.   description="After you install Euphoria, the documentation files will be in
  31819.    the <font color=\"#5500FF\"><b>doc</b></font> and
  31820.    <font color=\"#5500FF\"><b>html</b></font> directories.
  31821. <a href=\"html/overview.htm\"><font color=\"#5500FF\"><b>overview.doc</b></font></a>
  31822.  gives an overview of the documentation.
  31823.  <a href=\"html/refman.htm\"><b>refman.htm</b></a> (or
  31824.  <font color=\"#5500FF\"><b>refman.doc</b></font>) should be read first.
  31825.  If you want to search for information on any topic, type
  31826.  <font color=\"#993333\"><b>guru</b></font>."
  31827.  >
  31828.  
  31829. <_2clist
  31830.   name="3."
  31831.   pos=7
  31832.   description="Have fun running the programs in the
  31833.    <font color=\"#5500FF\"><b>demo</b></font> directory. Feel free to modify
  31834.    them, or run them in <font color=\"#993333\"><b>trace</b></font> mode by
  31835.    adding:"
  31836.  >
  31837.  
  31838. <_eucode>
  31839.         with trace
  31840.         trace(1)
  31841. </_eucode>
  31842.  
  31843. <_2clist
  31844.   name=""
  31845.   pos=7
  31846.   description="as the first two lines in the <b>.ex</b> or <b>.exw</b> file."
  31847.  >
  31848.  
  31849. <_2clist
  31850.   name="4."
  31851.   pos=7
  31852.   description="Try typing in some simple statements and running them.
  31853.    You can use any text editor. Later you may want to use the Euphoria editor,
  31854.    <font color=\"#993333\"><b>ed</b></font>, or download David Cuny's
  31855.    Euphoria editor from the
  31856.    <a href=\"http://www.RapidEuphoria.com\">Euphoria Web site</a>.
  31857.    <p>
  31858.    Don't be afraid to try things. Euphoria won't bite!"
  31859.  >
  31860.  
  31861. <_2clist
  31862.   name="5."
  31863.   pos=7
  31864.   description="See
  31865. <a href=\"html/what2do.htm\"><font color=\"#5500FF\"><b>what2do.doc</b></font></a>
  31866.  for more ideas."
  31867.  >
  31868.  
  31869. <_2clist
  31870.   name="6."
  31871.   pos=7
  31872.   description="Visit the Euphoria Web site, download some files, and
  31873.    subscribe to the Euphoria <b>mailing list</b> (see
  31874.  <a href=\"html/web.htm\"><font color=\"#5500FF\"><b>web.doc</b></font></a>)."
  31875.  >
  31876.  
  31877. </table>
  31878.  
  31879. <p>
  31880.  If you are new to programming, and you find 
  31881.  <a href="html/refman.htm"><b>refman.htm</b></a>
  31882.  hard to follow, download
  31883.  <b>David Gay</b>'s interactive tutorial called <i>"A Beginner's Guide
  31884.  To Euphoria"</i>. There's a link to it from the
  31885.  <a href="http://www.RapidEuphoria.com">Euphoria Web site</a>.
  31886.  
  31887. <p> <br>
  31888. <center>
  31889.  <_ba><_ba><_ba> <font face="Arial, Helvetica" color="#003366" size=-1>If
  31890.  you have any trouble installing, see</font> <a href="html/install.htm">
  31891.  <font face="Arial, Helvetica" color="#5500FF" size=-1>install.doc</font></a> </_ba></_ba></_ba>
  31892. </center>
  31893.  
  31894. <p>
  31895. <hr>
  31896.  
  31897. <dl>
  31898. <dt>
  31899.  <b><font face="Arial, Helvetica" color="#006633" size=-1>
  31900.  <_dul>Notice to Shareware Vendors:</_dul></font></b>
  31901. <dd>
  31902.   <font face="Arial, Helvetica" size=-1>We encourage you to distribute
  31903.   this Public Domain Edition of Euphoria. You can charge whatever you
  31904.   like for it. People can use Euphoria for as long as they like without
  31905.   obligation. We make money from those who start to seriously develop
  31906.   large applications, and want technical support plus
  31907.   enhanced bind, profile, and debug support for large programs.</font>
  31908. </dl>
  31909.  
  31910. <hr>
  31911.  
  31912. <dl>
  31913. <dt>
  31914.  <b><font face="Arial, Helvetica" color="#006633" size=-1>
  31915.  <_dul>DISCLAIMER:</_dul></font></b>
  31916. <dd>
  31917.   <font face="Arial, Helvetica" size=-1>
  31918.   The Public Domain and Complete Editions of Euphoria are provided "as is"
  31919.   without warranty of any kind. In no event shall Rapid Deployment
  31920.   Software be held liable for any damages arising from the use of or
  31921.   inability to use this product.</font>
  31922. </dl>
  31923.  
  31924. <hr>
  31925.  
  31926. <p> 
  31927.  
  31928. </_width>
  31929. </body>
  31930. </html>
  31931.  
  31932. REFMAN.HTX
  31933. 7931
  31934. <_init_comment>
  31935. <html>
  31936. <head><title>Euphoria Programming Language v2.2 Reference Manual - Head</title>
  31937. </head>
  31938. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  31939.  
  31940. <_center><font color="#006633" size=+2>
  31941. <br>
  31942.                    Euphoria Programming Language<br><br>
  31943.                             version 2.2<br><br>
  31944.                          Reference Manual<br>
  31945. </font></_center>
  31946. <p> 
  31947. <p>
  31948.  
  31949. <_center><font color="#FF0099" face="Arial, Helvetica" size=+1>
  31950.                  (c) 2000 Rapid Deployment Software<br>
  31951. </font></_center>
  31952.  
  31953. <p> 
  31954. <p>
  31955.  
  31956. <_center><font size=+1>
  31957.                Permission is freely granted to anyone<br>
  31958.                         to copy this manual.<br>
  31959. </font></_center>
  31960.  
  31961. <p> 
  31962. <p>
  31963. <hr>
  31964. <p>
  31965.  
  31966. <_center><font face="Arial, Helvetica" color="#006633" size=+2>
  31967.                          TABLE OF CONTENTS
  31968. </font></_center>
  31969.  
  31970. <p>
  31971. <_center><font size=+1>
  31972.                        <a href="refman_1.htm">Part I - Core Language</a>
  31973. </font></_center>
  31974.  
  31975. <dl>
  31976. <dt>
  31977.  
  31978.         1. <a href="refman_1.htm"> Introduction </a>
  31979.  
  31980. <dd>
  31981. <dl>
  31982. <dt>
  31983.            1.1 <a href="refman_1.htm#1"> Example Program </a>
  31984.  
  31985. <dd>
  31986. <dt>
  31987.            1.2 <a href="refman_1.htm#2"> Installation </a>
  31988.  
  31989. <dd>
  31990. <dt>
  31991.            1.3 <a href="refman_1.htm#3"> Running a Program </a>
  31992. <dd>
  31993.                  1.3.1 <a href="refman_1.htm#31"> Running under Windows </a>
  31994. <dd>
  31995.                  1.3.2 <a href="refman_1.htm#32"> Use of a Swap File </a>
  31996.  
  31997. <dd>
  31998. <dt>
  31999.            1.4 <a href="refman_1.htm#4"> Editing a Program </a>
  32000.  
  32001. <dd>
  32002. <dt>
  32003.            1.5 <a href="refman_1.htm#5"> Distributing a Program </a>
  32004. <dd>
  32005.                  1.5.1 <a href="refman_1.htm#51"> Licensing </a>
  32006.  
  32007. <p>
  32008. </dl>
  32009. <dt>
  32010.         2. <a href="refman_2.htm"> Language Definition </a>
  32011.  
  32012. <dd>
  32013. <dl>
  32014. <dt>
  32015.            2.1 <a href="refman_2.htm#1"> Objects </a>
  32016. <dd>
  32017.                 2.1.1 <a href="refman_2.htm#1"> Atoms and Sequences</a>
  32018. <dd>
  32019.                 2.1.2 <a href="refman_2.htm#11"> Character Strings and
  32020.                      Individual Characters</a>
  32021. <dd>
  32022.                 2.1.3 <a href="refman_2.htm#12"> Comments </a>
  32023.  
  32024. <dd>
  32025. <dt>
  32026.            2.2 <a href="refman_2.htm#2"> Expressions </a>
  32027.  
  32028. <dd>
  32029.               2.2.1 <a href="refman_2.htm#23"> Relational Operators </a>
  32030. <dd>
  32031.               2.2.2 <a href="refman_2.htm#24"> Logical Operators </a>
  32032. <dd>
  32033.               2.2.3 <a href="refman_2.htm#25"> Arithmetic Operators </a>
  32034. <dd>
  32035.               2.2.4 <a href="refman_2.htm#26"> Operations on Sequences </a>
  32036. <dd>
  32037.               2.2.5 <a href="refman_2.htm#21"> Subscripting of Sequences </a>
  32038. <dd>
  32039.               2.2.6 <a href="refman_2.htm#22"> Slicing of Sequences </a>
  32040. <dd>
  32041.               2.2.7 <a href="refman_2.htm#27"> Concatenation of Sequences and
  32042.                      Atoms - The & Operator </a>
  32043. <dd>
  32044.               2.2.8 <a href="refman_2.htm#28"> Sequence-Formation </a>
  32045. <dd>
  32046.               2.2.9 <a href="refman_2.htm#29"> Other Operations on Sequences
  32047.                      </a>
  32048. <ul type=circle>
  32049. <li>
  32050.                          <a href="refman_2.htm#291"> length </a>
  32051. <li>
  32052.                          <a href="refman_2.htm#292"> repeat </a>
  32053. <li>
  32054.                          <a href="refman_2.htm#293"> append / prepend </a>
  32055. </ul>
  32056. <dd>
  32057.               2.2.10 <a href="refman_2.htm#2A"> Precedence Chart </a>
  32058.  
  32059. <dd>
  32060. <dt>
  32061.            2.3 <a href="refman_2.htm#3"> Euphoria versus Conventional Languages
  32062.                </a>
  32063.  
  32064. <dd>
  32065. <dt>
  32066.            2.4 <a href="refman_2.htm#4"> Declarations </a>
  32067. <dd>
  32068.                2.4.1 <a href="refman_2.htm#41"> Identifiers </a>
  32069. <ul type=circle>
  32070. <li>
  32071.                          <a href="refman_2.htm#411"> procedures </a>
  32072. <li>
  32073.                          <a href="refman_2.htm#412"> functions </a>
  32074. <li>
  32075.                          <a href="refman_2.htm#413"> types </a>
  32076. <li>
  32077.                          <a href="refman_2.htm#414"> variables </a>
  32078. <li>
  32079.                          <a href="refman_2.htm#415"> constants </a>
  32080. </ul>
  32081. <dd>
  32082.                2.4.2 <a href="refman_2.htm#42"> Scope </a>
  32083. <dd>
  32084.                2.4.3 <a href="refman_2.htm#43"> Specifying the Type of a
  32085.                      Variable </a>
  32086.  
  32087. <dd>
  32088. <dt>
  32089.            2.5 <a href="refman_2.htm#5"> Statements </a>
  32090. <dd>
  32091.                2.5.1 <a href="refman_2.htm#assign"> assignment statement</a>
  32092. <ul type=circle>
  32093. <li>
  32094.                   <a href="refman_2.htm#assignop"> Assignment with Operator</a>
  32095. </ul>
  32096. <dd>
  32097.                2.5.2 <a href="refman_2.htm#proc"> procedure call </a>
  32098. <dd>
  32099.                2.5.3 <a href="refman_2.htm#if"> if statement</a>
  32100. <dd>
  32101.                2.5.4 <a href="refman_2.htm#while"> while statement</a>
  32102. <ul type=circle>
  32103. <li>
  32104.                    <a href="refman_2.htm#shortcir"> Short-Circuit Evaluation</a>
  32105. </ul>
  32106. <dd>
  32107.                2.5.5 <a href="refman_2.htm#for"> for statement</a>
  32108. <dd>
  32109.                2.5.6 <a href="refman_2.htm#return"> return statement</a>
  32110. <dd>
  32111.                2.5.7 <a href="refman_2.htm#exit"> exit statement</a>
  32112.  
  32113. <dd>
  32114. <dt>
  32115.            2.6 <a href="refman_2.htm#6"> Special Top-Level Statements </a>
  32116. <dd>
  32117.                2.6.1 <a href="refman_2.htm#61"> include </a>
  32118. <dd>
  32119.                2.6.2 <a href="refman_2.htm#62"> with / without </a>
  32120.  
  32121. <p>
  32122. </dl>
  32123. <dt>
  32124.         3. <a href="refman_3.htm"> Debugging and Profiling </a>
  32125.  
  32126. <dd>
  32127. <dl>
  32128. <dt>
  32129.            3.1 <a href="refman_3.htm#1"> Debugging </a>
  32130. <dd>
  32131.                3.1.1 <a href="refman_3.htm#11"> The Trace Screen </a>
  32132.  
  32133. <dt>
  32134.            3.2 <a href="refman_3.htm#2"> Profiling </a>
  32135. <dd>
  32136.                3.2.1 <a href="refman_3.htm#21"> Some Further Notes on Time
  32137.                      Profiling </a>
  32138.  
  32139. </dl>
  32140. </dl>
  32141. <p> 
  32142. <p>
  32143.  
  32144. <_center><font size=+1>
  32145.                      <a href="library.htm">Part II - Library Routines</a>
  32146. </font></_center>
  32147.  
  32148. <dl>
  32149. <dt>
  32150.         1. <a href="library.htm"> Introduction </a>
  32151. <p>
  32152. <dd>
  32153. <dt>
  32154.         2. <a href="library.htm#2"> Routines by Application Area </a>
  32155.  
  32156. <dd>
  32157. <dl>
  32158. <dt>
  32159.            2.1 <a href="library.htm#predefined"> Predefined Types</a>
  32160. <dd>
  32161. <dt>
  32162.            2.2 <a href="library.htm#seq_manip"> Sequence Manipulation</a>
  32163. <dd>
  32164. <dt>
  32165.            2.3 <a href="library.htm#srch_srt"> Searching and Sorting</a>
  32166. <dd>
  32167. <dt>
  32168.            2.4 <a href="library.htm#pattern_m"> Pattern Matching</a>
  32169. <dd>
  32170. <dt>
  32171.            2.5 <a href="library.htm#math"> Math</a>
  32172. <dd>
  32173. <dt>
  32174.            2.6 <a href="library.htm#bitw_logic"> Bitwise Logical Operations</a>
  32175. <dd>
  32176. <dt>
  32177.            2.7 <a href="library.htm#i_o"> File and Device I/O</a>
  32178. <dd>
  32179. <dt>
  32180.            2.8 <a href="library.htm#mouse_spt"> Mouse Support (DOS32)</a>
  32181. <dd>
  32182. <dt>
  32183.            2.9 <a href="library.htm#op_sys"> Operating System</a>
  32184. <dd>
  32185. <dt>
  32186.            2.10 <a href="library.htm#machine_dep"> Special Machine-Dependent
  32187.                Routines</a>
  32188. <dd>
  32189. <dt>
  32190.            2.11 <a href="library.htm#debugging"> Debugging</a>
  32191. <dd>
  32192. <dt>
  32193.            2.12 <a href="library.htm#gr_sound"> Graphics & Sound</a>
  32194. <dd>
  32195. <dt>
  32196.            2.13 <a href="library.htm#m_level_i"> Machine Level Interface</a>
  32197. <dd>
  32198. <dt>
  32199.            2.14 <a href="library.htm#dyn_call"> Dynamic Calls</a>
  32200. <dd>
  32201. <dt>
  32202.            2.15 <a href="library.htm#call_c_func"> Calling C Functions</a>
  32203. <dd>
  32204. </dl>
  32205. <p>
  32206. <dt>
  32207.         3. Alphabetical Listing of all Routines
  32208.  
  32209. <dd>
  32210.  
  32211. <dl>
  32212. <dt>
  32213.            <a href="lib_a_b.htm"> From A to B </a>
  32214. <dd>
  32215. <dt>
  32216.            <a href="lib_c_d.htm"> From C to D </a>
  32217. <dd>
  32218. <dt>
  32219.            <a href="lib_e_g.htm"> From E to G </a>
  32220. <dd>
  32221. <dt>
  32222.            <a href="lib_h_o.htm"> From H to O </a>
  32223. <dd>
  32224. <dt>
  32225.            <a href="lib_p_r.htm"> From P to R </a>
  32226. <dd>
  32227. <dt>
  32228.            <a href="lib_s_t.htm"> From S to T </a>
  32229. <dd>
  32230. <dt>
  32231.            <a href="lib_u_z.htm"> From U to Z </a>
  32232. <dd>
  32233.  
  32234. </dl>
  32235. </dl>
  32236.  
  32237. <_continue
  32238.   href="refman_1.htm"
  32239.   name="Part I - Core Language"
  32240. >
  32241.  
  32242. </body>
  32243. </html>
  32244. REFMAN_1.HTX
  32245. 24365
  32246. <_init_comment>
  32247. <html>
  32248. <head><title>Euphoria v2.2 Reference Manual Part I - Section 1 </title>
  32249. </head>
  32250. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  32251. <_width>
  32252. <_center><font color="#006633" size=+2><b>
  32253. <br>
  32254.                          Part I - Core Language
  32255. </b></font></_center>
  32256.  
  32257. <_center><font color="#FF0099" size=+2>
  32258. <br>
  32259.                             1. Introduction
  32260. </font></_center>
  32261. <p> <br>
  32262.  
  32263.  <font color="#993333"><b>Euphoria</b></font> is a new programming language
  32264.  with the following advantages over conventional languages:
  32265.  
  32266. <ul type=circle>
  32267. <li>
  32268.       a remarkably simple, flexible, powerful language definition
  32269.       that is easy to learn and use.
  32270.  
  32271. <p><li>
  32272.       dynamic storage allocation. Variables grow or shrink
  32273.         without the programmer having to worry about allocating
  32274.         and freeing chunks of memory.  Objects of any size can be
  32275.         assigned to an element of a Euphoria sequence (array).
  32276.  
  32277. <p><li>
  32278.       a high-performance, state-of-the-art interpreter that's at least
  32279.         <font color="#CC0099"><b><i>10 to 30 times</i></b></font> faster
  32280.         than conventional interpreters such as Microsoft QBasic,
  32281.         Perl and Python.
  32282.  
  32283. <p><li>
  32284.       lightning-fast pre-compilation. Your program is checked
  32285.         for syntax and converted into an efficient internal form at over
  32286.         <font color="#CC0099"><b><i>35,000 lines per second</i></b></font>
  32287.         on a Pentium-150.
  32288.  
  32289. <p><li>
  32290.       extensive run-time checking for: out-of-bounds subscripts,
  32291.         uninitialized variables, bad parameter values for library
  32292.         routines, illegal value assigned to a variable and many
  32293.         more.  There are no mysterious machine exceptions -- you
  32294.         will always get a full English description of any problem
  32295.         that occurs with your program at run-time, along with a
  32296.         call-stack trace-back and a dump of all of your variable
  32297.         values.  Programs can be debugged quickly, easily and
  32298.         more thoroughly.
  32299.  
  32300. <p><li>
  32301.       features of the underlying hardware are completely hidden.
  32302.       Programs are not aware of word-lengths, underlying bit-level
  32303.       representation of values, byte-order etc.
  32304.  
  32305. <p><li>
  32306.       a full-screen source debugger and an execution profiler
  32307.       are included, along with a full-screen, multi-file editor.
  32308.       On a color monitor, the editor displays Euphoria programs in
  32309.       multiple colors, to highlight comments, reserved words,
  32310.       built-in functions, strings, and level of nesting of brackets.
  32311.       It optionally performs auto-completion of statements,
  32312.       saving you typing effort and reducing syntax errors. This
  32313.       editor is written in Euphoria, and the source code is
  32314.       provided to you without restrictions. You are free to
  32315.       modify it, add features, and redistribute it as you wish.
  32316.  
  32317. <p><li>
  32318.       Euphoria programs run under Linux, 32-bit Windows, and any
  32319.       DOS environment, and are not subject to any 64K or 640K memory
  32320.       limitations. You can create programs that use the full multi-megabyte
  32321.       memory of your computer, and a swap file is automatically used when a
  32322.       program needs more memory than exists on your machine.
  32323.  
  32324. <p><li>
  32325.       You can make a single, stand-alone <b>.</b>exe file from your program.
  32326.  
  32327. <p><li>
  32328.       Euphoria routines are naturally generic. The example program below
  32329.         shows a single routine that will sort any type of data -- integers,
  32330.         floating-point numbers, strings etc. Euphoria is not an
  32331.         "object-oriented" language, yet it achieves many of the benefits of
  32332.         these languages in a much simpler way.
  32333.  
  32334. </ul>
  32335. <p>
  32336. <hr>
  32337.  
  32338. <a name=1></a>
  32339. <font color="#FF0099" size=+1>
  32340. <br>
  32341.  
  32342. <_dul>1.1 Example Program</_dul>
  32343.  
  32344. </font>
  32345. <p>
  32346.  
  32347.  The following is an example of a complete Euphoria program.
  32348.  
  32349. <p>
  32350. <_eucode>
  32351. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  32352.  
  32353.  sequence list, sorted_list
  32354.  
  32355.  function merge_sort(sequence x)
  32356.  -- put x into ascending order using a recursive merge sort
  32357.      integer n, mid
  32358.      sequence merged, a, b
  32359.  
  32360.      n = length(x)
  32361.      if n = 0 or n = 1 then
  32362.          return x  -- trivial case
  32363.      end if
  32364.  
  32365.      mid = floor(n/2)
  32366.      a = merge_sort(x[1..mid])       -- sort first half of x
  32367.      b = merge_sort(x[mid+1..n])     -- sort second half of x
  32368.  
  32369.      -- merge the two sorted halves into one
  32370.      merged = {}
  32371.      while length(a) > 0 and length(b) > 0 do
  32372.          if compare(a[1], b[1]) < 0 then
  32373.              merged = append(merged, a[1])
  32374.              a = a[2..length(a)]
  32375.          else
  32376.              merged = append(merged, b[1])
  32377.              b = b[2..length(b)]
  32378.          end if
  32379.      end while
  32380.      return merged & a & b  -- merged data plus leftovers
  32381.  end function
  32382.  
  32383.  procedure print_sorted_list()
  32384.  -- generate sorted_list from list
  32385.      list = {9, 10, 3, 1, 4, 5, 8, 7, 6, 2}
  32386.      sorted_list = merge_sort(list)
  32387.      ? sorted_list
  32388.  end procedure
  32389.  
  32390.  print_sorted_list()     -- this command starts the program
  32391.  
  32392.  
  32393. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  32394. </_eucode>
  32395. <p>
  32396.  
  32397.  The above example contains 4 separate commands that are processed in order.
  32398.  The first declares two variables: list and sorted_list to be
  32399.  <a href="refman_2.htm#1"><font color="#993333"><b>sequences</b></font></a>
  32400.  (flexible arrays). The second defines a
  32401.  <a href="refman_2.htm#412"><font color="#993333"><b>function</b></font></a>
  32402.  merge_sort(). The third defines a <a href="refman_2.htm#411">
  32403.  <font color="#993333"><b>procedure</b></font></a> print_sorted_list().
  32404.  The final command calls procedure print_sorted_list().
  32405.  
  32406. <p>
  32407.  The output from the program will be: <br>
  32408.  <font face="Arial, Helvetica">
  32409.      {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}.
  32410.  </font>
  32411.  
  32412. <p><font color="#CC0099"><b>
  32413.  merge_sort() will just as easily sort
  32414.  <font face="Arial, Helvetica"> {1.5, -9, 1e6, 100} </font> or
  32415.  <font face="Arial, Helvetica"> {"oranges", "apples", "bananas"} </font>.
  32416.  </b></font>
  32417.  
  32418. <p>
  32419.  This example is stored as <font color="#5500FF">
  32420.  <b>euphoria\tutorial\example.ex</b></font>. This is not the fastest
  32421.  way to sort in Euphoria. Go to the
  32422.  <font color="#5500FF"><b>euphoria\demo</b></font> directory and type
  32423.  "ex allsorts" to see timings on several different sorting algorithms for
  32424.  increasing numbers of objects. For a quick tutorial example of Euphoria
  32425.  programming see
  32426.  <font color="#5500FF"><b>euphoria\demo\bench\filesort.ex</b></font>.
  32427.  
  32428. <p>
  32429. <hr>
  32430.  
  32431. <a name=2></a>
  32432. <font color="#FF0099" size=+1>
  32433. <br>
  32434.  
  32435. <_dul>1.2 Installation</_dul>
  32436.  
  32437. </font>
  32438. <p>
  32439.  
  32440.  To install Euphoria on your machine, first read the file
  32441.  <a href="install.htm"><font color="#5500FF"><b>install.doc</b></font></a>.
  32442.  Installation simply involves copying the
  32443.  <font color="#993333"><b>euphoria</b></font> files to your hard disk
  32444.  under a directory named "euphoria", and then modifying your
  32445.  <b>autoexec.bat</b> file
  32446.  so that <font color="#5500FF"><b>euphoria\bin</b></font>
  32447.  is on your search path, and the
  32448.  environment variable <b>EUDIR</b> is set to the euphoria directory. 
  32449.  On DOS/Windows an automatic
  32450.  install program, <font color="#5500FF"><b>install.bat</b></font> is
  32451.  provided for this purpose. For the latest details, please read the
  32452.  instructions in <font color="#5500FF"><b>install.doc</b></font> before you
  32453.  run <font color="#5500FF"><b>install.bat</b></font>.
  32454.  
  32455. <p>
  32456.  When installed, the <font color="#993333"><b>euphoria</b></font> directory
  32457.  will look something like this:
  32458.  
  32459. <dl>
  32460. <dt>
  32461.         <font color="#5500FF"><b>\euphoria</b></font>
  32462. <dl>
  32463. <dt>
  32464.                 readme.doc
  32465. <dt>
  32466.                 readme.htm
  32467. <dt>
  32468.                 <font color="#5500FF"><b>\bin</b></font>
  32469. <dd>
  32470.                         ex.exe and exw.exe, or exu (Linux), ed.bat, guru.bat, other utilities
  32471. <dt>
  32472.                 <font color="#5500FF"><b>\include</b></font>
  32473. <dd>
  32474.                         standard include files, e.g. graphics.e
  32475. <dt>
  32476.                 <font color="#5500FF"><b>\doc</b></font>
  32477. <dd>
  32478.                         refman.doc, library.doc, and several other plain-text
  32479.                         documentation files
  32480. <dt>
  32481.                 <font color="#5500FF"><b>\html</b></font>
  32482. <dd>
  32483.                         HTML files corresponding to each of the .doc files
  32484.                         in the doc directory
  32485. <dt>
  32486.                 <font color="#5500FF"><b>\tutorial</b></font>
  32487. <dd>
  32488.                         small tutorial programs to help you learn Euphoria
  32489. <dt>
  32490.                 <font color="#5500FF"><b>\demo</b></font>
  32491. <dl>
  32492. <dt>
  32493.                         generic demo programs that run on all platforms
  32494. <dt>
  32495.                         <font color="#5500FF"><b>\dos32</b></font>
  32496. <dd>
  32497.                                 DOS32-specific demo programs (optional)
  32498. <dt>
  32499.                         <font color="#5500FF"><b>\win32</b></font>
  32500. <dd>
  32501.                                 WIN32-specific demo programs (optional)
  32502. <dt>
  32503.                         <font color="#5500FF"><b>\linux</b></font>
  32504. <dd>
  32505.                                 Linux-specific demo programs (optional)
  32506. <dt>
  32507.                         <font color="#5500FF"><b>\langwar</b></font>
  32508. <dd>
  32509.                                 language war game (pixel-graphics version for DOS,
  32510.                                 or text version for Linux)
  32511. <dt>
  32512.                         <font color="#5500FF"><b>\bench</b></font>
  32513. <dd>
  32514.                                 benchmark programs
  32515. </dl>
  32516. <dt>
  32517.                 <font color="#5500FF"><b>\register</b></font>
  32518. <dd>
  32519.                         information on ordering the Complete Edition
  32520. </dl>
  32521. </dl>
  32522.  
  32523. <p>
  32524. The linux subdirectory is not included in the DOS/Windows distribution,
  32525. and the dos32 and win32 subdirectories are not included in the Linux
  32526. distribution. In this manual, directory names are shown using backslash
  32527. (<b>\</b>). Linux users should substitute forward slash (<b>/</b>).
  32528.  
  32529. <hr>
  32530.  
  32531. <a name=3></a>
  32532. <font color="#FF0099" size=+1>
  32533. <br>
  32534. <p>
  32535. <_dul>1.3 Running a Program</_dul>
  32536.  
  32537. </font>
  32538. <p>
  32539.  
  32540.  Euphoria programs are executed by typing
  32541.  <font color="#993333"><_bq>ex</_bq></font>,
  32542.  <font color="#993333"><_bq>exw</_bq></font> or
  32543.  <font color="#993333"><_bq>exu</_bq></font>
  32544.  followed by the name of the main Euphoria file. You can type additional
  32545.  words (known as <font color="#993333"><b>arguments</b></font>) on this line,
  32546.  known as the <font color="#993333"><b>command-line</b></font>.
  32547.  Your program can call the built-in function
  32548.  <a href="lib_c_d.htm#command_line">command_line()</a> to read the
  32549.  command-line.
  32550.  The DOS32 version of the
  32551.  Euphoria interpreter is called
  32552.  <font color="#993333"><b>ex.exe</b></font>. The WIN32 version
  32553.  is called
  32554.  <font color="#993333"><b>exw.exe</b></font>. The Linux version
  32555.  is called <font color="#993333"><b>exu</b></font>. By convention, main 
  32556.  Euphoria
  32557.  files have an extension of <_bq>.ex</_bq>, <_bq>.exw</_bq> or 
  32558.  <_bq>.exu</_bq>.  Other
  32559.  Euphoria files, that are meant to be included in a larger program, end in
  32560.  <_bq>.e</_bq> or sometimes <_bq>.ew</_bq> or <_bq>.eu</_bq>.
  32561.  To save typing, you can leave off the ".ex", and
  32562.  the <font color="#993333"><b>ex</b></font> command will supply it for you
  32563.  automatically. <font color="#993333"><b>exw.exe</b></font> will supply
  32564.  ".exw", and <font color="#993333"><b>exu</b></font> 
  32565.  will supply ".exu". If the file can't be found in the current directory,
  32566.  your PATH will be searched. You can redirect standard input and standard
  32567.  output when you run a Euphoria program, for example:
  32568.  
  32569. <pre>
  32570.         ex filesort.ex < raw.txt > sorted.txt
  32571. </pre>
  32572.            or simply,
  32573. <pre>
  32574.         ex filesort < raw.txt > sorted.txt
  32575. </pre>
  32576.  
  32577. <p>
  32578. Unlike many other compilers and interpreters, there are no special
  32579. command-line options for <font color="#993333"><b>ex</b></font>,
  32580. <font color="#993333"><b>exw</b></font> or
  32581. <font color="#993333"><b>exu</b></font>. Only the name of your
  32582. Euphoria file is expected, and if you don't supply it, you
  32583. will be prompted for it.
  32584.  
  32585. <p>
  32586.  For frequently-used programs under DOS/Windows you might want to make a small 
  32587.  <b>.bat</b> (batch) file, perhaps called <b>myprog.bat</b>, 
  32588.  containing two statements like:
  32589. <pre>
  32590.         @echo off
  32591.         ex myprog.ex %1 %2 %3
  32592. </pre>
  32593.  The first statement turns off echoing of commands to the screen. The second
  32594.  runs <b>ex myprog.ex</b> with up to 3 command-line arguments.
  32595.  See <a href="lib_c_d.htm#command_line">command_line()</a> for an example of
  32596.  how to read these arguments. If your program takes more arguments, you
  32597.  should add %4 %5 etc. Having a .bat file will save you the minor
  32598.  inconvenience of typing <font color="#993333"><_bq>ex</_bq></font>
  32599.  (or <font color="#993333"><_bq>exw</_bq></font>) all the time, i.e.
  32600.  you can just type:
  32601. <pre>
  32602.         myprog
  32603. </pre>
  32604. instead of:
  32605. <pre>
  32606.         ex myprog
  32607. </pre>
  32608.  Unfortunately DOS will not allow redirection of standard input and output
  32609.  when you use a <b>.bat</b> file
  32610. <p>
  32611. Under Linux, you can type the path to the Euphoria interpreter
  32612. on the first line of your main file, e.g. if your
  32613. program is called foo.exu:
  32614.  
  32615. <pre>
  32616.         #!/home/rob/euphoria/bin/exu
  32617.         
  32618.         procedure foo()
  32619.             ? 2+2
  32620.         end procedure
  32621.  
  32622.         foo()
  32623. </pre>
  32624. Then if you make your file executable:
  32625. <pre>
  32626.         chmod +x foo.exu
  32627. </pre>
  32628. You can just type: 
  32629. <pre>
  32630.         foo.exu 
  32631. </pre>
  32632. to run your program. You could even shorten the name to simply "foo".
  32633. Euphoria ignores the first line of your program 
  32634. if it starts with <b>#!</b>.
  32635.  
  32636. <p>
  32637.  You can also run <font color="#5500FF"><b>bind.bat</b></font> (DOS32 or Linux)
  32638.  or <font color="#5500FF"><b>bindw.bat</b></font> (WIN32) to
  32639.  combine your Euphoria program with <font color="#993333"><b>ex.exe</b></font>,
  32640.  <font color="#993333"><b>exw.exe</b></font> or
  32641.  <font color="#993333"><b>exu</b></font>,
  32642.  to make a stand-alone executable file (<b>.exe</b> file on DOS/Windows).
  32643.  With a stand-alone <b>.exe</b> file you
  32644.  <font color="#CC0099"><i><_ba>can</_ba></i></font> redirect standard
  32645.  input and output. Binding is discussed further in
  32646.  <a href="refman_1.htm#5">1.5 Distributing a Program</a>.
  32647.  
  32648. <p>
  32649.  Either 
  32650.  <font color="#993333"><b>exu</b></font> or 
  32651.  <font color="#993333"><b>ex.exe</b></font> and
  32652.  <font color="#993333"><b>exw.exe</b></font>  
  32653.  are in the
  32654.  <font color="#5500FF"><b>euphoria\bin</b></font>
  32655.  directory which must be on your
  32656.  search path. The environment variable EUDIR should be set to the main
  32657.  Euphoria directory, e.g. <font color="#5500FF"><b>c:\euphoria</b></font>.
  32658.  
  32659. <p>
  32660.  
  32661. <a name=31></a>
  32662. <font color="#FF0099" size=+1>
  32663. <br>
  32664.  
  32665. <_sul>1.3.1 Running under Windows</_sul>
  32666.  
  32667. </font>
  32668. <p>
  32669.  
  32670.  You can run Euphoria programs directly from the Windows environment, or from
  32671.  a DOS shell that you have opened from Windows. By "associating" <b>.ex</b>
  32672.  files with <font color="#993333"><b>ex.exe</b></font>, and <b>.exw</b> files
  32673.  with <font color="#993333"><b>exw.exe</b></font> you can simply double-click
  32674.  on a <b>.ex</b> or <b>.exw</b> file to run it. Under Windows 95/98/NT you
  32675.  would define a new file type for <b>.ex</b>, by clicking on
  32676.  My Computer / view / options / file types. It is possible to have several
  32677.  Euphoria programs active in different windows. If you turn your program
  32678.  into a <b>.exe</b> file, you can simply double-click on it to run it.
  32679.  
  32680. <p>
  32681.  
  32682. <a name=32></a>
  32683. <font color="#FF0099" size=+1>
  32684. <br>
  32685.  
  32686. <_sul>1.3.2 Use of a Swap File</_sul>
  32687.  
  32688. </font>
  32689. <p>
  32690.  If you run a Euphoria program under Linux or Windows (or in a DOS shell under
  32691.  Windows), and the program runs out of physical memory, it will start using
  32692.  "virtual memory". The operating system provides this virtual memory 
  32693.  automatically by swapping out the least-recently-used code and data 
  32694.  to a system swap file.
  32695.  To change the size of the Windows swap file, click on Control Panel / 386
  32696.  Enhanced / "virtual memory...". Under OS/2 you can adjust the
  32697.  "DPMI_MEMORY_LIMIT" by clicking the Virtual DOS machine icon / "DOS Settings"
  32698.  to allocate more extended memory for your program.
  32699.  
  32700. <p>
  32701.  Under pure DOS, outside of Windows, there is no system swap file so the
  32702.  DOS-extender built in to <font color="#993333"><b>ex.exe</b></font> (DOS32)
  32703.  will create one for possible use by your program.
  32704.  See <a href="platform.htm#swapfile"><font color="#5500FF">
  32705.  <b>platform.doc</b></font></a>.
  32706.  
  32707. <p>
  32708. <hr>
  32709.  
  32710. <a name=4></a>
  32711. <font color="#FF0099" size=+1>
  32712. <br>
  32713.  
  32714. <_dul>1.4 Editing a Program</_dul>
  32715.  
  32716. </font>
  32717. <p>
  32718.  
  32719.  You can use any text editor to edit a Euphoria program. However, Euphoria
  32720.  comes with its own special editor that is written entirely in Euphoria.
  32721.  Type: <font color="#993333"><b>ed</b></font>
  32722.  followed by the complete name of the file you wish to edit
  32723.  (the .ex/.exw/.exu extension is not assumed). You can use this editor to edit any
  32724.  kind of
  32725.  text file. When you edit a Euphoria file, some extra features such as
  32726.  color syntax highlighting and auto-completion of certain statements, are
  32727.  available to make your job easier.
  32728.  
  32729. <p>
  32730.  Whenever you run a Euphoria program and get an error message, during
  32731.  compilation or execution, you can simply type
  32732.  <font color="#993333"><b>ed</b></font>
  32733.  with no file name and you
  32734.  will be automatically positioned in the file containing the error, at
  32735.  the correct line and column, and with the error message displayed at the
  32736.  top of the screen.
  32737.  
  32738. <p>
  32739.  Under Windows you can associate <font color="#5500FF"><b>ed.bat</b></font>
  32740.  with various kinds of text
  32741.  files that you want to edit. Color syntax highlighting is provided for
  32742.  <b>.ex</b>, <b>.exw</b>, <b>.exu</b>, <b>.e</b>, <b>.ew</b>, <b>.eu</b>, 
  32743.  and <b>.pro</b>
  32744.  (<a href="refman_3.htm#2">profile</a>) files.
  32745.  
  32746. <p>
  32747.  Most keys that you type are inserted into the file at the cursor position.
  32748.  Hit the <b>Esc</b> key once to get a menu bar of special commands. The arrow
  32749.  keys, and the Insert/Delete/Home/End/PageUp/PageDown keys are also active.
  32750.  Under Linux some keys may not be available, and alternate keys are
  32751.  provided.
  32752.  See the file <font color="#5500FF"><b>euphoria\doc\ed.doc</b></font>
  32753.  (<a href="ed.htm">euphoria\html\ed.htm</a>)
  32754.  for a complete description of the editing commands. <b>Esc h</b> (help) will
  32755.  let you view <font color="#5500FF"><b>ed.doc</b></font> from your editing
  32756.  session.
  32757.  
  32758. <p>
  32759.  If you need to understand or modify any detail of the editor's operation,
  32760.  you can edit the file <font color="#5500FF"><b>ed.ex</b></font>
  32761.  in <font color="#5500FF"><b>euphoria\bin</b></font>
  32762.  (be sure to make a backup
  32763.  copy so you don't lose your ability to edit).  If the name
  32764.  <font color="#993333"><b>ed</b></font> conflicts
  32765.  with some other command on your system, simply rename the file
  32766.  <font color="#5500FF"><b>euphoria\bin\ed.bat</b></font> to something else.
  32767.  Because this editor is written
  32768.  in Euphoria, it is remarkably concise and easy to understand. The same
  32769.  functionality implemented in a language like C, would take far more
  32770.  lines of code.
  32771.  
  32772. <p>
  32773.  <b>ed</b> is a simple DOS editor.
  32774.  See also <b>David Cuny</b>'s excellent <b>ee.ex</b> editor for
  32775.  DOS32 and Linux. You can download
  32776.  it from the <a href="http://www.RapidEuphoria.com">Euphoria Web site</a>.
  32777.  There are also some Windows editors oriented to Euphoria.
  32778.  These are also on <a href="http://www.RapidEuphoria.com">the Web site</a>.
  32779.  
  32780. <p>
  32781. <hr>
  32782.  
  32783. <a name=5></a>
  32784. <font color="#FF0099" size=+1>
  32785. <br>
  32786.  
  32787. <_dul>1.5 Distributing a Program</_dul>
  32788.  
  32789. </font>
  32790. <p>
  32791.  
  32792.  Euphoria provides you with 3 distinct ways of distributing a program.
  32793.  
  32794. <p>
  32795.  In the first method you simply ship your users the Public Domain
  32796.  <font color="#993333"><b>ex.exe</b></font> or
  32797.  <font color="#993333"><b>exw.exe</b></font> or
  32798.  <font color="#993333"><b>exu</b></font>
  32799.  file, along with your main
  32800.  Euphoria .ex, .exw, or .exu file and any .e
  32801.  include files that are needed (including any of the standard ones from
  32802.  <font color="#5500FF"><b>euphoria\include</b></font>).
  32803.  If the Euphoria source files are placed together in one
  32804.  directory and ex.exe, exw.exe or exu is placed in the same directory 
  32805.  or somewhere on the search path, then your user can run your program by typing
  32806.  <font color="#993333"><_bq>ex</_bq></font>
  32807.  (<font color="#993333"><_bq>exw</_bq></font>) or
  32808.  (<font color="#993333"><_bq>exu</_bq></font>)
  32809.  followed
  32810.  by the path of your main .ex, .exw, or .exu file.
  32811.  You might also provide a small <b>.bat</b> file so people won't actually
  32812.  have to type <font color="#993333"><_bq>ex</_bq></font>
  32813.  (<font color="#993333"><_bq>exw</_bq></font>). This
  32814.  method assumes that you are willing to share your Euphoria source code with
  32815.  your users.
  32816.  
  32817. <p>
  32818.  The Complete Edition gives you two more methods of distribution. You can
  32819.  <font color="#993333"><_bq>shroud</_bq></font> your program, or you can
  32820.  <font color="#993333"><_bq>bind</_bq></font> your program.
  32821.  <font color="#993333"><b>Shrouding</b></font> combines
  32822.  all of the .e files that your program needs, along with your main file
  32823.  to create a single .ex, .exw, or .exu file. Comments are stripped out and
  32824.  variable and routine names are converted into short meaningless names.
  32825.  You can also apply a "scrambling" algorithm to further improve security
  32826.  and make your program tamper-proof.
  32827.  <font color="#993333"><b>Binding</b></font> combines your shrouded/scrambled
  32828.  program with ex.exe, exw.exe, or exu to create a
  32829.  <font color="#CC0099"><b>single, stand-alone executable (.exe)</b></font>
  32830.  file. For example, if your program is called "myprog<b>.</b>ex"
  32831.  you can create "myprog<b>.</b>exe" which will run identically.
  32832.  
  32833. <p>
  32834.  If you have just one program to distribute, and you want to conceal the
  32835.  source, you should make it into a <b>.exe</b> file. If you have several
  32836.  small programs, you might want to shroud each of them and ship just one copy
  32837.  of the Public Domain ex.exe, exw.exe or exu to run them. This will save
  32838.  disk space and give you a smaller <b>.</b>zip file for distribution.
  32839.  
  32840. <p>
  32841.  For more information about shrouding and binding, see
  32842.  <a href="bind.htm"><font color="#5500FF"><b>bind.doc</b></font></a>.
  32843.  
  32844. <p>
  32845.  
  32846. <a name=51></a>
  32847. <font color="#FF0099" size=+1>
  32848. <br>
  32849.  
  32850. <_sul>1.5.1 Licensing</_sul>
  32851.  
  32852. </font>
  32853. <p>
  32854.  You have complete royalty-free rights to distribute any Euphoria programs
  32855.  that you develop. You are free to distribute the Public Domain Edition
  32856.  <font color="#993333"><b>ex.exe</b></font>,
  32857.  <font color="#993333"><b>exw.exe</b></font> and 
  32858.  <font color="#993333"><b>exu</b></font> files
  32859.  so anyone can run your program. With the Complete Edition, you can
  32860.  <font color="#993333"><b>shroud</b></font> or
  32861.  <font color="#993333"><b>bind</b></font> your programs and distribute
  32862.  the resulting files royalty-free.
  32863.  
  32864.  
  32865. <p>
  32866.  You may incorporate any Euphoria source  
  32867.  files from this package into 
  32868.  your program, either "as is" or with your modifications. 
  32869.  (You will probably need at least a few of the standard include files 
  32870.  in any large program).
  32871.  
  32872. <p>
  32873.  We would appreciate it if you told people that your program was developed
  32874.  using Euphoria, and gave them the address:
  32875.  <b><a href="http://www.RapidEuphoria.com">
  32876.  http://www.RapidEuphoria.com</a></b>
  32877.  of our Web page, but we do not require any such acknowledgment.
  32878.  
  32879. <p>
  32880.  The only files that you may
  32881.  <font color="#CC0099"><i><_ba>not</_ba></i></font> distribute are the
  32882.  <font color="#993333"><b>ex.exe</b></font>,
  32883.  <font color="#993333"><b>exw.exe</b></font>,
  32884.  <font color="#993333"><b>bind.ex</b></font>,
  32885.  <font color="#993333"><b>bind.bat</b></font>,
  32886.  <font color="#993333"><b>bindw.bat</b></font>,
  32887.  and <font color="#993333"><b>shroud.bat</b></font>
  32888.  files that come with the Complete Edition for WIN32 + DOS32,
  32889.  and
  32890.  <font color="#993333"><b>exu</b></font>,
  32891.  <font color="#993333"><b>bind.ex</b></font>,
  32892.  <font color="#993333"><b>bind</b></font> and
  32893.  <font color="#993333"><b>shroud</b></font>
  32894.  that come with the Complete Edition for Linux.
  32895.  The sample icon file, <b>euphoria.ico</b>, that's included 
  32896.  with the WIN32 + DOS32 Complete Edition, may be distributed
  32897.  with or without your changes.
  32898.  
  32899. <_continue
  32900.   href="refman_2.htm"
  32901.   name="2. Language Definition"
  32902. >
  32903.  
  32904. </_width>
  32905. </body>
  32906. </html>
  32907. REFMAN_2.HTX
  32908. 72427
  32909. <_init_comment>
  32910. <html>
  32911. <head><title>Euphoria v2.2 Reference Manual Part I - Section 2 </title>
  32912. </head>
  32913. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  32914. <_width>
  32915. <_center><font color="#FF0099" size=+2>
  32916. <br>
  32917.                          2. Language Definition
  32918. </font></_center>
  32919. <p>
  32920. <a name=1></a>
  32921. <font color="#FF0099" size=+1>
  32922. <br>
  32923.  
  32924. <_dul>2.1 Objects</_dul>
  32925.  
  32926. </font>
  32927. <p>
  32928.  
  32929. <font color="#FF0099" size=+1>
  32930. <br>
  32931.  
  32932. <_sul>2.1.1 Atoms and Sequences</_sul>
  32933.  
  32934. </font>
  32935. <p>
  32936.  
  32937.  All data <font color="#993333"><b>objects</b></font> in Euphoria are either
  32938.  <font color="#993333"><b>atoms</b></font> or
  32939.  <font color="#993333"><b>sequences</b></font>.
  32940.  An <font color="#993333"><b>atom</b></font> is a single numeric value.
  32941.  A <font color="#993333"><b>sequence</b></font> is a collection of numeric
  32942.  values.
  32943.  
  32944. <p>
  32945.  The <font color="#993333"><b>objects</b></font> contained in a
  32946.  sequence can be an arbitrary mix of atoms or
  32947.  sequences. A sequence is represented by a list of objects in brace brackets,
  32948.  separated by commas. Atoms can have any integer or double-precision floating
  32949.  point value. They can range from approximately -1e300 (minus one times 10 to
  32950.  the power 300) to +1e300 with 15 decimal digits of accuracy. Here are some
  32951.  Euphoria objects:
  32952.  
  32953. <_eucode>
  32954.         -- examples of atoms:
  32955.         0
  32956.         1000
  32957.         98.6
  32958.         -1e6
  32959.  
  32960.         -- examples of sequences:
  32961.         {2, 3, 5, 7, 11, 13, 17, 19}
  32962.         {1, 2, {3, 3, 3}, 4, {5, {6}}}
  32963.         {{"jon", "smith"}, 52389, 97.25}
  32964.         {}                        -- the 0-element sequence
  32965. </_eucode>
  32966. <p>
  32967.  
  32968.  Numbers can also be entered in hexadecimal. For example:
  32969.  
  32970. <_eucode>
  32971.         #FE             -- 254
  32972.         #A000           -- 40960
  32973.         #FFFF00008      -- 68718428168
  32974.         -#10            -- -16
  32975. </_eucode>
  32976. <p>
  32977.  
  32978.  Only the capital letters A, B, C, D, E, F are allowed in hex numbers.
  32979.  
  32980. <p>
  32981.  Sequences can be nested to any depth, i.e. you can have sequences within
  32982.  sequences within sequences and so on to any depth (until you run out of
  32983.  memory). Brace brackets are used to construct sequences out of a list of
  32984.  expressions.  These expressions can be constant or evaluated at run-time.
  32985.  e.g.
  32986.  
  32987. <_eucode>
  32988.         {x+6, 9, y*w+2, sin(0.5)}
  32989. </_eucode>
  32990.  
  32991. <p>
  32992.  The <font color="#CC0099"><b>"Hierarchical Objects"</b></font> part
  32993.  of the Euphoria acronym comes from the
  32994.  hierarchical nature of nested sequences. This should not be confused with
  32995.  the class hierarchies of certain object-oriented languages.
  32996.  
  32997. <p>
  32998.  Why do we call them <font color="#993333"><_bq>atoms</_bq></font>?
  32999.  Why not just "numbers"? Well, an atom
  33000.  <font color="#CC0099"><_ba><i>is</i></_ba></font> just a
  33001.  number, but we wanted to have a distinctive term that emphasizes that they are
  33002.  indivisible. Of course in the world of physics, atoms were split into smaller
  33003.  parts many years ago, but in Euphoria you can't split them. They are the basic
  33004.  building blocks of all the data that a Euphoria program can manipulate. With
  33005.  this analogy, <font color="#993333"><b>sequences</b></font>
  33006.  might be thought of as "molecules", made from atoms
  33007.  and other molecules. A better analogy would be that sequences are like
  33008.  directories, and atoms are like files. Just as a directory on your computer
  33009.  can contain both files and other directories, a sequence can contain both
  33010.  atoms and other sequences (and
  33011.  <font color="#CC0099"><_ba><i>those</i></_ba></font> sequences can contain
  33012.  atoms and sequences and so on).
  33013.  
  33014. <p>
  33015.  As you will soon discover, sequences make Euphoria very simple
  33016.  <font color="#CC0099"><_ba><i>and</i></_ba></font> very powerful.
  33017.  <font color="#CC0099"><b>Understanding atoms and sequences is the key to
  33018.  understanding Euphoria.</b></font>
  33019.  
  33020. <dl>
  33021. <dt>
  33022.  <b><font color="#006633"><_sul>Performance Note:</_sul></font></b>
  33023. <dd>
  33024.  Does this mean that
  33025.  all atoms are stored in memory as
  33026.  8-byte floating-point numbers? No. The Euphoria interpreter usually stores
  33027.  integer-valued atoms as machine integers (4 bytes) to save space and
  33028.  improve execution speed. When fractional results occur or numbers get too
  33029.  big, conversion to floating-point happens automatically.
  33030. </dl>
  33031.  
  33032. <a name=11></a>
  33033. <font color="#FF0099" size=+1>
  33034. <br>
  33035.  
  33036. <_sul>2.1.2 Character Strings and Individual Characters</_sul>
  33037.  
  33038. </font>
  33039. <p>
  33040.  
  33041.  A <font color="#993333"><b>character string</b></font> is just a
  33042.  <font color="#993333"><b>sequence</b></font> of characters.
  33043.  It may be entered using quotes e.g.
  33044.  
  33045. <_eucode>
  33046.         "ABCDEFG"
  33047. </_eucode>
  33048.  
  33049. <p>
  33050.  Character strings may be manipulated and
  33051.  operated upon just like any other sequences. For example the above
  33052.  string is entirely equivalent to the sequence:
  33053.  
  33054.  
  33055. <_eucode>
  33056.         {65, 66, 67, 68, 69, 70, 71}
  33057. </_eucode>
  33058.  
  33059.  which contains the corresponding ASCII codes. The Euphoria compiler
  33060.  will immediately convert "ABCDEFG" to the above sequence of numbers.
  33061.  In a sense, there are no "strings" in Euphoria, only sequences of numbers.
  33062.  A quoted string is really just a convenient notation that saves you from
  33063.  having to type in all the ASCII codes.
  33064.  
  33065. <p>
  33066.  <a name=empty_seq></a>
  33067.  It follows that "" is equivalent to {}. Both represent the sequence of
  33068.  length-0, also known as the
  33069.  <font color="#993333"><b>empty sequence</b></font>. As a matter of
  33070.  programming style, it is natural to use "" to
  33071.  suggest a length-0 sequence of characters, and {} to suggest some other
  33072.  kind of sequence.
  33073.  
  33074. <p>
  33075.  <a name=char></a>
  33076.  An <font color="#993333"><b>individual character</b></font> is an
  33077.  <font color="#993333"><b>atom</b></font>.
  33078.  It must be entered using single quotes. There is a difference between an
  33079.  individual character (which is an atom), and a character string of length-1
  33080.  (which is a sequence). e.g.
  33081.  
  33082. <_eucode>
  33083.         'B'   -- equivalent to the atom 66 - the ASCII code for B
  33084.         "B"   -- equivalent to the sequence {66}
  33085. </_eucode>
  33086.  
  33087. <p>
  33088.  Again, 'B' is just a notation that is equivalent to typing 66. There aren't
  33089.  really any "characters" in Euphoria, just numbers (atoms).
  33090.  
  33091. <p>
  33092.  Keep in mind that an atom is
  33093.  <font color="#CC0099"><_ba><i>not</i></_ba></font> equivalent to a
  33094.  one-element sequence containing
  33095.  the same value, although there are a few built-in routines that choose
  33096.  to treat them similarly.
  33097.  
  33098. <p>
  33099.  Special characters may be entered using a back-slash:
  33100.  
  33101. <pre>
  33102.         \n        newline
  33103.         \r        carriage return
  33104.         \t        tab
  33105.         \\        backslash
  33106.         \"        double quote
  33107.         \'        single quote
  33108. </pre>
  33109.  
  33110. <p>
  33111.  For example, "Hello, World!\n", or '\\'. The Euphoria editor displays
  33112.  character strings in green.
  33113.  
  33114. <p>
  33115.  
  33116. <a name=12></a>
  33117. <font color="#FF0099" size=+1>
  33118. <br>
  33119.  
  33120. <_sul>2.1.3 Comments</_sul>
  33121.  
  33122. </font>
  33123. <p>
  33124.  
  33125.  Comments are started by two dashes and extend to the end of the current line.
  33126.  e.g.
  33127.  
  33128. <_eucode>
  33129.         -- this is a comment
  33130. </_eucode>
  33131.  
  33132. <p>
  33133.  Comments are ignored by the compiler and have no effect on execution speed.
  33134.  The editor displays comments in red. 
  33135. <p> 
  33136.  On the first line (only) of your program,
  33137.  you can use a special comment beginning with #!, e.g.
  33138. <_eucode>
  33139.         #!/home/rob/euphoria/bin/exu  
  33140. </_eucode>
  33141. This informs the Linux shell that your file should be executed by the
  33142. Euphoria interpreter, and gives the full path to the interpreter.
  33143. If you make your file executable, you can run it, just by typing its name,
  33144. and without the need to type "exu". On DOS and Windows (version 2.2 or later)
  33145. this line is treated as a comment.
  33146. <p>
  33147. <hr>
  33148.  
  33149. <a name=2></a>
  33150. <font color="#FF0099" size=+1>
  33151. <br>
  33152.  
  33153. <_dul>2.2 Expressions</_dul>
  33154.  
  33155. </font>
  33156. <p>
  33157.  
  33158.  Like other programming languages, Euphoria lets you calculate results by
  33159.  forming expressions. However, in Euphoria you can perform calculations on
  33160.  entire sequences of data with one expression, where in most other languages
  33161.  you would have to construct a loop. In Euphoria you can handle a sequence
  33162.  much as you would a single number. It can be copied, passed to a subroutine,
  33163.  or calculated upon as a unit. For example,
  33164.  
  33165. <_eucode>
  33166.         {1,2,3} + 5
  33167. </_eucode>
  33168.  
  33169.  is an expression that adds the sequence {1,2,3} and the atom 5 to get the
  33170.  resulting sequence {6,7,8}.
  33171.  
  33172. <p>
  33173.  We will see more examples later.
  33174.  
  33175. <p>
  33176.  
  33177. <a name=23></a>
  33178. <font color="#FF0099" size=+1>
  33179. <br>
  33180.  
  33181. <_sul>2.2.1 Relational Operators</_sul>
  33182.  
  33183. </font>
  33184. <p>
  33185.  
  33186.  The relational operators  <font color="#993333"><b><   >   <=  
  33187.  >=   =   !=  </b></font> each produce a 1 (true) or a
  33188.  0 (false) result.
  33189.  
  33190. <_eucode>
  33191.         1 > 0       -- 1 (true)
  33192.         1 = 1       -- 1 (true)
  33193.         4.4 >= 4.5  -- 0 (false)
  33194. </_eucode>
  33195.  
  33196. <p>
  33197.  As we will soon see you can also apply these operators to sequences.
  33198.  
  33199. <p>
  33200.  
  33201. <a name=24></a>
  33202. <font color="#FF0099" size=+1>
  33203. <br>
  33204.  
  33205. <_sul>2.2.2 Logical Operators</_sul>
  33206.  
  33207. </font>
  33208. <p>
  33209.  
  33210.  The logical operators <font color="#993333"><_bsq>and</_bsq></font>,
  33211.  <font color="#993333"><_bsq>or</_bsq></font>,
  33212.  <font color="#993333"><_bsq>xor</_bsq></font>,
  33213.  and <font color="#993333"><_bsq>not</_bsq></font>
  33214.  are used to determine the
  33215.  "truth" of an expression. e.g.
  33216.  
  33217. <_eucode>
  33218.         1 and 1     -- 1 (true)
  33219.         1 and 0     -- 0 (false)
  33220.         0 and 1     -- 0 (false)
  33221.         0 and 0     -- 0 (false)
  33222.  
  33223.         1 or  1     -- 1 (true)
  33224.         1 or  0     -- 1 (true)
  33225.         0 or  1     -- 1 (true)
  33226.         0 or  0     -- 0 (false)
  33227.  
  33228.         1 xor 1     -- 0 (false)
  33229.         1 xor 0     -- 1 (true)
  33230.         0 xor 1     -- 1 (true)
  33231.         0 xor 0     -- 0 (false)
  33232.  
  33233.         not 1       -- 0 (false)
  33234.         not 0       -- 1 (true)
  33235. </_eucode>
  33236.  
  33237. <p>
  33238.  You can also apply these operators to numbers other than 1 or 0. The rule is:
  33239.  zero means false and non-zero means true. So for instance:
  33240.  
  33241. <_eucode>
  33242.         5 and -4    -- 1 (true)
  33243.         not 6       -- 0 (false)
  33244. </_eucode>
  33245.  
  33246. <p>
  33247.  These operators can also be applied to sequences. See below.
  33248.  
  33249. <p>
  33250.  In some cases <a href="refman_2.htm#shortcir"><_bq>short-circuit</_bq></a>
  33251.  evaluation will be used for expressions containing
  33252.  <font color="#993333"><_bq>and</_bq></font> or
  33253.  <font color="#993333"><_bq>or</_bq></font>.
  33254.  
  33255. <p>
  33256.  
  33257. <a name=25></a>
  33258. <font color="#FF0099" size=+1>
  33259. <br>
  33260.  
  33261. <_sul>2.2.3 Arithmetic Operators</_sul>
  33262.  
  33263. </font>
  33264. <p>
  33265.  
  33266.  The usual arithmetic operators are available: add, subtract, multiply,
  33267.  divide, unary minus, unary plus.
  33268.  
  33269. <_eucode>
  33270.         3.5 + 3  -- 6.5
  33271.         3 - 5    -- -2
  33272.         6 * 2    -- 12
  33273.         7 / 2    -- 3.5
  33274.         -8.1     -- -8.1
  33275.         +8       -- +8
  33276. </_eucode>
  33277.  
  33278. <p>
  33279.  <a name=inf_nan></a>
  33280.  Computing a result that is too big (i.e. outside of -1e300 to +1e300) will
  33281.  result in one of the special atoms <b>+infinity</b> or <b>-infinity</b>.
  33282.  These appear as <_bq>inf</_bq> or <_bq>-inf</_bq> when you print them out.
  33283.  It is also possible to generate <_bq>nan</_bq> or <_bq>-nan</_bq>.
  33284.  "nan" means "not a number", i.e. an undefined value (such as inf
  33285.  divided by inf). These values are defined in the IEEE
  33286.  floating-point standard. If
  33287.  you see one of these special values in your output, it usually indicates an
  33288.  error in your program logic, although generating inf as an intermediate
  33289.  result may be acceptable in some cases. For instance, 1/inf is 0, which may
  33290.  be the "right" answer for your algorithm.
  33291.  
  33292. <p>
  33293.  Division by zero, as well as bad arguments to math library routines, e.g.
  33294.  square root of a negative number, log of a non-positive number etc. cause an
  33295.  immediate error message and your program is aborted.
  33296.  
  33297. <p>
  33298.  The only reason that you might use unary plus is to emphasize to the reader
  33299.  of your program that a number is positive. The interpreter does not actually
  33300.  calculate anything for this.
  33301.  
  33302. <p>
  33303.  
  33304. <a name=26></a>
  33305. <font color="#FF0099" size=+1>
  33306. <br>
  33307.  
  33308. <_sul>2.2.4 Operations on Sequences</_sul>
  33309.  
  33310. </font>
  33311. <p>
  33312.  
  33313.  All of the relational, logical and arithmetic operators described above,
  33314.  as well as the math routines described in
  33315.  <a href="library.htm">Part II - Library Routines</a>, can be applied
  33316.  to sequences as well as to single numbers (atoms).
  33317.  
  33318. <p>
  33319.  When applied to a sequence, a unary (one operand) operator is actually
  33320.  applied to each element in the sequence to yield a sequence of results of the
  33321.  same length. If one of these elements is itself a sequence then the same rule
  33322.  is applied again recursively. e.g.
  33323.  
  33324. <_eucode>
  33325.         x = -{1, 2, 3, {4, 5}}   -- x is {-1, -2, -3, {-4, -5}}
  33326. </_eucode>
  33327.  
  33328. <p>
  33329.  If a binary (two-operand) operator has operands which are both sequences then
  33330.  the two sequences must be of the same length. The binary operation is then
  33331.  applied to corresponding elements taken from the two sequences to get a
  33332.  sequence of results. e.g.
  33333.  
  33334. <_eucode>
  33335.         x = {5, 6, 7 {1, 1}} + {10, 10, 20, 100}
  33336.         -- x is {15, 16, 27, {101, 101}}
  33337. </_eucode>
  33338.  
  33339. <p>
  33340.  If a binary operator has one operand which is a sequence while the other is a
  33341.  single number (atom) then the single number is effectively repeated to
  33342.  form a sequence of equal length to the sequence operand. The rules for
  33343.  operating on two sequences then apply. Some examples:
  33344.  
  33345. <_eucode>
  33346.         y = {4, 5, 6}
  33347.  
  33348.         w = 5 * y   -- w is {20, 25, 30}
  33349.  
  33350.         x = {1, 2, 3}
  33351.  
  33352.         z = x + y                          -- z is {5, 7, 9}
  33353.  
  33354.         z = x < y                          -- z is {1, 1, 1}
  33355.  
  33356.         w = {{1, 2}, {3, 4}, {5}}
  33357.  
  33358.         w = w * y           -- w is {{4, 8}, {15, 20}, {30}}
  33359.  
  33360.         w = {1, 0, 0, 1} and {1, 1, 1, 0}    -- {1, 0, 0, 0}
  33361.  
  33362.         w = not {1, 5, -2, 0, 0}     -- w is {0, 0, 0, 1, 1}
  33363.  
  33364.         w = {1, 2, 3} = {1, 2, 4}    -- w is {1, 1, 0}
  33365.         -- note that the first '=' is assignment, and the
  33366.         -- second '=' is a relational operator that tests
  33367.         -- equality 
  33368. </_eucode>
  33369.  
  33370. <a name=21></a>
  33371. <font color="#FF0099" size=+1>
  33372. <br>
  33373.  
  33374. <_sul>2.2.5 Subscripting of Sequences</_sul>
  33375.  
  33376. </font>
  33377. <p>
  33378.  A single element of a sequence may be selected by giving the element number
  33379.  in square brackets. Element numbers start at 1. Non-integer subscripts are
  33380.  rounded down to an integer.
  33381.  
  33382. <p>
  33383.  For example, if x contains {5, 7.2, 9, 0.5, 13} then x[2] is 7.2. Suppose we
  33384.  assign something different to x[2]:
  33385.  
  33386. <_eucode>
  33387.         x[2] = {11,22,33}
  33388. </_eucode>
  33389.  
  33390. <p>
  33391.  Then x becomes: {5, {11,22,33}, 9, 0.5, 13}. Now if we ask for x[2] we get
  33392.  {11,22,33} and if we ask for x[2][3] we get the atom 33. If you try to
  33393.  subscript with a number that is outside of the range 1 to the number of
  33394.  elements, you will get a subscript error. For example x[0],  x[-99] or
  33395.  x[6] will cause errors. So will x[1][3] since x[1] is not a sequence. There
  33396.  is no limit to the number of subscripts that may follow a variable, but
  33397.  the variable must contain sequences that are nested deeply enough. The
  33398.  two dimensional array, common in other languages, can be easily represented
  33399.  with a sequence of sequences:
  33400.  
  33401. <_eucode>
  33402.         x = {
  33403.              {5, 6, 7, 8, 9},      -- x[1]
  33404.              {1, 2, 3, 4, 5},      -- x[2]
  33405.              {0, 1, 0, 1, 0}       -- x[3]
  33406.             }
  33407. </_eucode>
  33408.  
  33409.  where we have written the numbers in a way that makes the structure
  33410.  clearer. An expression of the form x[i][j] can be used to access any element.
  33411.  
  33412. <p>
  33413.  The two dimensions are not symmetric however, since an entire "row" can be
  33414.  selected with x[i], but there is no simple expression to select an entire
  33415.  column. Other logical structures, such as n-dimensional arrays, arrays of
  33416.  strings, structures, arrays of structures etc. can also be handled easily and
  33417.  flexibly:
  33418.  
  33419. <_eucode>
  33420.  3-D array:
  33421.         y = {
  33422.              {{1,1}, {3,3}, {5,5}},
  33423.              {{0,0}, {0,1}, {9,1}},
  33424.              {{-1,9},{1,1}, {2,2}}
  33425.             }
  33426. </_eucode>
  33427.  
  33428. <blockquote>
  33429.      y[2][3][1] is 9
  33430. </blockquote>
  33431.  
  33432. <p>
  33433.  Array of strings:
  33434.  
  33435. <_eucode>
  33436.         s = {"Hello", "World", "Euphoria", "", "Last One"}
  33437. </_eucode>
  33438.  
  33439. <blockquote>
  33440.      s[3] is "Euphoria" <br>
  33441.      s[3][1] is 'E'
  33442. </blockquote>
  33443.  
  33444. <p>
  33445.  A Structure:
  33446.  
  33447. <_eucode>
  33448.         employee = {
  33449.                     {"John","Smith"},
  33450.                     45000,
  33451.                     27,
  33452.                     185.5
  33453.                    }
  33454. </_eucode>
  33455.  
  33456. <blockquote>
  33457.      To access "fields" or elements within a structure it is good
  33458.      programming style to make up a set of constants that name the various
  33459.      fields. This will make your program easier to read. For the example
  33460.      above you might have:
  33461.  
  33462. </blockquote>
  33463.  
  33464. <_eucode>
  33465.         constant NAME = 1
  33466.         constant FIRST_NAME = 1, LAST_NAME = 2
  33467.  
  33468.         constant SALARY = 2
  33469.         constant AGE = 3
  33470.         constant WEIGHT = 4
  33471. </_eucode>
  33472.  
  33473. <blockquote>
  33474.      You could then access the person's name with employee[NAME], or if you
  33475.      wanted the last name you could say employee[NAME][LAST_NAME].
  33476. </blockquote>
  33477.  
  33478. <p>
  33479.  Array of structures:
  33480.  
  33481. <_eucode>
  33482.         employees = {
  33483.                      {{"John","Smith"}, 45000, 27, 185.5},   -- a[1]
  33484.                      {{"Bill","Jones"}, 57000, 48, 177.2},   -- a[2]
  33485.  
  33486.                      -- .... etc.
  33487.                     }
  33488. </_eucode>
  33489.  
  33490. <blockquote>
  33491.      employees[2][SALARY] would be 57000.
  33492. </blockquote>
  33493.  
  33494. <p>
  33495.  <font color="#CC0099"><b>Euphoria data structures are
  33496.  almost infinitely flexible.</b></font>
  33497.  Arrays in other languages are constrained to have a fixed number of elements,
  33498.  and those elements must all be of the same type. Euphoria eliminates both
  33499.  of those restrictions.
  33500.  You can easily add a new structure to the employee sequence above,
  33501.  or store an unusually long name in the NAME field and Euphoria will take
  33502.  care of it for you. If you wish, you can store a variety of different
  33503.  employee "structures", with different sizes, all in one sequence.
  33504.  
  33505. <p>
  33506.  Not only can a Euphoria program easily represent all conventional data
  33507.  structures but you can create very useful, flexible structures that would be
  33508.  extremely hard to declare in a conventional language.
  33509.  See <a href="refman_2.htm#3">2.3 Euphoria versus Conventional Languages</a>.
  33510.  
  33511. <p>
  33512.  Note that expressions in general may not be subscripted, just variables. For
  33513.  example: {5+2,6-1,7*8,8+1}[3] is
  33514.  <font color="#CC0099"><_ba><i>not</i></_ba></font> supported. There are
  33515.  a few instances
  33516.  where this would be convenient, but in general it indicates that you are
  33517.  wastefully discarding some results that you have calculated.
  33518.  
  33519. <p>
  33520.  
  33521. <a name=22></a>
  33522. <font color="#FF0099" size=+1>
  33523. <br>
  33524.  
  33525. <_sul>2.2.6 Slicing of Sequences</_sul>
  33526.  
  33527. </font>
  33528. <p>
  33529.  
  33530.  A sequence of consecutive elements may be selected by giving the starting and
  33531.  ending element numbers. For example if x is {1, 1, 2, 2, 2, 1, 1, 1} then
  33532.  x[3..5] is the sequence {2, 2, 2}. x[3..3] is the sequence {2}. x[3..2] is
  33533.  also allowed. It evaluates to the length-0 sequence {}.  If y has the value:
  33534.  {"fred", "george", "mary"} then y[1..2] is {"fred", "george"}.
  33535.  
  33536. <p>
  33537.  We can also use slices for overwriting portions of variables. After x[3..5] =
  33538.  {9, 9, 9} x would be {1, 1, 9, 9, 9, 1, 1, 1}. We could also have said
  33539.  x[3..5] = 9 with the same effect. Suppose y is {0, "Euphoria", 1, 1}.
  33540.  Then y[2][1..4] is "Euph". If we say y[2][1..4]="ABCD" then y will
  33541.  become {0, "ABCDoria", 1, 1}.
  33542.  
  33543. <p>
  33544.  In general, a variable name can be followed by 0 or more subscripts,
  33545.  followed in turn by 0 or 1 slices. Only variables may be subscripted or
  33546.  sliced, not expressions.
  33547.  
  33548. <p>
  33549.  We need to be a bit more precise in defining the rules for
  33550.  <font color="#993333"><b>empty slices</b></font>. Consider a slice s[i..j]
  33551.  where s is of length n. A slice from i to j, where  j = i-1  and i >= 1
  33552.  produces the <a href="refman_2.htm#empty_seq">empty sequence</a>, even if
  33553.  i = n+1. Thus 1..0  and n+1..n and everything in between are legal <b>
  33554.  <font color="#993333">(empty) slices</font></b>.
  33555.  Empty slices are quite useful in many algorithms. A slice from i to j where
  33556.  j < i - 1 is illegal , i.e. "reverse" slices such as s[5..3] are not allowed.
  33557.  
  33558. <p>
  33559.  
  33560. <a name=27></a>
  33561. <font color="#FF0099" size=+1>
  33562. <br>
  33563.  
  33564. <_sul>2.2.7 Concatenation of Sequences and Atoms - The '&' Operator</_sul>
  33565.  
  33566. </font>
  33567. <p>
  33568.  
  33569.  Any two objects may be concatenated using the
  33570.  <font color="#993333"><b>&</b></font> operator. The result is a
  33571.  sequence with a length equal to the sum of the lengths of the concatenated
  33572.  objects (where atoms are considered here to have length 1). e.g.
  33573.  
  33574. <_eucode>
  33575.         {1, 2, 3} & 4              -- {1, 2, 3, 4}
  33576.  
  33577.         4 & 5                      -- {4, 5}
  33578.  
  33579.         {{1, 1}, 2, 3} & {4, 5}    -- {{1, 1}, 2, 3, 4, 5}
  33580.  
  33581.         x = {}
  33582.         y = {1, 2}
  33583.         y = y & x                  -- y is still {1, 2}
  33584. </_eucode>
  33585.  
  33586. <p>
  33587. You can delete element i of any sequence s by concatenating the
  33588. parts of the sequence before and after i:
  33589.  
  33590. <_eucode>
  33591.     s = s[1..i-1] & s[i+1..length(s)]
  33592. </_eucode>
  33593.  
  33594. This works even when i is 1 or length(s), since s[1..0] is a legal empty slice,
  33595. and so is s[length(s)+1..length(s)].
  33596.  
  33597. <p>
  33598.  
  33599. <a name=28></a>
  33600. <font color="#FF0099" size=+1>
  33601. <br>
  33602.  
  33603. <_sul>2.2.8 Sequence-Formation</_sul>
  33604.  
  33605. </font>
  33606. <p>
  33607.  
  33608.  Finally, sequence-formation, using braces and commas:
  33609.  
  33610. <_eucode>
  33611.         {a, b, c, ... }
  33612. </_eucode>
  33613.  
  33614.  is also an operator. It takes n operands, where n is 0 or more, and makes an
  33615.  n-element sequence from their values. e.g.
  33616.  
  33617. <_eucode>
  33618.         x = {apple, orange*2, {1,2,3}, 99/4+foobar}
  33619. </_eucode>
  33620. <p>
  33621.  The sequence-formation operator is listed at the bottom of the
  33622.  <a href="refman_2.htm#2A">precedence chart</a>.
  33623.  
  33624. <p>
  33625.  
  33626. <a name=29></a>
  33627. <font color="#FF0099" size=+1>
  33628. <br>
  33629.  
  33630. <_sul>2.2.9 Other Operations on Sequences</_sul>
  33631.  
  33632. </font>
  33633. <p>
  33634.  
  33635.  Some other important operations that you can perform on sequences have
  33636.  English names, rather than special characters.
  33637.  These operations are built-in to 
  33638.  <font color="#993333"><b>ex.exe</b></font>/<font color="#993333"><b>exw.exe</b></font>/<font color="#993333"><b>exu</b></font>
  33639.  , so
  33640.  they'll always be there, and
  33641.  so they'll be fast. They are described in detail in
  33642.  <a href="library.htm">Part II - Library Routines</a>, but are important
  33643.  enough to Euphoria programming that we should mention them here before
  33644.  proceeding. You call these operations as if they were subroutines, although
  33645.  they are actually implemented much more efficiently than that.
  33646.  
  33647. <p>
  33648.  
  33649. <a name=291></a>
  33650.  
  33651. <br>
  33652.  
  33653. <_sul><font color="#CC3366" size=+1>length(s)</font></_sul>
  33654.  
  33655. </font>
  33656. <p>
  33657.  
  33658.  <a href="lib_h_o.htm#length"><font color="#993333"><b>length()</b></font></a>
  33659.  tells you the length of a sequence s. This is the number of
  33660.  elements in s. Some of these elements may be sequences that contain elements
  33661.  of their own, but length just gives you the "top-level" count. You'll get an
  33662.  error if you ask for the length of an atom. e.g.
  33663.  
  33664. <_eucode>
  33665.         length({5,6,7})             -- 3
  33666.         length({1, {5,5,5}, 2, 3})  -- 4 (not 6!)
  33667.         length({})                  -- 0
  33668.         length(5)                   -- error!
  33669. </_eucode>
  33670.  
  33671. <a name=292></a>
  33672. <br>
  33673.  
  33674. <_sul><font color="#CC3366" size=+1>repeat(item, count)</font></_sul>
  33675.  
  33676. </font>
  33677. <p>
  33678.  
  33679.  <a href="lib_p_r.htm#repeat"><font color="#993333"><b>repeat()</b></font></a>
  33680.  makes a sequence that consists of an item repeated count times. e.g.
  33681. <_eucode>
  33682.         repeat(0, 100)         -- {0,0,0,...,0}   i.e. 100 zeros
  33683.         repeat("Hello", 3)     -- {"Hello", "Hello", "Hello"}
  33684.         repeat(99,0)           -- {}
  33685. </_eucode>
  33686.  
  33687. <p>
  33688.  The item to be repeated can be any atom or sequence.
  33689.  
  33690. <p>
  33691.  
  33692. <a name=293></a>
  33693.  
  33694. <br>
  33695.  
  33696. <_sul><font color="#CC3366" size=+1>append(s, item) /
  33697.       prepend(s, item)</font></_sul>
  33698.  
  33699. </font>
  33700. <p>
  33701.  
  33702.  <a href="lib_a_b.htm#append"><font color="#993333"><b>append()</b></font></a>
  33703.  creates a new sequence by adding an item to the end of a sequence s.
  33704.  <a href="lib_p_r.htm#prepend"><font color="#993333"><b>prepend()</b></font></a>
  33705.  creates a new sequence by adding an element to the beginning of a
  33706.  sequence s. e.g.
  33707.  
  33708. <_eucode>
  33709.         append({1,2,3}, 4)         -- {1,2,3,4}
  33710.         prepend({1,2,3}, 4)        -- {4,1,2,3}
  33711.  
  33712.         append({1,2,3}, {5,5,5})   -- {1,2,3,{5,5,5}}
  33713.         prepend({}, 9)             -- {9}
  33714.         append({}, 9)              -- {9}
  33715. </_eucode>
  33716.  
  33717. <p>
  33718.  The length of the new sequence is always 1 greater than the length of the
  33719.  original sequence. The item to be added to the sequence can be any atom or
  33720.  sequence.
  33721.  
  33722. <p>
  33723.  These two built-in functions, <font color="#993333"><b>append()</b></font>
  33724.  and <font color="#993333"><b>prepend()</b></font>, have some similarities
  33725.  to the concatenate operator, <font color="#993333"><b>&</b></font>,
  33726.  but there are clear differences. e.g.
  33727.  
  33728. <_eucode>
  33729.         -- appending a sequence is different
  33730.         append({1,2,3}, {5,5,5})   -- {1,2,3,{5,5,5}}
  33731.         {1,2,3} & {5,5,5}          -- {1,2,3,5,5,5}
  33732.  
  33733.         -- appending an atom is the same
  33734.         append({1,2,3}, 5)         -- {1,2,3,5}
  33735.         {1,2,3} & 5                -- {1,2,3,5}
  33736. </_eucode>
  33737.  
  33738. <a name=2A></a>
  33739. <font color="#FF0099" size=+1>
  33740. <br>
  33741.  
  33742. <_sul>2.2.10 Precedence Chart</_sul>
  33743.  
  33744. </font>
  33745. <p>
  33746.  
  33747.  The precedence of operators in expressions is as follows:
  33748.  
  33749. <pre>
  33750.         <font color="#009999"><b>highest precedence:</b></font>     function/type calls
  33751.  
  33752.                                 unary-  unary+  not
  33753.  
  33754.                                 *  /
  33755.  
  33756.                                 +  -
  33757.  
  33758.                                 &
  33759.  
  33760.                                 <  >  <=  >=  =  !=
  33761.  
  33762.                                 and  or  xor
  33763.  
  33764.         <font color="#009999"><b>lowest precedence:</b></font>      { , , , }
  33765. </pre>
  33766.  
  33767. <p>
  33768.  Thus 2+6*3 means 2+(6*3) rather than (2+6)*3. Operators on the same line
  33769.  above have equal precedence and are evaluated left to right.
  33770.  
  33771. <p>
  33772.  The equals symbol '=' used in an
  33773.  <a href="refman_2.htm#assign">assignment statement</a> is not an operator,
  33774.  it's just part of the syntax of the language.
  33775.  
  33776. <p>
  33777. <hr>
  33778.  
  33779. <a name=3></a>
  33780. <font color="#FF0099" size=+1>
  33781. <br>
  33782.  
  33783. <_dul>2.3 Euphoria versus Conventional Languages</_dul>
  33784.  
  33785. </font>
  33786. <p>
  33787.  
  33788.  By basing Euphoria on this one, simple, general, recursive data structure,
  33789.  a tremendous amount of the complexity normally found in programming languages
  33790.  has been avoided. The arrays, structures, unions, arrays of records,
  33791.  multidimensional arrays, etc. of other languages can all be easily
  33792.  represented in Euphoria with sequences. So can higher-level structures such
  33793.  as lists, stacks, queues, trees etc.
  33794.  
  33795. <p>
  33796.  Furthermore, in Euphoria you can have sequences of mixed type; you can
  33797.  assign any object to an element of a sequence; and sequences easily grow or
  33798.  shrink in length without your having to worry about storage allocation issues.
  33799.  The exact layout of a data structure does not have to be declared in advance,
  33800.  and can change dynamically as required. It is easy to write generic code,
  33801.  where, for instance, you push or pop a mix of various kinds of data
  33802.  objects using a single stack. Making a flexible list that contains a variety
  33803.  of different kinds of data objects is trivial in Euphoria, but requires dozens
  33804.  of lines of ugly code in other languages.
  33805.  
  33806. <p>
  33807.  Data structure manipulations are very efficient since the Euphoria interpreter
  33808.  will point to large data objects rather than copy them.
  33809.  
  33810. <p>
  33811.  Programming in Euphoria is based entirely on creating and manipulating
  33812.  flexible, dynamic sequences of data. Sequences are
  33813.  <font color="#CC0099"><_ba><i>it</i></_ba></font> - there are no
  33814.  other data structures to learn. You operate in a simple, safe, elastic world
  33815.  of <font color="#CC0099"><_ba><i>values</i></_ba></font>, that is far
  33816.  removed from the rigid, tedious, dangerous world
  33817.  of bits, bytes, pointers and machine crashes.
  33818.  
  33819. <p>
  33820.  Unlike other languages such as LISP and Smalltalk, Euphoria's
  33821.  "garbage collection" of unused storage is a continuous process that never
  33822.  causes random delays in execution of a program, and does not pre-allocate
  33823.  huge regions of memory.
  33824.  
  33825. <p>
  33826.  The language definitions of conventional languages such as C, C++, Ada, etc.
  33827.  are very complex. Most programmers become fluent in only a subset of the
  33828.  language. The ANSI standards for these languages read like complex legal
  33829.  documents.
  33830.  
  33831. <p>
  33832.  You are forced to write different code for different data types simply to
  33833.  copy the data, ask for its current length, concatenate it, compare it etc.
  33834.  The manuals for those languages are packed with routines such as "strcpy",
  33835.  "strncpy", "memcpy", "strcat",  "strlen", "strcmp", "memcmp", etc. that
  33836.  each only work on one of the many types of data.
  33837.  
  33838. <p>
  33839.  Much of the complexity surrounds issues of data type. How do you define
  33840.  new types? Which types of data can be mixed? How do you convert one type
  33841.  into another in a way that will keep the compiler happy? When you need to
  33842.  do something requiring flexibility at run-time, you frequently find yourself
  33843.  trying to fake out the compiler.
  33844.  
  33845. <p>
  33846.  In these languages the numeric value 4 (for example) can have a different
  33847.  meaning depending on whether it is an int, a char, a short, a double, an
  33848.  int * etc. In Euphoria, 4 is the atom 4, period. Euphoria has something
  33849.  called types as we shall see later, but it is a much simpler concept.
  33850.  
  33851. <p>
  33852.  Issues of dynamic storage allocation and deallocation consume a great deal
  33853.  of programmer coding time and debugging time in these other languages, and
  33854.  make the resulting programs much harder to understand. Programs that must
  33855.  run continuously often exhibit storage "leaks", since it takes a great
  33856.  deal of discipline to safely and properly free all blocks of storage
  33857.  once they are no longer needed.
  33858.  
  33859. <p>
  33860.  Pointer variables are extensively used. The pointer has been called the
  33861.  "go to" of data structures. It forces programmers to think of data as
  33862.  being bound to a fixed memory location where it can be manipulated in all
  33863.  sorts of low-level, non-portable, tricky ways. A picture of the actual
  33864.  hardware that your program will run on is never far from your mind. Euphoria
  33865.  does not have pointers and does not need them.
  33866.  
  33867. <p>
  33868. <hr>
  33869.  
  33870. <a name=4></a>
  33871. <font color="#FF0099" size=+1>
  33872. <br>
  33873.  
  33874. <_dul>2.4 Declarations</_dul>
  33875.  
  33876. </font>
  33877. <p>
  33878.  
  33879. <a name=41></a>
  33880. <font color="#FF0099" size=+1>
  33881. <br>
  33882.  
  33883. <_sul>2.4.1 Identifiers</_sul>
  33884.  
  33885. </font>
  33886. <p>
  33887.  
  33888.  <font color="#993333"><b>Identifiers</b></font>, which consist of
  33889.  variable names and other user-defined symbols, may be of any
  33890.  length. Upper and lower case are distinct. Identifiers must start with a
  33891.  letter and then be followed by letters, digits or underscores. The following
  33892.  <font color="#993333"><b>reserved words</b></font>
  33893.  have special meaning in Euphoria and may not be used as identifiers:
  33894.  
  33895. <b><_eucode>
  33896.     and            end             include          to
  33897.     by             exit            not              type
  33898.     constant       for             or               while
  33899.     do             function        procedure        with
  33900.     else           global          return           without
  33901.     elsif          if              then             xor
  33902. </_eucode></b>
  33903.  
  33904. <p>
  33905.  The Euphoria editor displays these words in blue.
  33906.  
  33907. <p>
  33908.  Identifiers can be used in naming the following:
  33909.  <ul>
  33910.  <li>procedures
  33911.  <li>functions
  33912.  <li>types
  33913.  <li>variables
  33914.  <li>constants
  33915.  </ul>
  33916.  
  33917. <p>
  33918. <a name=411></a>
  33919. <font color="#CC3366" size=+1>
  33920. <br>
  33921.  
  33922. <_sul>procedures</_sul>
  33923.  
  33924. </font>
  33925. <p>
  33926.  
  33927.         These perform some computation and may have a list of parameters,
  33928.         e.g.
  33929.  
  33930. <_eucode>
  33931.         procedure empty()
  33932.         end procedure
  33933.  
  33934.         procedure plot(integer x, integer y)
  33935.             position(x, y)
  33936.             puts(1, '*')
  33937.         end procedure
  33938. </_eucode>
  33939.  
  33940. <p>
  33941.         There are a fixed number of named parameters, but this is not
  33942.         restrictive since any parameter could be a variable-length sequence
  33943.         of arbitrary objects. In many languages variable-length parameter
  33944.         lists are impossible.  In C, you must set up strange mechanisms that
  33945.         are complex enough that the average programmer cannot do it without
  33946.         consulting a manual or a local guru.
  33947.  
  33948. <p>
  33949.         A copy of the value of each argument is passed in. The formal
  33950.         parameter variables may be modified inside the procedure but this does
  33951.         not affect the value of the arguments.
  33952.  
  33953. <dl>
  33954. <dt>
  33955.         <b><font color="#006633"><_sul>Performance Note:</_sul></font></b>
  33956. <dd>
  33957.         The interpreter does not actually copy sequences or
  33958.         floating-point numbers unless it becomes necessary. For example,
  33959. <_eucode>
  33960.             y = {1,2,3,4,5,6,7,8.5,"ABC"}
  33961.             x = y
  33962. </_eucode>
  33963.         The statement x = y does not actually cause a new copy of y to be
  33964.         created. Both x and y will simply "point" to the same sequence. If we
  33965.         later perform x[3] = 9, then a separate sequence will be created for x
  33966.         in memory (although there will still be just one shared copy of 8.5 and
  33967.         "ABC"). The same thing applies to "copies" of arguments passed in to
  33968.         subroutines.
  33969. </dl>
  33970.  
  33971. <a name=412></a>
  33972. <font color="#CC3366" size=+1>
  33973. <br>
  33974.  
  33975. <_sul>functions</_sul>
  33976.  
  33977. </font>
  33978. <p>
  33979.  
  33980.         These are just like procedures, but they return a value, and can be
  33981.         used in an expression, e.g.
  33982.  
  33983. <_eucode>
  33984.         function max(atom a, atom b)
  33985.             if a >= b then
  33986.                 return a
  33987.             else
  33988.                 return b
  33989.             end if
  33990.         end function
  33991. </_eucode>
  33992.  
  33993. <p>
  33994.         Any Euphoria object can be returned.  You can, in effect, have
  33995.         multiple return values, by returning a sequence of objects. e.g.
  33996.  
  33997. <_eucode>
  33998.         return {x_pos, y_pos}
  33999. </_eucode>
  34000.  
  34001. <p>
  34002.         We will use the general term "subroutine", or simply "routine" when a
  34003.         remark is applicable to both procedures and functions.
  34004.  
  34005. <p>
  34006. <a name=413></a>
  34007. <font color="#CC3366" size=+1>
  34008. <br>
  34009.  
  34010. <_sul>types</_sul>
  34011.  
  34012. </font>
  34013. <p>
  34014.  
  34015.         These are special functions that may be used in declaring the allowed
  34016.         values for a variable. A type must have exactly one parameter and
  34017.         should return an atom that is either true (non-zero) or false (zero).
  34018.         Types can also be called just like other functions. See
  34019.         <a href="refman_2.htm#43">2.4.3 Specifying the Type of a Variable</a>.
  34020.  
  34021. <p>
  34022. <a name=414></a>
  34023. <font color="#CC3366" size=+1>
  34024. <br>
  34025.  
  34026. <_sul>variables</_sul>
  34027.  
  34028. </font>
  34029. <p>
  34030.  
  34031.         These may be assigned values during execution e.g.
  34032.  
  34033. <_eucode>
  34034.         -- x may only be assigned integer values
  34035.         integer x
  34036.         x = 25
  34037.  
  34038.         -- a, b and c may be assigned *any* value
  34039.         object a, b, c
  34040.         a = {}
  34041.         b = a
  34042.         c = 0
  34043. </_eucode>
  34044.  
  34045. <p>
  34046.         When you declare a variable you name the variable (which protects you
  34047.         against making spelling mistakes later on) and you specify the values
  34048.         that may legally be assigned to the variable during execution of
  34049.         your program.
  34050.  
  34051. <p>
  34052. <a name=415></a>
  34053. <font color="#CC3366" size=+1>
  34054. <br>
  34055.  
  34056. <_sul>constants</_sul>
  34057.  
  34058. </font>
  34059. <p>
  34060.  
  34061.         These are variables that are assigned an initial value that can
  34062.         never change e.g.
  34063.  
  34064. <_eucode>
  34065.         constant MAX = 100
  34066.         constant Upper = MAX - 10, Lower = 5
  34067.         constant name_list = {"Fred", "George", "Larry"}
  34068. </_eucode>
  34069.  
  34070. <p>
  34071.         The result of any expression can be assigned to a constant, even one
  34072.         involving calls to previously defined functions, but once the
  34073.         assignment is made, the value of the constant variable is "locked in".
  34074.  
  34075. <p>
  34076.         Constants may not be declared inside a subroutine.
  34077.  
  34078. <p>
  34079. <a name=42></a>
  34080. <font color="#FF0099" size=+1>
  34081. <br>
  34082.  
  34083. <_sul>2.4.2 Scope</_sul>
  34084.  
  34085. </font>
  34086. <p>
  34087.  
  34088.  Every symbol must be declared before it is used. You can read a program
  34089.  from beginning to end without encountering any variables or routines that
  34090.  haven't been defined yet. It is possible to call a routine that comes later
  34091.  in the source, but you must use the special functions,
  34092.  <font color="#993333"><b>routine_id()</b></font>,
  34093.  and either <font color="#993333"><b>call_func()</b></font> or
  34094.  <font color="#993333"><b>call_proc()</b></font> to do it.
  34095.  See <a href="library.htm#dyn_call">Part II -
  34096.  Library Routines - Dynamic Calls</a>.
  34097.  
  34098. <p>
  34099.  Procedures, functions and types can call themselves recursively. Mutual
  34100.  recursion, where routine A calls routine B which directly or indirectly calls
  34101.  routine A, requires the <a href="lib_p_r.htm#routine_id">
  34102.  <font color="#993333"><b>routine_id()</b></font></a> mechanism.
  34103.  
  34104. <p>
  34105.  <a name=scope></a>
  34106.  A symbol is defined from the point where it is declared to the end of its
  34107.  <font color="#993333"><_bq>scope</_bq></font>.
  34108.  The scope of a variable declared inside a procedure or function (a
  34109.  <font color="#993333"><_bq>private</_bq></font> variable) ends
  34110.  at the end of the procedure or function.  The scope
  34111.  of all other variables, constants, procedures, functions and types ends at
  34112.  the end of the source file in which they are declared and they are referred
  34113.  to as <font color="#993333"><_bq>local</_bq></font>,
  34114.  unless the keyword
  34115.  <font color="#993333"><_bq>global</_bq></font> precedes
  34116.  their declaration, in which case their scope extends indefinitely.
  34117.  
  34118. <p>
  34119.  When you include a Euphoria file in a main file (see
  34120.  <a href="refman_2.htm#6">2.6 Special Top-Level Statements</a>),
  34121.  only the variables and routines declared using the
  34122.  <font color="#993333"><_bq>global</_bq></font> keyword are
  34123.  accessible or even visible to the main file. The other, non-global,
  34124.  declarations in the included file are forgotten by the compiler at the end of
  34125.  the included file, and you will get an error message, "not declared", if you
  34126.  try to use them in the main file.
  34127.  
  34128. <p>
  34129.  The <font color="#993333"><_bq>global</_bq></font> keyword
  34130.  makes it clear which symbols are to be used directly by the
  34131.  users of an include file, and which symbols are strictly for internal use
  34132.  within the include file.
  34133.  
  34134. <p>
  34135.  Euphoria encourages you to restrict the scope of symbols. If all symbols were
  34136.  automatically global to the whole program, there would tend to be a lot of
  34137.  naming conflicts in large programs, especially when different parts of a
  34138.  program are written by different programmers. A naming conflict might cause
  34139.  a compiler error message, or it could lead to a very subtle bug, where
  34140.  different parts of a program accidentally modify the same variable without
  34141.  being aware of it.
  34142.  
  34143. <p>
  34144.  Try to use the most restrictive scope that you can. Make variables
  34145.  <font color="#993333"><b>private</b></font> to
  34146.  one routine where possible, and where that isn't possible, make them
  34147.  <font color="#993333"><b>local</b></font> to a file, rather than
  34148.  <font color="#993333"><b>global</b></font> to the whole program.
  34149.  
  34150. <p>
  34151.  <font color="#993333"><b>Constant</b></font> declarations must be
  34152.  outside of any subroutine. Constants cannot be
  34153.  <font color="#993333"><b>private</b></font>.
  34154.  
  34155. <p>
  34156.  Variable declarations inside a subroutine must all appear at the beginning,
  34157.  before the executable statements of the subroutine.
  34158.  
  34159. <p>
  34160.  Declarations at the top level, outside of any subroutine, must really
  34161.  be at the very top. They can't be nested inside a loop or
  34162.  <a href="refman_2.htm#if">if-statement</a>.
  34163.  
  34164. <p>
  34165.  <a name=loop_scope></a>
  34166.  The controlling variable used in a
  34167.  <a href="refman_2.htm#for">for-loop</a> is special. It is automatically
  34168.  declared at the beginning of the loop, and its scope ends at the end of the
  34169.  for-loop. If the loop is inside a function or procedure, the loop variable is
  34170.  a <font color="#993333"><b>private</b></font> variable and may not have the
  34171.  same name as any other <font color="#993333"><b>private</b></font>
  34172.  variable. When the loop is at the top level, outside of any function or
  34173.  procedure, the loop variable is a <font color="#993333"><b>local</b></font>
  34174.  variable and may not have the same name as any other
  34175.  <font color="#993333"><b>global</b></font> or
  34176.  <font color="#993333"><b>local</b></font> variable in that file. You can
  34177.  use the same name in many different for-loops as long as the loops aren't
  34178.  nested. You do not
  34179.  declare loop variables as you would other variables. The range of values
  34180.  specified in the for statement defines the legal values of the loop
  34181.  variable - specifying a type would be redundant and is not allowed.
  34182.  
  34183. <p>
  34184.  
  34185. <a name=43></a>
  34186. <font color="#FF0099" size=+1>
  34187. <br>
  34188.  
  34189. <_sul>2.4.3 Specifying the Type of a Variable</_sul>
  34190.  
  34191. </font>
  34192. <p>
  34193.  
  34194.  So far you've already seen some examples of variable types but now we will
  34195.  define types more precisely.
  34196.  
  34197. <p>
  34198.  Variable declarations have a type name followed by a list of the variables
  34199.  being declared. For example,
  34200. <_eucode>
  34201.         object a
  34202.  
  34203.         global integer x, y, z
  34204.  
  34205.         procedure fred(sequence q, sequence r)
  34206. </_eucode>
  34207.  
  34208. <p>
  34209.  The types:
  34210.  <a href="refman_2.htm#1"><font color="#993333"><b>object</b></font>,
  34211.  <font color="#993333"><b>sequence</b></font>,
  34212.  <font color="#993333"><b>atom</b></font></a>
  34213.  and <font color="#993333"><b>integer</b></font> are <b>predefined</b>.
  34214.  Variables of type <font color="#993333"><b>object</b></font> may
  34215.  take on <font color="#CC0099"><_ba><i>any</i></_ba></font> value.
  34216.  Those declared with type <font color="#993333"><b>sequence</b></font>
  34217.  must always be sequences.
  34218.  Those declared with type <font color="#993333"><b>atom</b></font> must
  34219.  always be atoms.
  34220.  
  34221.  <a name=integer></a>
  34222.  Those declared with type <font color="#993333"><b>integer</b></font> must
  34223.  be atoms with integer values from -1073741824
  34224.  to +1073741823 inclusive. You can perform exact calculations on larger integer
  34225.  values, up to about 15 decimal digits, but declare them as
  34226.  <font color="#993333"><b>atom</b></font>, rather than integer.
  34227.  
  34228. <dl>
  34229. <dt>
  34230. <b><font color="#006633"><_sul>Note:</_sul></font></b>
  34231.  
  34232. <dd>
  34233.  In a procedure or function parameter list like the one for fred() above,
  34234.  a type name may only be followed by a single parameter name.
  34235.  
  34236. <p>
  34237. <dt>
  34238. <b><font color="#006633"><_sul>Performance Note:</_sul></font></b>
  34239.  
  34240. <dd>
  34241.  Calculations using variables declared as integer will
  34242.  usually be somewhat faster than calculations involving variables declared as
  34243.  atom. If your machine has floating-point hardware, Euphoria will use it to
  34244.  manipulate atoms that aren't representable as integers. If your machine
  34245.  doesn't have floating-point hardware, Euphoria will call software
  34246.  floating-point arithmetic routines contained in
  34247.  <font color="#993333"><b>ex.exe</b></font> (or in Windows).
  34248.  You can force ex.exe to bypass any floating-point hardware, by setting an
  34249.  environment variable:
  34250.  
  34251. <pre>
  34252.             SET NO87=1
  34253. </pre>
  34254.  
  34255.  The slower software routines will be used, but this could be of some
  34256.  advantage if you are worried about the floating-point bug in some early
  34257.  Pentium chips.
  34258. </dl>
  34259.  
  34260. <p>
  34261.  <a name=type></a>
  34262.  To augment the <a href="refman_2.htm#43">predefined types</a>, you can create
  34263.  <font color="#993333"><b>user-defined types</b></font>. All you have to
  34264.  do is define a single-parameter function, but declare it with
  34265.  <font color="#993333"><b>type ... end type</b></font> instead of
  34266.  <font color="#993333"><b>function ... end function</b></font>.
  34267.  For example,
  34268.  
  34269. <_eucode>
  34270.         type hour(integer x)
  34271.             return x >= 0 and x <= 23
  34272.         end type
  34273.  
  34274.         hour h1, h2
  34275.  
  34276.         h1 = 10      -- ok
  34277.         h2 = 25      -- error! program aborts with a message
  34278. </_eucode>
  34279.  
  34280. <p>
  34281.  Variables h1 and h2 can only be assigned integer values in the range 0 to 23
  34282.  inclusive. After each assignment to h1 or h2 the interpreter will call hour(),
  34283.  passing the new value.  The value will first be checked to see if it is an
  34284.  integer (because of "integer x"). If it is, the return statement will be
  34285.  executed to test the value of x (i.e. the new value of h1 or h2).  If hour()
  34286.  returns true, execution continues normally. If hour() returns false then the
  34287.  program is aborted with a suitable diagnostic message.
  34288.  
  34289. <p>
  34290.  "hour" can be used to declare subroutine parameters as well:
  34291.  
  34292. <_eucode>
  34293.         procedure set_time(hour h)
  34294. </_eucode>
  34295.  
  34296. <p>
  34297.  set_time() can only be called with a reasonable value for parameter h,
  34298.  otherwise the program will abort with a message.
  34299.  
  34300. <p>
  34301.  A variable's type will be checked after each assignment to the variable
  34302.  (except where the compiler can predetermine that a check will not be
  34303.  necessary), and the program will terminate immediately if the type function
  34304.  returns false.  Subroutine parameter types are checked each time that the
  34305.  subroutine is called. This checking guarantees that a variable can never have
  34306.  a value that does not belong to the type of that variable.
  34307.  
  34308. <p>
  34309.  <a name=typechk></a>
  34310.  Unlike other languages, the type of a variable does not affect any
  34311.  calculations on the variable. Only the value of the variable matters in an
  34312.  expression. The type just serves as an error check to prevent any "corruption"
  34313.  of the variable.
  34314.  
  34315. <p>
  34316.  Type checking can be turned off or on between subroutines using the
  34317.  <font color="#993333"><_bq>with type_check</_bq></font> or
  34318.  <font color="#993333"><_bq>without type_check</_bq></font>
  34319.  <a href="refman_2.htm#62">special statements</a>.
  34320.  It is initially on by default.
  34321.  
  34322. <dl>
  34323. <dt>
  34324. <b><font color="#006633"><_sul>Note to Benchmarkers:</_sul></font></b>
  34325. <dd>
  34326.  When comparing the speed of Euphoria programs against
  34327.  programs written in other languages, you should specify
  34328.  <font color="#993333"><b>without type_check</b></font> at the top of the file.
  34329.  This gives Euphoria permission to skip run-time
  34330.  type checks, thereby saving some execution time. All other checks are still
  34331.  performed, e.g. subscript checking, uninitialized variable checking etc.
  34332.  Even when you turn off type checking, Euphoria reserves the right to make
  34333.  checks at strategic places, since this can actually allow it to run your
  34334.  program <font color="#CC0099"><_ba><i>faster</i></_ba></font> in many cases.
  34335.  So you may still get a type check failure
  34336.  even when you have turned off type checking. Whether type checking is
  34337.  on or off, you will never get a <b><i>machine-level</i></b> exception.
  34338.  <font color="#CC0099"><b>You will always get a
  34339.  meaningful message from Euphoria when something goes wrong.</b></font>
  34340.  (<i>This might not be the case when you <a href="lib_p_r.htm#poke">poke</a>
  34341.  directly into memory, or call routines written in C or machine code.</i>)
  34342. </dl>
  34343.  
  34344. <p>
  34345.  Euphoria's method of defining types is simpler than what you will find
  34346.  in other languages, yet Euphoria provides the programmer with
  34347.  <font color="#CC0099"><_ba><i>greater</i></_ba></font> flexibility in
  34348.  defining the legal values for a type of data. Any algorithm
  34349.  can be used to include or exclude values. You can even declare a variable
  34350.  to be of type <font color="#993333"><_bq>object</_bq></font> which
  34351.  will allow it to take on <font color="#CC0099"><_ba><i>any</i></_ba></font>
  34352.  value. Routines can
  34353.  be written to work with very specific types, or very general types.
  34354.  
  34355. <p>
  34356.  For small programs, there is little advantage to defining new types, and
  34357.  beginners may wish to stick with the four
  34358.  <a href="refman_2.htm#43">predefined types</a>, or even
  34359.  declare all variables as <font color="#993333"><_bq>object</_bq></font>.
  34360.  
  34361. <p>
  34362.  For larger programs, strict type definitions can greatly aid the process
  34363.  of debugging.  Logic errors are caught close to their source and are not
  34364.  allowed to propagate in subtle ways through the rest of the program.
  34365.  Furthermore, it is much easier to reason about the misbehavior of a
  34366.  section of code when you are guaranteed that the variables involved
  34367.  always had a legal value, if not the desired value.
  34368.  
  34369. <p>
  34370.  Types also provide meaningful, machine-checkable documentation about your
  34371.  program, making it easier for you or others to understand your code at a
  34372.  later date. Combined with the
  34373.  <a href="refman_2.htm#21">subscript checking</a>, uninitialized variable
  34374.  checking, and other checking that is always present, strict run-time type
  34375.  checking makes debugging much easier in Euphoria than in most other
  34376.  languages. It also increases the reliability of the final program since
  34377.  many latent bugs that would have survived the testing phase in other
  34378.  languages will have been caught by Euphoria.
  34379.  
  34380. <dl>
  34381. <dt>
  34382. <b><font color="#006633"><_sul>Anecdote 1:</_sul></font></b>
  34383. <dd>
  34384.  In porting a large C program to Euphoria, a number
  34385.  of latent bugs were discovered. Although this C program was believed to be
  34386.  totally "correct", we found: a situation where an uninitialized variable
  34387.  was being read; a place where element number "-1" of an array was routinely
  34388.  written and read; and a situation where something was written just off the
  34389.  screen. These problems resulted in errors that weren't easily visible to a
  34390.  casual observer, so they had survived testing of the C code.
  34391.  
  34392. <p>
  34393. <dt>
  34394. <b><font color="#006633"><_sul>Anecdote 2:</_sul></font></b>
  34395. <dd>
  34396.  The Quick Sort algorithm presented on page 117 of <i>Writing Efficient
  34397.  Programs</i> by Jon Bentley has a subscript error! The algorithm will
  34398.  sometimes read the element just <i>before</i> the beginning of the array
  34399.  to be sorted, and will sometimes read the element just <i>after</i>
  34400.  the end of the array.
  34401.  Whatever garbage is read, the algorithm will still work - this is probably
  34402.  why the bug was never caught. But what if there isn't any (virtual) memory
  34403.  just before or just after the array? Bentley later modifies the algorithm
  34404.  such that this bug goes away -- but he presented this version as being
  34405.  correct. <b><i><font color="#006633">Even the experts need subscript
  34406.  checking!</font></i></b>
  34407.  
  34408. <p>
  34409. <dt>
  34410. <b><font color="#006633"><_sul>Performance Note:</_sul></font></b>
  34411.  
  34412. <dd>
  34413.  When typical user-defined types are used extensively, type
  34414.  checking adds only 20 to 40 percent to execution time. Leave it on unless
  34415.  you really need the extra speed. You might also consider turning it off for
  34416.  just a few heavily-executed routines.
  34417.  <a href="refman_3.htm#2">Profiling</a> can help with this decision.
  34418.  
  34419. </dl>
  34420.  
  34421. <hr>
  34422.  
  34423. <a name=5></a>
  34424. <font color="#FF0099" size=+1>
  34425. <br>
  34426.  
  34427. <_dul>2.5 Statements</_dul>
  34428.  
  34429. </font>
  34430. <p>
  34431.  
  34432.  The following kinds of executable statements are available:
  34433. <ul>
  34434. <li>
  34435.         <a href="refman_2.htm#assign">assignment statement</a>
  34436. <li>
  34437.         <a href="refman_2.htm#proc">procedure call</a>
  34438. <li>
  34439.         <a href="refman_2.htm#if">if statement</a>
  34440. <li>
  34441.         <a href="refman_2.htm#while">while statement</a>
  34442. <li>
  34443.         <a href="refman_2.htm#for">for statement</a>
  34444. <li>
  34445.         <a href="refman_2.htm#return">return statement</a>
  34446. <li>
  34447.         <a href="refman_2.htm#exit">exit statement</a>
  34448. </ul>
  34449.  
  34450. <p>
  34451.  Semicolons are not used in Euphoria, but you are free to put as many
  34452.  statements as you like on one line, or to split a single statement across
  34453.  many lines. You may not split a statement in the middle of an identifier,
  34454.  string, number or keyword.
  34455.  
  34456. <p>
  34457. <a name=assign></a>
  34458. <font color="#FF0099" size=+1>
  34459. <br>
  34460.  
  34461. <_sul>2.5.1 assignment statement</_sul>
  34462.  
  34463. </font>
  34464. <p>
  34465.  
  34466.  An <font color="#993333"><b>assignment statement</b></font> assigns
  34467.  the value of an expression to a simple
  34468.  variable, or to a subscript or slice of a variable. e.g.
  34469.  
  34470. <_eucode>
  34471.         x = a + b
  34472.  
  34473.         y[i] = y[i] + 1
  34474.  
  34475.         y[i..j] = {1, 2, 3}
  34476. </_eucode>
  34477.  
  34478. <p>
  34479.  The previous value of the variable, or element(s) of the subscripted or
  34480.  sliced variable are discarded.  For example, suppose x was a 1000-element
  34481.  sequence that we had initialized with:
  34482.  
  34483. <_eucode>
  34484.         object x
  34485.  
  34486.         x = repeat(0, 1000)  -- a sequence of 1000 zeros
  34487. </_eucode>
  34488.  
  34489.  and then later we assigned an atom to x with:
  34490.  
  34491. <_eucode>
  34492.         x = 7
  34493. </_eucode>
  34494.  
  34495.  This is perfectly legal since x is declared as an
  34496.  <font color="#993333"><b>object</b></font>. The previous value
  34497.  of x, namely the 1000-element sequence, would simply disappear. Actually,
  34498.  the space consumed by the 1000-element sequence will be automatically
  34499.  recycled due to Euphoria's dynamic storage allocation.
  34500.  
  34501. <p>
  34502.  Note that the equals symbol '=' is used for both assignment and for
  34503.  <a href="refman_2.htm#23">equality testing</a>.
  34504.  There is never any confusion because an assignment in Euphoria is
  34505.  a statement only, it can't be used as an expression (as in C).
  34506.  
  34507. <p>
  34508. <a name=assignop></a>
  34509. <font color="#CC3366" size=+1>
  34510. <br>
  34511.  
  34512. <_sul>Assignment with Operator</_sul>
  34513.  
  34514. </font>
  34515. <p>
  34516.  
  34517.  Euphoria also provides some additional forms of the assignment statement.
  34518.  
  34519. <p> To save typing, and to make your code a bit neater, you can combine
  34520.  assignment with one of the operators:<br>
  34521.        <font color="#993333"><b>+   -  
  34522.                                 /   *   &</b></font>
  34523.  
  34524. <p> For example, instead of saying:
  34525.  
  34526. <_eucode>
  34527.       mylongvarname = mylongvarname + 1
  34528. </_eucode>
  34529. You can say:
  34530. <_eucode>
  34531.       mylongvarname += 1
  34532. </_eucode>
  34533.  
  34534. Instead of saying:
  34535. <_eucode>
  34536.       galaxy[q_row][q_col][q_size] = galaxy[q_row][q_col][q_size] * 10
  34537. </_eucode>
  34538. You can say:
  34539. <_eucode>
  34540.       galaxy[q_row][q_col][q_size] *= 10
  34541. </_eucode>
  34542. and instead of saying:
  34543. <_eucode>
  34544.       accounts[start..finish] = accounts[start..finish] / 10
  34545. </_eucode>
  34546. You can say:
  34547. <_eucode>
  34548.       accounts[start..finish] /= 10
  34549. </_eucode>
  34550.  
  34551. <p>
  34552. In general, whenever you have an assignment of the form:
  34553. <pre>
  34554.       <b><i>left-hand-side = left-hand-side op expression</i></b>
  34555. </pre>
  34556. You can say:
  34557. <pre>
  34558.       <b><i>left-hand-side op= expression</i></b>
  34559. </pre>
  34560. where <b><i>op</i></b> is one of:   
  34561.   <font color="#993333"><b> +   -   *   /   &</b></font>
  34562. <p>
  34563. When the left-hand-side contains multiple subscripts/slices, the
  34564. <font color="#993333"><_bq><i>op=</i></_bq></font>
  34565. form will usually execute faster than the longer form. When you get used
  34566. to it, you may find the <font color="#993333"><_bq><i>op=</i></_bq></font>
  34567. form to be slightly more readable than the long form, since you don't
  34568. have to visually compare the left-hand-side against the copy of itself
  34569. on the right side.
  34570.  
  34571. <p>
  34572. <a name=proc></a>
  34573. <font color="#FF0099" size=+1>
  34574. <br>
  34575.  
  34576. <_sul>2.5.2 procedure call</_sul>
  34577.  
  34578. </font>
  34579. <p>
  34580.  A <font color="#993333"><b>procedure call</b></font> starts execution
  34581.  of a procedure, passing it an optional list of argument values. e.g.
  34582.  
  34583. <_eucode>
  34584.         plot(x, 23)
  34585. </_eucode>
  34586.  
  34587. <a name=if></a>
  34588. <font color="#FF0099" size=+1>
  34589. <br>
  34590.  
  34591. <_sul>2.5.3 if statement</_sul>
  34592.  
  34593. </font>
  34594. <p>
  34595.  An <font color="#993333"><b>if statement</b></font> tests a condition
  34596.  to see if it is 0 (false) or non-zero (true) and then executes the
  34597.  appropriate series of statements. There may
  34598.  be optional <font color="#993333"><b>elsif</b></font> and
  34599.  <font color="#993333"><b>else</b></font> clauses. e.g.
  34600.  
  34601. <_eucode>
  34602.         if a < b then
  34603.             x = 1
  34604.         end if
  34605.  
  34606.  
  34607.         if a = 9 and find(0, s) then
  34608.             x = 4
  34609.             y = 5
  34610.         else
  34611.             z = 8
  34612.         end if
  34613.  
  34614.  
  34615.         if char = 'a' then
  34616.             x = 1
  34617.         elsif char = 'b' or char = 'B' then
  34618.             x = 2
  34619.         elsif char = 'c' then
  34620.             x = 3
  34621.         else
  34622.             x = -1
  34623.         end if
  34624. </_eucode>
  34625.  
  34626. <p>
  34627.  Notice that <font color="#993333"><_bq>elsif</_bq></font> is a contraction
  34628.  of <font color="#993333"><_bq>else if</_bq></font>, but it's cleaner because
  34629.  it doesn't require an <font color="#993333"><_bq>end if</_bq></font> to go
  34630.  with it. There is just one <font color="#993333"><_bq>end if</_bq></font> for
  34631.  the entire <font color="#993333"><b>if</b></font> statement, even when
  34632.  there are many <b><font color="#993333">elsif's</font></b> contained in it.
  34633. <p>
  34634. The <font color="#993333"><b>if</b></font> and
  34635. <font color="#993333"><b>elsif</b></font> conditions are tested using
  34636. <a href="refman_2.htm#shortcir">short-circuit evaluation</a>. 
  34637. <p>
  34638. <a name=while></a>
  34639. <font color="#FF0099" size=+1>
  34640. <br>
  34641.  
  34642. <_sul>2.5.4 while statement</_sul>
  34643.  
  34644. </font>
  34645. <p>
  34646.  A <font color="#993333"><b>while statement</b></font> tests a condition
  34647.  to see if it is non-zero (true), and while it is true a loop is executed. e.g.
  34648.  
  34649. <_eucode>
  34650.         while x > 0 do
  34651.             a = a * 2
  34652.             x = x - 1
  34653.         end while
  34654. </_eucode>
  34655.  
  34656. <a name=shortcir></a>
  34657. <font color="#CC3366" size=+1>
  34658. <br>
  34659.  
  34660. <_sul>Short-Circuit Evaluation</_sul>
  34661.  
  34662. </font>
  34663. <p>
  34664.  When the condition tested by <font color="#993333"><_bq>if</_bq></font>,
  34665.  <font color="#993333"><_bq>elsif</_bq></font>, or
  34666.  <font color="#993333"><_bq>while</_bq></font> contains
  34667.  <font color="#993333"><_bq>and</_bq></font> or
  34668.  <font color="#993333"><_bq>or</_bq></font> operators,
  34669.  <font color="#993333"><_ba><i>short-circuit</i></_ba></font> evaluation
  34670.  will be used.
  34671.  For example,
  34672.  
  34673.  <_eucode>
  34674.         if a < 0 and b > 0 then ...
  34675.  </_eucode>
  34676.  
  34677.  If a < 0 is false, then Euphoria will not bother to test if b is greater
  34678.  than 0. It will assume that the overall result is false. Similarly,
  34679.  
  34680.  <_eucode>
  34681.         if a < 0 or b > 0 then ...
  34682.  </_eucode>
  34683.  
  34684.  if a < 0 is true, then Euphoria will immediately decide that the result true,
  34685.  without testing the value of b.
  34686.  
  34687. <p>
  34688.  In general, whenever we have a condition of the form:
  34689. <_eucode>
  34690.         A and B
  34691. </_eucode>
  34692.  where A and B can be any two expressions,
  34693.  Euphoria will take a short-cut when A is false and immediately
  34694.  make the overall result false, without even looking at expression B.
  34695.  
  34696. <p>
  34697.  Similarly, with:
  34698. <_eucode>
  34699.         A or B
  34700. </_eucode>
  34701.  when A is true, Euphoria will skip the evaluation of expression B,
  34702.  and declare the result to be true.
  34703.  
  34704. <p>
  34705.  If the expression B contains a call to a function, and that function has
  34706.  possible <b>side-effects</b>, i.e. it might do more than just return a value,
  34707.  you will get a compile-time warning. Older versions (pre-2.1) of Euphoria
  34708.  did not use <font color="#993333"><b>short-circuit</b></font> evaluation,
  34709.  and it's possible that some old code will no longer work correctly,
  34710.  although a search of the Euphoria archives did not turn up any programs
  34711.  that depend on side-effects in this way.
  34712.  
  34713. <p>
  34714.  The expression, B, could contain something that would normally cause
  34715.  a run-time error. If Euphoria skips the evaluation of B, the error will not
  34716.  be discovered. For instance:
  34717.  
  34718.  <_eucode>
  34719.         if x != 0 and 1/x > 10 then  -- divide by zero error avoided
  34720.  
  34721.         while 1 or {1,2,3,4,5} do    -- illegal sequence result avoided
  34722.  </_eucode>
  34723.  
  34724.  B could even contain uninitialized variables, out-of-bounds subscripts etc.
  34725.  
  34726. <p>
  34727.  This may look like sloppy coding, but in fact it often allows you to
  34728.  write something in a simpler and more readable way. For instance:
  34729.  <_eucode>
  34730.         if atom(x) or length(x)=1 then
  34731.  </_eucode>
  34732.  
  34733.  Without short-circuiting, you would have a problem when x was an atom,
  34734.  since length is not defined for atoms. With short-circuiting, length(x)
  34735.  will only be checked when x is a sequence. Similarly:
  34736.  
  34737.  <_eucode>
  34738.         -- find 'a' or 'A' in s
  34739.         i = 1
  34740.         while i <= length(s) and s[i] != 'a' and s[i] != 'A' do
  34741.              i += 1
  34742.         end while
  34743.  </_eucode>
  34744.  
  34745.  In this loop the variable i might eventually become
  34746.  greater than length(s). Without short-circuit evaluation, a subscript
  34747.  out-of-bounds error will occur when s[i] is evaluated on the final
  34748.  iteration. With short-circuiting, the loop will terminate immediately when
  34749.  i <= length(s) becomes false. Euphoria will not evaluate s[i] != 'a'
  34750.  and will not evaluate s[i] != 'A'. No subscript error will occur.
  34751.  
  34752. <p>
  34753.  <font color="#993333"><b>Short-circuit</b></font> evaluation of
  34754.  <font color="#993333"><_bq>and</_bq></font>
  34755.  and <font color="#993333"><_bq>or</_bq></font> takes place for
  34756.  <font color="#993333"><_bq>if</_bq></font>,
  34757.  <font color="#993333"><_bq>elsif</_bq></font> and
  34758.  <font color="#993333"><_bq>while</_bq></font> conditions only.
  34759.  It is not used in other contexts. For example, the assignment statement:
  34760.  
  34761.  <_eucode>
  34762.         x = 1 or {1,2,3,4,5}  -- x should be set to {1,1,1,1,1}
  34763.  </_eucode>
  34764.  
  34765.  If short-circuiting were used here, we would set x to 1, and not even
  34766.  look at {1,2,3,4,5}. This would be wrong. Short-circuiting can be used
  34767.  in if/elsif/while conditions because we only care if the result is true
  34768.  or false, and conditions are required to produce an atom as a result.
  34769.  
  34770. <p>
  34771. <a name=for></a>
  34772. <font color="#FF0099" size=+1>
  34773. <br>
  34774.  
  34775. <_sul>2.5.5 for statement</_sul>
  34776.  
  34777. </font>
  34778. <p>
  34779.  A <font color="#993333"><b>for statement</b></font> sets up a special
  34780.  loop with a controlling <font color="#993333"><b>loop variable</b></font>
  34781.  that runs from an initial value up or down to some final value. e.g.
  34782.  
  34783. <_eucode>
  34784.         for i = 1 to 10 do
  34785.             ? i   -- ? is a short form for print()
  34786.         end for
  34787.  
  34788.         -- fractional numbers allowed too
  34789.         for i = 10.0 to 20.5 by 0.3 do
  34790.             for j = 20 to 10 by -2 do    -- counting down
  34791.                 ? {i, j}
  34792.             end for
  34793.         end for
  34794. </_eucode>
  34795.  
  34796. <p>
  34797.  The <font color="#993333"><b>loop variable</b></font> is
  34798.  declared automatically and exists until the end of the
  34799.  loop. Outside of the loop the variable has no value and is not even declared.
  34800.  If you need its final value, copy it into another variable before leaving
  34801.  the loop. The compiler will not allow any assignments to a loop variable. The
  34802.  initial value, loop limit and increment must all be atoms. If no increment
  34803.  is specified then +1 is assumed. The limit and increment values are
  34804.  established when the loop is entered, and are not affected by anything that
  34805.  happens during the execution of the loop. See also the
  34806.  <a href="refman_2.htm#loop_scope">scope of the loop variable in 2.4.2
  34807.  Scope</a>.
  34808.  
  34809. <p>
  34810. <a name=return></a>
  34811. <font color="#FF0099" size=+1>
  34812. <br>
  34813.  
  34814. <_sul>2.5.6 return statement</_sul>
  34815.  
  34816. </font>
  34817. <p>
  34818.  A <font color="#993333"><b>return statement</b></font> returns from a
  34819.  subroutine. If the subroutine is a function
  34820.  or type then a value must also be returned. e.g.
  34821.  
  34822. <_eucode>
  34823.         return
  34824.  
  34825.         return {50, "FRED", {}}
  34826. </_eucode>
  34827.  
  34828. <a name=exit></a>
  34829. <font color="#FF0099" size=+1>
  34830. <br>
  34831.  
  34832. <_sul>2.5.7 exit statement</_sul>
  34833.  
  34834. </font>
  34835. <p>
  34836.  An <font color="#993333"><b>exit statement</b></font> may appear inside a
  34837.  <a href="refman_2.htm#while">while-loop</a> or a
  34838.  <a href="refman_2.htm#for">for-loop</a>. It causes immediate termination of
  34839.  the loop, with control passing to the first statement after the loop. e.g.
  34840.  
  34841. <_eucode>
  34842.         for i = 1 to 100 do
  34843.             if a[i] = x then
  34844.                 location = i
  34845.                 exit
  34846.             end if
  34847.         end for
  34848. </_eucode>
  34849.  
  34850. <p>
  34851.  It is also quite common to see something like this:
  34852.  
  34853. <_eucode>
  34854.         constant TRUE = 1
  34855.  
  34856.         while TRUE do
  34857.             ...
  34858.             if some_condition then
  34859.                 exit
  34860.             end if
  34861.             ...
  34862.         end while
  34863. </_eucode>
  34864.  
  34865.  i.e. an "infinite" while-loop that actually terminates via an
  34866.  <font color="#993333"><b>exit statement</b></font> at some arbitrary
  34867.  point in the body of the loop.
  34868.  
  34869. <p>
  34870.  With <font color="#993333"><b>ex.exe</b></font>, if you happen to create
  34871.  a real infinite loop, with no
  34872.  input/output taking place, there is no easy way to stop it. You will have to
  34873.  type Control-Alt-Delete to either reboot, or (under Windows) terminate your
  34874.  DOS prompt session. If the program had files open for writing, it would be
  34875.  advisable to run <b>scandisk</b> to check your file system integrity.
  34876.  Only when your program is waiting for keyboard input, will control-c abort
  34877.  the program (unless <a href="lib_a_b.htm#allow_break">allow_break(0)</a>
  34878.  was used).
  34879.  
  34880. <p>
  34881.  With <font color="#993333"><b>exw.exe</b></font> or 
  34882.       <font color="#993333"><b>exu</b></font>, control-c will
  34883.  always stop your program immediately.
  34884.  
  34885. <p>
  34886. <hr>
  34887.  
  34888. <a name=6></a>
  34889. <font color="#FF0099" size=+1>
  34890. <br>
  34891.  
  34892. <_dul>2.6 Special Top-Level Statements</_dul>
  34893.  
  34894. </font>
  34895. <p>
  34896.  
  34897.  Euphoria processes your <b>.ex</b> file in one pass, starting at the first
  34898.  line and proceeding through to the last line. When a procedure or function
  34899.  definition is encountered, the routine is checked for syntax and converted
  34900.  into an internal form, but no execution takes place. When a statement that
  34901.  is outside of any routine is encountered, it is checked for syntax,
  34902.  converted into an internal form and then immediately executed.
  34903.  A common practice is to immediately initialize a global variable, just
  34904.  after its declaration. If your <b>.ex</b> file contains only
  34905.  routine definitions, but no immediate execution statements, then nothing will
  34906.  happen when you try to run it (other than syntax checking). You need to have
  34907.  an immediate statement to call your main routine (see
  34908.  <a href="refman_1.htm#1">1.1 Example Program</a>).
  34909.  It is quite possible to have a <b>.ex</b> file with nothing but
  34910.  immediate statements, for example you might want to use Euphoria as a
  34911.  simple calculator, typing in just one
  34912.  <a href="lib_p_r.htm#print">print</a>
  34913.  (or <a href="lib_a_b.htm#?">?</a>) statement into a file, and
  34914.  then executing it. To give the user something to look at, the
  34915.  <font color="#5500FF"><b>Language War</b></font> demo program
  34916.  reads in and displays a file on the screen, before the rest of the
  34917.  program is compiled (on a 486 or higher this makes little difference as the
  34918.  compiler takes less than a second to finish compiling the entire program).
  34919.  
  34920. <p>
  34921.  As we have seen, you can use any Euphoria
  34922.  <a href="refman_2.htm#5">statement</a>, including
  34923.  <a href="refman_2.htm#for">for-loops</a>,
  34924.  <a href="refman_2.htm#while">while-loops</a>,
  34925.  <a href="refman_2.htm#if">if</a> statements etc. (but not
  34926.  <a href="refman_2.htm#return">return</a>), at the top level i.e.
  34927.  <_ba><i>outside</i></_ba> of any
  34928.  <a href="refman_2.htm#412">function</a> or
  34929.  <a href="refman_2.htm#411">procedure</a>.
  34930.  In addition, the following special statements may
  34931.  <font color="#CC0099"><_ba><i>only</i></_ba></font> appear at the top level:
  34932. <ul>
  34933. <li> include
  34934. <li> with / without
  34935. </ul>
  34936.  
  34937. <p>
  34938. <a name=61></a>
  34939. <font color="#FF0099" size=+1>
  34940. <br>
  34941.  
  34942. <_sul>2.6.1 include</_sul>
  34943.  
  34944. </font>
  34945. <p>
  34946. When you write a large program it is often helpful
  34947. to break it up into logically separate files, by using
  34948. <font color="#993333"><b>include statements</b></font>.
  34949. Sometimes you will want to reuse some code that you have previously
  34950. written, or that someone else has written. Rather than copy this code into
  34951. your main program, you can use an
  34952. <font color="#993333"><b>include statement</b></font> to refer to the file
  34953. containing the code. An include statement looks like:
  34954.  
  34955. <dl>
  34956. <dt>
  34957.  <font color="#993333"><b>include</b></font> <b><i>filename</i></b>
  34958.  
  34959. <dd>
  34960.                    This reads in (compiles) a Euphoria source file.
  34961.  
  34962. <p>
  34963.                    Any <a href="refman_2.htm#scope">global symbols</a>
  34964.                    that have already been defined will
  34965.                    be visible in the included file.
  34966.  
  34967. <p>
  34968.                    <b><font color="#006633">N.B.</font></b> Only those
  34969.                    symbols defined as
  34970.                    <a href="refman_2.htm#scope"><_bq>global</_bq></a>
  34971.                    in the included file will be visible (accessible) in the
  34972.                    remainder of the program.
  34973.  
  34974. <p>
  34975.                    If an absolute <i>filename</i> is given,
  34976.                    Euphoria will use it. When
  34977.                    a relative <i>filename</i> is given, Euphoria will
  34978.                    first look for
  34979.                    it in the same directory as the main file given on
  34980.                    the <font color="#993333"><b>ex</b></font>
  34981.                    (or <font color="#993333"><b>exw</b></font> or
  34982.                    <font color="#993333"><b>exu</b></font>)
  34983.                    <a href="refman_1.htm#3">command-line</a>.
  34984.                    If it's not there, it will look in
  34985.                    <font color="#5500FF"><b>euphoria\include</b></font>.
  34986.                    This directory contains the standard
  34987.                    Euphoria include files. The environment variable EUDIR tells
  34988.                    <font color="#993333"><b>ex.exe/exw.exe/exu</b></font>
  34989.                    where to find your
  34990.                    <font color="#993333"><b>euphoria</b></font> directory.
  34991.  
  34992. <p>
  34993.                    An included file can include other files. In fact, you can
  34994.                    "nest" included files up to 10 levels deep.
  34995.  
  34996. <p>                Include file names typically end in <b>.e</b>, or sometimes
  34997.                    <b>.ew</b> or <b>.eu</b> (when they are intended for use 
  34998.                    with Windows or Linux).
  34999.                    This is just a convention. It is not required.
  35000.  
  35001. <p>
  35002.                    An include statement will be quietly ignored if a file with
  35003.                    the same name has already been included, directly or
  35004.                    indirectly.
  35005.  
  35006. <p>
  35007.                    An include statement must be written on a line by itself.
  35008.                    Only a comment can appear after it on the same line.
  35009. </dl>
  35010.  
  35011. <a name=62></a>
  35012. <font color="#FF0099" size=+1>
  35013. <br>
  35014.  
  35015. <_sul>2.6.2 with / without</_sul>
  35016.  
  35017. </font>
  35018. <p>
  35019.     These special statements affect the way that Euphoria
  35020.     translates your program into internal form. They are not meant to
  35021.     change the logic of your program, but they may affect the diagnostic
  35022.     information that you get from running your program.
  35023.     See <a href="refman_3.htm">3. Debugging and Profiling</a> for more
  35024.     information.
  35025.  
  35026. <dl>
  35027. <dt>
  35028.  <font color="#993333"><b>with</b></font>
  35029.  
  35030. <dd>
  35031.        This turns <b>on</b> one of the options:
  35032.        <b>
  35033.        <a href="refman_3.htm#2"><font color="#993333">profile</font></a>,
  35034.        <a href="refman_3.htm#2"><font color="#993333">profile_time</font></a>,
  35035.        <a href="refman_3.htm#trace"><font color="#993333">trace</font></a>,
  35036.        <font color="#993333">warning</font></b> or
  35037.        <a href="refman_2.htm#typechk"><font color="#993333"><b>type_check</b>
  35038.        </font></a>.
  35039.         Options <font color="#993333"><b>warning</b></font> and
  35040.         <font color="#993333"><b>type_check</b></font> are
  35041.         initially on, while
  35042.         <font color="#993333"><b>profile</b></font>,
  35043.         <font color="#993333"><b>profile_time</b></font> and
  35044.         <font color="#993333"><b>trace</b></font> are initially off.
  35045.         <p>
  35046.         Any warnings that are issued will appear on your screen after your
  35047.         program has finished execution. Warnings indicate very minor problems.
  35048.         A warning will never stop your program from executing.
  35049. <p>
  35050. <dt>
  35051.  <font color="#993333"><b>without</b></font>
  35052.  
  35053. <dd>
  35054.     This turns <b>off</b> one of the above options.
  35055.  
  35056. </dl>
  35057.  
  35058. <p>
  35059. There is also a special <font color="#993333"><b>with</b></font> option
  35060. where a code number appears after <font color="#993333"><b>with</b></font>.
  35061. RDS uses this code to make a file exempt from adding to the
  35062. statement count in the Public Domain Edition of Euphoria.
  35063.  
  35064. <p>
  35065. You can select any combination of settings, and you can change the settings,
  35066. but the changes must occur
  35067. <_ba><i>between</i></_ba> subroutines, not
  35068. within a subroutine. The only exception is that you can only turn on one
  35069. type of profiling for a given run of your program.
  35070.  
  35071. <p>
  35072. An <b>included file</b> inherits the
  35073. <font color="#993333"><b>with/without</b></font> settings in
  35074. effect at the point where it is included.
  35075. An included file can change these settings, but they will revert back
  35076. to their original state at the end of the included file.
  35077. For instance, an included file might turn off
  35078. warnings for itself and (initially) for any files that it includes,
  35079. but this will not turn off warnings for the main file.
  35080.  
  35081. <_continue
  35082.   href="refman_3.htm"
  35083.   name="3. Debugging and Profiling"
  35084. >
  35085.  
  35086. </_width>
  35087. </body>
  35088. </html>
  35089. REFMAN_3.HTX
  35090. 18569
  35091. <_init_comment>
  35092. <html>
  35093. <head><title>Euphoria v2.2 Reference Manual Part I - Section 3 </title>
  35094. </head>
  35095. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  35096. <_width>
  35097. <_center><font color="#FF0099" size=+2>
  35098. <br>
  35099.                        3. Debugging and Profiling
  35100. </font></_center>
  35101. <p>
  35102. <a name=1></a>
  35103. <font color="#FF0099" size=+1>
  35104. <br>
  35105.  
  35106. <_dul>3.1 Debugging</_dul>
  35107.  
  35108. </font>
  35109. <p>
  35110.  
  35111.  Debugging in Euphoria is much easier than in most other programming languages.
  35112.  The extensive run-time checking provided at all times by Euphoria
  35113.  automatically catches many bugs that in other languages might take hours of
  35114.  your time to track down. When Euphoria catches an error, you will always get
  35115.  a brief report on your screen, and a detailed report in a file called
  35116.  <font color="#993333"><_bq>ex.err</_bq></font>. These reports always
  35117.  include a full English description of what happened, along with a
  35118.  call-stack traceback. The file <font color="#993333"><b>ex.err</b></font>
  35119.  will also have
  35120.  a dump of all variable values, and optionally a list of the most recently
  35121.  executed statements. For extremely large sequences, only a partial dump is
  35122.  shown. If <font color="#993333"><b>ex.err</b></font> is not
  35123.  convenient, you can choose another file name,
  35124.  anywhere on your system, by calling 
  35125.  <a href="lib_c_d.htm#crash_file">crash_file</a>().
  35126.  
  35127. <p>
  35128.  In addition, you are able to create
  35129.  <a href="refman_2.htm#type">user-defined types</a> that precisely
  35130.  determine the set of legal values for each of your variables. An error report
  35131.  will occur the moment that one of your variables is assigned an illegal value.
  35132.  
  35133. <p>
  35134.  Sometimes a program will misbehave without failing any run-time checks. In
  35135.  any programming language it may be a good idea to simply study the source
  35136.  code and rethink the algorithm that you have coded. It may also be useful
  35137.  to insert print statements at strategic locations in order to monitor the
  35138.  internal logic of the program. This approach is particularly convenient in
  35139.  an interpreted language like Euphoria since you can simply edit the source
  35140.  and rerun the program without waiting for a re-compile/re-link.
  35141.  
  35142. <p>
  35143.  <a name=trace></a>
  35144.  Euphoria provides you with additional powerful tools for debugging. You
  35145.  can <font color="#993333"><b><i>trace</i></b></font>
  35146.  the execution of your program source code on one screen while
  35147.  you witness the output of your program on another.
  35148.  <b><a href="refman_2.htm#62"><font color="#993333">with trace</font></a> /
  35149.  <a href="refman_2.htm#62"><font color="#993333">without trace</font></a></b>
  35150.  special statements select the
  35151.  parts in your program that are available for tracing. Often you
  35152.  will simply insert a <font color="#993333"><_bq>with trace</_bq></font>
  35153.  statement at the very beginning of
  35154.  your source code to make it all traceable. Sometimes it is better to place
  35155.  the first <font color="#993333"><_bq>with trace</_bq></font>
  35156.  after all of your <a href="refman_2.htm#type">user-defined types</a>, so
  35157.  you don't trace into these routines after each assignment to a variable.
  35158.  At other times, you may know exactly which routine or routines you are
  35159.  interested in tracing, and you will want to select only these ones. Of
  35160.  course, once you are in the trace window you can interactively skip over
  35161.  the execution of any routine by pressing down-arrow on the keyboard rather
  35162.  than Enter.
  35163.  
  35164. <p>
  35165.  Only traceable lines can appear in <font color="#993333"><b>ex.err</b></font>
  35166.  as "Traced lines leading up to the failure" should a run-time error occur.
  35167.  If you want this information and didn't get it, you should insert a
  35168.  <font color="#993333"><_bq>with trace</_bq></font>
  35169.  and then rerun your program.
  35170.  Execution will be a bit slower when lines compiled
  35171.  <font color="#993333"><_bq>with trace</_bq></font> are executed.
  35172.  
  35173. <p>
  35174.  After you have predetermined the lines that are traceable, your program must
  35175.  then dynamically cause the trace facility to be activated by executing a
  35176.  <a href="lib_s_t.htm#trace">trace(1)</a> statement.
  35177.  Again, you could simply say:
  35178.  
  35179. <_eucode>
  35180.         with trace
  35181.         trace(1)        -- or trace(2) if you prefer a mono display
  35182. </_eucode>
  35183.  
  35184.  at the top of your program, so you can start tracing from the beginning of
  35185.  execution. More commonly, you will want to trigger tracing when a certain
  35186.  routine is entered, or when some condition arises. e.g.
  35187.  
  35188. <_eucode>
  35189.         if x < 0 then
  35190.             trace(1)
  35191.         end if
  35192. </_eucode>
  35193.  
  35194. <p>
  35195.  You can turn off tracing by executing a
  35196.  <a href="lib_s_t.htm#trace">trace(0)</a> statement. You can also
  35197.  turn it off interactively by typing 'q' to quit tracing. Remember that
  35198.  <font color="#993333"><_bq>with trace</_bq></font> must appear
  35199.  <b><i>outside</i></b> of any routine, whereas
  35200.  trace(1) and trace(0) can appear
  35201.  <b><i>inside</i></b> a routine <b><i>or outside</i></b>.
  35202.  
  35203. <p>
  35204.  You might want to turn on tracing from within a
  35205.  <a href="refman_2.htm#413">type</a>. Suppose you run your
  35206.  program and it fails, with the <font color="#993333"><b>ex.err</b></font>
  35207.  file showing that one of your variables has been set to a strange,
  35208.  although not illegal value, and you wonder how it could have happened. Simply
  35209.  <a href="refman_2.htm#type">create a type</a> for that variable
  35210.  that executes <font color="#006699">trace(1)</font> if the value being
  35211.  assigned to the variable is the strange one that you are interested in.
  35212.  e.g.
  35213.  
  35214. <_eucode>
  35215.         type positive_int(integer x)
  35216.             if x = 99 then
  35217.                 trace(1) -- how can this be???
  35218.                 return 1 -- keep going
  35219.             else
  35220.                 return x > 0
  35221.             end if
  35222.         end type
  35223. </_eucode>
  35224.  
  35225. <p>
  35226.  When positive_int() returns,
  35227.  you will see the exact statement that caused your variable to be set to the
  35228.  strange value, and you will be able to check the values of other variables.
  35229.  You will also be able to check the output screen to
  35230.  see what has happened up to this precise moment. If you define
  35231.  positive_int() so it returns 0 for the strange value (99) instead of 1, you
  35232.  can force a diagnostic dump into <font color="#993333"><b>ex.err</b></font>.
  35233.  
  35234. <p>
  35235.  
  35236. <a name=11></a>
  35237. <font color="#FF0099" size=+1>
  35238. <br>
  35239.  
  35240. <_sul>3.1.1 The Trace Screen</_sul>
  35241.  
  35242. </font>
  35243. <p>
  35244.  
  35245.  When a <a href="lib_s_t.htm#trace">trace(1)</a> statement is executed,
  35246.  your main output screen is saved and
  35247.  a <font color="#993333"><b>trace screen</b></font> appears.
  35248.  It shows a view of your program with the statement
  35249.  that will be executed next highlighted, and several statements before and
  35250.  after showing as well. Several lines at the bottom of the screen are
  35251.  reserved for displaying variable names and values. The top line shows the
  35252.  commands that you can enter at this point:
  35253.  
  35254. <p>
  35255. <table border=0 cellspacing=2 cellpadding=2>
  35256.  
  35257. <_3clist
  35258.   name="<font color=\"#993333\">F1</font>"
  35259.   description="display main output screen - take a look at your program's
  35260.      output so far"
  35261. >
  35262.  
  35263. <_3clist
  35264.   name="<font color=\"#993333\">F2</font>"
  35265.   description="redisplay trace screen. Press this key while viewing the
  35266.      main output screen to return to the trace display."
  35267. >
  35268.  
  35269. <_3clist
  35270.   name="<font color=\"#993333\">Enter</font>"
  35271.   description="execute the currently-highlighted statement only"
  35272. >
  35273.  
  35274. <_3clist
  35275.   name="<font color=\"#993333\">down-arrow</font>"
  35276.   description="continue execution and break when any statement coming after
  35277.    this one in the source listing is about to be executed. This lets you skip
  35278.    over subroutine calls. It also lets you stop on the first statement
  35279.    following the end of a <a href=\"refman_2.htm#for\">for-loop</a> or
  35280.    <a href=\"refman_2.htm#while\">while-loop</a> without having to witness
  35281.    all iterations of the loop."
  35282. >
  35283.  
  35284. <_3clist
  35285.   name="<font color=\"#993333\">?</font>"
  35286.   description="display the value of a variable. Many variables are displayed
  35287.      automatically as they are assigned a value, but sometimes you will have
  35288.      to explicitly ask for one that is not on display. After hitting
  35289.      <font color=\"#993333\"><b>?</b></font>
  35290.      you will be prompted for the name of the variable. Variables that are
  35291.      not defined at this point cannot be shown. Variables that have not yet
  35292.      been initialized will have \"< NO VALUE >\" beside their name. Only
  35293.      variables, not general expressions, can be displayed."
  35294. >
  35295.  
  35296. <_3clist
  35297.   name="<font color=\"#993333\">q</font>"
  35298.   description="quit tracing and resume normal execution. Tracing will
  35299.      start again when the next trace(1) is executed."
  35300. >
  35301.  
  35302. <_3clist
  35303.   name="<font color=\"#993333\">Q</font>"
  35304.   description="quit tracing and let the program run freely to its normal
  35305.      completion. trace() statements will be ignored."
  35306. >
  35307.  
  35308. <_3clist
  35309.   name="<font color=\"#993333\">!</font>"
  35310.   description="this will abort execution of your program. A traceback
  35311.      and dump of variable values will go to
  35312.      <font color=\"#993333\"><b>ex.err</b></font>."
  35313. >
  35314.  
  35315. </table>
  35316.  
  35317. <p>
  35318.  As you trace your program, variable names and values appear automatically in
  35319.  the bottom portion of the screen. Whenever a variable is assigned-to, you will
  35320.  see its name and new value appear at the bottom. This value is always kept
  35321.  up-to-date. Private variables are automatically cleared from the screen
  35322.  when their routine returns. When the variable display area is full,
  35323.  least-recently referenced variables will be discarded to make room for
  35324.  new variables. The value of a long sequence will be cut off after 80
  35325.  characters.
  35326.  
  35327. <p>
  35328.  For your convenience, numbers that are in the range of printable ASCII
  35329.  characters (32-127) are displayed along with the ASCII character itself. The
  35330.  ASCII character will be in a different color (or in quotes in a mono display).
  35331.  This is done for all variables, since Euphoria does not know in general
  35332.  whether you are thinking of a number as an ASCII character or not. You will
  35333.  also see ASCII characters (in quotes) in
  35334.  <font color="#993333"><b>ex.err</b></font>. This can make for a rather
  35335.  "busy" display, but the ASCII information is often very useful.
  35336.  
  35337. <p>
  35338.  The trace screen adopts the same graphics mode as the main output screen.
  35339.  This makes flipping between them quicker and easier.
  35340.  
  35341. <p>
  35342.  When a traced program requests keyboard input, the main output screen will
  35343.  appear, to let you type your input as you normally would. This works fine for
  35344.  <a href="lib_e_g.htm#gets">gets()</a> (read one line) input.
  35345.  When <a href="lib_e_g.htm#get_key">get_key()</a> (quickly sample the
  35346.  keyboard) is
  35347.  called you will be given 8 seconds to type a character, otherwise it is
  35348.  assumed that there is no input for this call to get_key(). This allows you to
  35349.  test the case of input and also the case of no input for get_key().
  35350.  
  35351. <p>
  35352. <hr>
  35353.  
  35354. <a name=2></a>
  35355. <font color="#FF0099" size=+1>
  35356. <br>
  35357.  
  35358. <_dul>3.2 Profiling</_dul> (Complete Edition Only)
  35359.  
  35360. </font>
  35361. <p>
  35362.  
  35363.  If you specify <a href="refman_2.htm#62"><font color="#993333">
  35364.  <_bq>with profile</_bq></font></a> (DOS32, WIN32 or Linux), or
  35365.  <a href="refman_2.htm#62"><font color="#993333">
  35366.  <_bq>with profile_time</_bq></font></a>
  35367.  (DOS32 only) then a special listing of your program, called
  35368.  a <font color="#993333"><_bq><i>profile</i></_bq></font>,
  35369.  will be produced when your program finishes execution. This listing is
  35370.  written to the file <font color="#993333"><_bq>ex.pro</_bq></font> in
  35371.  the current directory.
  35372.  
  35373. <p>
  35374.  There are two types of profiling available:
  35375.  <font color="#993333"><b>execution-count profiling</b></font>,
  35376.  and <font color="#993333"><b>time profiling</b></font>.
  35377.  You get execution-count profiling when you specify
  35378.  <font color="#993333"><_bq>with profile</_bq></font>. You get time
  35379.  profiling when you specify
  35380.  <font color="#993333"><_bq>with profile_time</_bq></font>.
  35381.  You can't mix the two types of profiling in a single run of your program.
  35382.  You need to make two separate runs.
  35383.  
  35384. <p>
  35385.  We ran the <font color="#5500FF"><b>sieve.ex</b></font> benchmark program in
  35386.  <font color="#5500FF"><b>demo\bench</b></font> under both types of
  35387.  profiling. The results are in
  35388.  <font color="#5500FF"><b>sieve1.pro</b></font> (execution-count profiling)
  35389.  and <font color="#5500FF"><b>sieve2.pro</b></font> (time profiling).
  35390.  
  35391. <p>
  35392.  Execution-count profiling shows precisely how many times each statement
  35393.  in your program was executed. If the statement was never executed the
  35394.  count field will be blank.
  35395.  
  35396. <p>
  35397.  Time profiling (DOS32 only) shows an estimate of the total time spent
  35398.  executing each statement. This estimate is expressed as a percentage of the
  35399.  total time. If a statement was never sampled, the percentage field will be
  35400.  blank. If you see 0.00 it means the statement was sampled, but not enough
  35401.  times to get a score of 0.01.
  35402.  
  35403. <p>
  35404.  Only statements compiled <font color="#993333"><_bq>with profile</_bq></font>
  35405.  or <font color="#993333"><_bq>with profile_time</_bq></font> are shown in
  35406.  the listing. Normally you will specify either
  35407.  <font color="#993333"><_bq>with profile</_bq></font>
  35408.  or <font color="#993333"><_bq>with profile_time</_bq></font> at the top
  35409.  of your main <b>.ex</b> file, so you can get a complete listing.
  35410.  View this file with the Euphoria editor to see a color display.
  35411.  
  35412. <p>
  35413.  Profiling can help you in many ways:
  35414.  
  35415. <ul>
  35416. <li>
  35417.        it lets you see which statements are heavily executed,
  35418.        as a clue to speeding up your program
  35419.  
  35420. <li>
  35421.        it lets you verify that your program is actually working
  35422.        the way you intended
  35423.  
  35424. <li>
  35425.        it lets you see which sections of code were never tested
  35426.        - don't let your users be the first!
  35427. </ul>
  35428.  
  35429. <p>
  35430.  Sometimes you will want to focus on a particular action performed by your
  35431.  program. For example, in the
  35432.  <font color="#5500FF"><b>Language War</b></font> game, we found that the game
  35433.  in general was fast enough, but when a planet exploded, shooting 2500
  35434.  pixels off in all directions, the game slowed down. We wanted to speed
  35435.  up the explosion routine. We didn't care about the rest of the code. The
  35436.  solution was to call <a href="lib_p_r.htm#profile">profile(0)</a>
  35437.  at the beginning of Language War, just after
  35438.  <font color="#993333"><_bq>with profile_time</_bq></font>,
  35439.  to turn off profiling, and then to call
  35440.  <font color="#006699">profile(1)</font> at the beginning of the
  35441.  explosion routine and <font color="#006699">profile(0)</font>
  35442.  at the end of the routine. In this way
  35443.  we could run the game, creating numerous explosions, and logging a lot
  35444.  of samples, just for the explosion effect. If samples were charged against
  35445.  other lower-level routines, we knew that those samples occurred during
  35446.  an explosion. If we had simply profiled the whole program, the picture
  35447.  would not have been clear, as the lower-level routines would also
  35448.  have been used for moving ships, drawing phasors etc. profile() can help
  35449.  in the same way when you do execution-count profiling.
  35450.  
  35451. <p>
  35452.  
  35453. <a name=21></a>
  35454. <font color="#FF0099" size=+1>
  35455. <br>
  35456.  
  35457. <_sul>3.2.1 Some Further Notes on Time Profiling</_sul>
  35458.  
  35459. </font>
  35460. <p>
  35461.  
  35462.  With each click of the system clock, an interrupt is generated. When you
  35463.  specify <font color="#993333"><_bq>with profile_time</_bq></font> Euphoria
  35464.  will sample your program to see which
  35465.  statement is being executed at the exact moment that each interrupt occurs.
  35466.  
  35467. <p>
  35468.  These interrupts normally occur 18.2 times per second, but if you call
  35469.  <a href="lib_s_t.htm#tick_rate">tick_rate()</a> you can choose a much higher
  35470.  rate and thus get a more accurate
  35471.  time profile, since it will be based on more samples. By default, if you
  35472.  haven't called tick_rate(), then tick_rate(100) will be called automatically
  35473.  when you start profiling. You can set it even higher (up to say 1000) but you
  35474.  may start to affect your program's performance.
  35475.  
  35476. <p>
  35477.  Each sample requires 4 bytes of memory and buffer space is normally reserved
  35478.  for 25000 samples. If you need more than 25000 samples you can request it:
  35479.  
  35480. <_eucode>
  35481.         with profile_time 100000
  35482. </_eucode>
  35483.  
  35484.  will reserve space for 100000 samples (for example). If the buffer overflows
  35485.  you'll see a warning at the top of <font color="#993333"><b>ex.pro</b></font>.
  35486.  At 100 samples per second your
  35487.  program can run for 250 seconds before using up the default 25000 samples.
  35488.  It's not feasible for Euphoria to dynamically enlarge the sample buffer
  35489.  during the handling of an interrupt. That's why you might have to specify it
  35490.  in your program. After completing each top-level executable statement,
  35491.  Euphoria will process the samples accumulated so far, and free up the
  35492.  buffer for more samples. In this way the profile can be based on more samples
  35493.  than you have actually reserved space for.
  35494.  
  35495. <p>
  35496.  The percentages shown in the left margin of
  35497.  <font color="#993333"><b>ex.pro</b></font>,
  35498.  are calculated by dividing
  35499.  the number of times that a particular statement was sampled, by the total
  35500.  number of samples taken. e.g. if a statement were sampled 50 times out of a
  35501.  total of 500 samples, then a value of 10.0 (10 per cent) would appear in the
  35502.  margin beside that statement. When profiling is disabled with profile(0),
  35503.  interrupts are ignored, no samples are taken and the total
  35504.  number of samples does not increase.
  35505.  
  35506. <p>
  35507.  By taking more samples you can get more accurate results. However, one
  35508.  situation to watch out for is the case where a program synchronizes itself
  35509.  to the clock interrupt, by waiting for <a href="lib_s_t.htm#time">time()</a>
  35510.  to advance. The statements executed just after the point where the clock
  35511.  advances might <font color="#CC0099"><_ba><i>never</i></_ba></font> be
  35512.  sampled, which could give you a very distorted picture. e.g.
  35513. <_eucode>
  35514.         while time() < LIMIT do
  35515.         end while
  35516.         x += 1 -- This statement will never be sampled
  35517. </_eucode>
  35518.  
  35519. <p>
  35520.  Sometimes you will see a significant percentage beside a return statement.
  35521.  This is usually due to time spent deallocating storage for temporary and
  35522.  private variables used within the routine. Significant storage deallocation
  35523.  time can also occur when you assign a new value to a large sequence.
  35524.  
  35525. <p>
  35526.  If disk swapping starts to happen, you may see large times attributed to
  35527.  statements that need to access the swap file, such as statements
  35528.  that access elements of a large swapped-out sequence.
  35529.  
  35530. <_continue
  35531.   href="library.htm"
  35532.   name="Part II - Library Routines"
  35533. >
  35534.  
  35535. </_width>
  35536. </body>
  35537. </html>
  35538. REGISTER.HTX
  35539. 7106
  35540. <_init_comment>
  35541. <html>
  35542. <head><title>Ordering the Complete Edition of Euphoria</title>
  35543. </head>
  35544. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  35545. <_width>
  35546. <_center><font face="Arial, Helvetica" color="#FF0099" size=+2>
  35547. <br>
  35548.                Ordering the Complete Edition of Euphoria
  35549. </font></_center>
  35550. <p>
  35551.  
  35552. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  35553. <br>
  35554.  
  35555. <_dul>1. What You Get</_dul>
  35556.  
  35557. </font>
  35558. <p>
  35559.  Euphoria runs on <b>Windows</b>, <b>DOS</b> and <b>Linux</b> platforms. You
  35560.  can choose from the following packages:
  35561. <pre>
  35562.      New Registrations:
  35563.         <b><font color="#CC3366">WIN32 + DOS32</font></b> ........... $39
  35564.         <b><font color="#CC3366">Linux</font></b>  .................. $25
  35565.         <b><font color="#CC3366">WIN32 + DOS32 + Linux</font></b>  .. $59
  35566.      
  35567.      Upgrades:   
  35568.         <b><font color="#CC3366">WIN32 + DOS32</font></b> ........... $24
  35569.         <b><font color="#CC3366">WIN32 + DOS32 + Linux</font></b> ... $44
  35570. </pre>
  35571. <p>                
  35572.  Low cost <b>upgrade</b> prices are available to all registered users of
  35573.  Euphoria (from v1.0 onward). To get the upgrade price on a package, 
  35574.  you must have previously registered Euphoria on one of the platforms 
  35575.  contained in that package. For example, to be eligible for the
  35576.  <b><font color="#CC3366">WIN32 + DOS32</font></b> upgrade price, you must
  35577.  have previously registered Euphoria for
  35578.  <b><font color="#CC3366">WIN32 + DOS32</font></b>, or just
  35579.  <b><font color="#CC3366">DOS32</font></b>. To be eligible for the
  35580.  <b><font color="#CC3366">WIN32 + DOS32 + Linux</font></b> upgrade price,
  35581.  you must simply be a registered user of Euphoria on any platform.
  35582.                 
  35583. <p>
  35584.  All prices are in U.S. dollars. Shipping of a 3.5" floppy disk to any
  35585.  country, if required, costs $5.
  35586.  If you don't require a disk or a receipt, you can download the 
  35587.  Complete Edition software from our Web site and avoid the shipping charge.
  35588. <p>
  35589.  When you register or upgrade, you get:
  35590. <ul>
  35591. <li>
  35592.  versions of <b><font color="#993333">ex.exe</font>
  35593.  (<font color="#CC3366">DOS32</font>)</b> and
  35594.  <b><font color="#993333">exw.exe</font>
  35595.  (<font color="#CC3366">WIN32</font>)</b>, and/or
  35596.  <b><font color="#993333">exu</font>
  35597.  (<font color="#CC3366">Linux</font>)</b> with full,
  35598.  greater than 300 statements, diagnostic support
  35599. <p>
  35600. <li>
  35601.  the ability to <font color="#993333"><b>bind</b></font> and
  35602.  <font color="#993333"><b>shroud</b></font> Euphoria programs for easy use and
  35603.  distribution
  35604. <p>
  35605. <li>
  35606.  <font color="#993333"><b>execution-count profiling</b></font>, to analyze
  35607.  your program's logic, and improve performance
  35608. <p>
  35609. <li>
  35610.  <font color="#993333"><b>time profiling</b></font>, to discover performance
  35611.  bottlenecks (<font color="#CC3366"><b>DOS32</b></font> only)
  35612. <p>
  35613. <li>
  35614.  a discount on all future releases of Euphoria for the platforms that you have 
  35615.  registered
  35616. <p>
  35617. <li>
  35618.  6 months of free technical support from Rapid Deployment Software
  35619. <p>
  35620. <li>
  35621.  6 months of free software upgrades to the package you registered or upgraded
  35622. <p>
  35623. <li>
  35624.  the ability to vote in the <i>Euphoria Micro-Economy</i> and encourage others
  35625.  to develop software that you find useful. (See
  35626.  <a href="web.htm">web.doc</a> or the
  35627.  <a href="http://www.RapidEuphoria.com">RDS Web site</a> for details on the
  35628.  Micro-Economy.)
  35629. </ul>
  35630. <p>
  35631.  <b>Free upgrades</b> consist of downloading improved official-release software
  35632.  from the Web. You must have registered or upgraded within 6 months of a
  35633.  new <_ba><i>official</i></_ba> release (alpha-test and beta-test releases
  35634.  aren't considered).
  35635. <p>
  35636.  If you have earned money in the <i>Euphoria Micro-Economy</i>, please contact
  35637.  RDS (rds@attcanada.net) for details on how to reduce the price.
  35638.  
  35639. <p>
  35640.  
  35641. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  35642. <br>
  35643.  
  35644. <_dul>2. Methods of Registering</_dul>
  35645.  
  35646. </font>
  35647. <br>
  35648. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  35649. <br>
  35650.  
  35651. <_sul>2.1 Credit Card Orders</_sul>
  35652.  
  35653. </font>
  35654. <p>
  35655.  You can register or upgrade Euphoria through <b>DigiBuy</b> 
  35656.  using your MasterCard, Visa, American Express or Discover Card.
  35657.  
  35658.  Go to our Web site:
  35659. <pre>
  35660.         <a href="http://www.RapidEuphoria.com">http://www.RapidEuphoria.com</a>
  35661. </pre>
  35662.  and click "Register Now <i>On-Line!</i>"
  35663.  DigiBuy has a <font color="#FF0099"><b>secure</b></font> server that lets 
  35664.  your Web browser encrypt your credit card information before sending 
  35665.  it across the Internet. 
  35666. <p>
  35667.  If you choose to download the Complete Edition, we will send the instructions 
  35668.  to the e-mail address that you provide to DigiBuy. This usually happens the
  35669.  same day, or early the next day. If you choose to receive a disk
  35670.  (and receipt) we will assume that you don't need the instructions.
  35671.  E-mail us if you do - we 
  35672.  will give you the instructions, while still shipping your disk and receipt.
  35673. <p>
  35674.  With DigiBuy, there are <i>no</i> extra sales taxes to pay, unless you are
  35675.  a resident of Connecticut, Minnesota or Washington States.
  35676. <p>
  35677. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  35678. <br>
  35679.  
  35680. <_sul>2.2 Paying with a Check or Money Order</_sul>
  35681.  
  35682. </font>
  35683. <p>
  35684.  There is a program,
  35685.  <font color="#5500FF"><b>how2reg.ex</b></font>, in the 
  35686.  <b>euphoria\register</b> directory that will ask you questions
  35687.  and advise you on how to order.
  35688. <p> 
  35689.  Just type:
  35690. <pre>
  35691.         ex how2reg
  35692.    
  35693.  or on Linux:
  35694.         
  35695.         exu how2reg.ex
  35696. </pre>
  35697.  
  35698.  Run <font color="#5500FF"><b>how2reg</b></font> any time, and rerun it as
  35699.  many times as you like. You are <i>not</i> committed to registering
  35700.  just by running it. 
  35701.  Run <font color="#5500FF"><b>how2reg</b></font> for upgrade orders
  35702.  as well.
  35703. <p>
  35704.  After running <font color="#5500FF"><b>how2reg</b></font>, print
  35705.  <b>MYORDER.FRM</b> or simply copy the
  35706.  information to a sheet of paper, before mailing it to RDS with your check or
  35707.  money order.
  35708. <p>
  35709.  We prefer U.S. or Canadian currency. However, we can accept personal checks
  35710.  from any of the following countries:
  35711.  
  35712. <blockquote>
  35713. <p>
  35714.      Australia, Austria, Barbados, Belgium, Britain, Canada, Denmark, Finland,
  35715.      France, Greece, Germany, Hong Kong, Ireland, Japan, Mexico, Netherlands, 
  35716.      New Zealand, Norway, Portugal, Spain, Sweden, Switzerland, United States
  35717. <p>
  35718.      Please do a fair conversion from our U.S. dollar prices to your local
  35719.      currency.
  35720. </blockquote>
  35721. <p>
  35722.  Make your check or money order payable to:
  35723. <blockquote><blockquote>
  35724.     <b><font face="verdana, arial, geneva" color="#003366" size=-1>
  35725.     Rapid Deployment Software<p>
  35726.     130 Holm Crescent<br>
  35727.     Thornhill, Ontario<br>
  35728.     L3T 5J3<br>
  35729.     CANADA
  35730. </font></b></blockquote></blockquote>
  35731.  
  35732. <p>
  35733.  There are no extra sales taxes to pay. 
  35734. <p>
  35735.  
  35736. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  35737. <br>
  35738.  
  35739. <_dul>3. Return Policy</_dul>
  35740.  
  35741. </font>
  35742. <p>
  35743.  Since you have ample opportunity to "try before you buy" we do not accept
  35744.  returns. However, if the disk is damaged or lost in transit we will send
  35745.  you a new one free of charge.
  35746.  
  35747. <p> 
  35748.  
  35749. </_width>
  35750. </body>
  35751. </html>
  35752.  
  35753. RELNOTES.HTX
  35754. 56834
  35755. <_init_comment>
  35756. <html>
  35757. <head><title>Euphoria v2.2 Release Notes</title>
  35758. </head>
  35759. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  35760. <_width>
  35761. <_center><font face="Arial, Helvetica" color="#006633"><b>
  35762. <br>
  35763.                            Euphoria Release Notes<br>
  35764. </b></font></_center>
  35765.  
  35766. <p> <br>
  35767.  
  35768. <font face="Arial, Helvetica" color="#003366">
  35769. <b><_dul>Version 2.2 Official Release for WIN32+DOS32 January 14, 2000:</_dul></b></font>
  35770. <ul>
  35771. <li> Better error messages are now issued from the interpreter, and from
  35772. the bind program, for some typical errors that users can make when 
  35773. binding a program.
  35774. <p>
  35775. <li> The documentation has been improved in a few places.
  35776. <p>
  35777. <li> The <b>window.exw</b> demo program shows how to load the 
  35778. Euphoria icon contained in exw.exe.
  35779. <p>
  35780. <li> Language War uses Jiri Babor's improved version of <b>putsxy.e</b>.
  35781. </ul>
  35782.  
  35783. <p> <br>
  35784.  
  35785. <font face="Arial, Helvetica" color="#003366">
  35786. <b><_dul>Version 2.2 Beta Release for WIN32+DOS32 December 23, 1999:</_dul></b></font>
  35787. <p>
  35788. Most of the new library routines developed for Euphoria 2.2 on 
  35789. Linux, have now been ported to WIN32 and DOS32. 
  35790. These are: sleep(), chdir(), flush(), lock_file(), unlock_file(),
  35791. crash_file(), get_screen_char() and put_screen_char(). For a
  35792. description of these routines refer to the Linux release notes below,
  35793. or <a href=library.htm>LIBRARY.DOC</a>.
  35794.  
  35795. <p>
  35796. Some cross-platform bug fixes and other miscellaneous improvements 
  35797. were made during the Linux port. These bug fixes and improvements
  35798. have now been ported back to WIN32+DOS32. See the Linux release notes (below).
  35799.  
  35800. <p>
  35801. In addition, the following improvements have been made specifically 
  35802. for WIN32 and DOS32:
  35803. <ul>
  35804. <p>
  35805. <li> <b>exw.exe</b> now contains a Euphoria icon that is displayed 
  35806. automatically by Windows. The icon was contributed by Gary Dumer.
  35807. Registered users may change this icon when they bind a program.
  35808. <p>
  35809. <li> <b>exw.exe</b> is now a compressed executable of just 73K (or so).
  35810. It's compressed using the UPX compression tool for .exe files.
  35811. <p>
  35812. <li> <b>ex.exe</b> has been updated with the latest release of 
  35813. the CauseWay DOS extender. A problem where
  35814. CauseWay would sometimes limit you to 64Mb of memory under
  35815. some DOS configurations has been eliminated, and a few other minor
  35816. bugs were fixed.
  35817. <p>
  35818. <li> <b><font color="#009999">bug fix:</font></b>
  35819. The error traceback could sometimes crash or be misprinted when
  35820. a type_check failure occurred. It could only happen when 1 was added to
  35821. an expression, and the non-integer result of the expression 
  35822. was assigned to a variable declared as integer.
  35823. <p>
  35824. <li> <b><font color="#009999">bug fix:</font></b>
  35825. If text_rows() was called as the first routine needing a WIN32 console
  35826. window, Euphoria would fail to set the new number of lines of
  35827. text on the console.
  35828.  
  35829. </ul>
  35830.  
  35831. <p> <br>
  35832.  
  35833. <font face="Arial, Helvetica" color="#003366">
  35834. <b><_dul>Version 2.2 Official Release for Linux November 22, 1999:</_dul></b></font>
  35835. <ul>
  35836. <li> <b>All platforms: <font color="#009999">bug fix:</font></b>
  35837. If a Euphoria routine called itself recursively from inside a
  35838. for-loop, and at one level of recursion the for-loop counted <i>up</i> 
  35839. to an upper limit, and at another level of recursion the for-loop 
  35840. counted <i>down</i> to a 
  35841. lower limit, the for-loop would probably malfunction at one of the levels.
  35842. Thanks to Delroy Gayle.
  35843. <p>
  35844. <li> The documentation was improved in many places, especially with respect
  35845. to the Linux platform.
  35846. </ul>
  35847. <p>
  35848. <font face="Arial, Helvetica" color="#003366">
  35849. <b><_dul>Version 2.2 beta-test release for Linux October 22, 1999:</_dul></b></font>
  35850. <p>
  35851. <i>Most of these features and bug fixes will also be made available 
  35852. in Version 2.2 for <font color="#CC3366"><b>WIN32 + DOS32</b></font></i>. 
  35853. <ul>
  35854. <p>
  35855. <li>
  35856. <font color="#006699"><b>platform()</b></font> has been moved from misc.e into exu to eliminate 
  35857. the function call overhead. platform() now takes zero time to compute.
  35858. The compiler simply plugs in the appropriate constant value.
  35859. <p>
  35860. <li>
  35861.  <font color="#006699"><b>lock_file()</b></font> 
  35862.  and <font color="#006699"><b>unlock_file()</b></font> have been added 
  35863.  to allow multiple processes
  35864.  to share access to files. This can be important in CGI programming and
  35865.  other areas.
  35866. <p>
  35867. <li>
  35868. <font color="#006699"><b>flush()</b></font> will force the contents of the memory buffer out to a file or device.
  35869. <p>
  35870. <li>
  35871. <font color="#006699"><b>chdir()</b></font> will change to a new current directory and let you know if it
  35872. was successful.
  35873. <p>
  35874. <li>
  35875. <font color="#006699"><b>sleep()</b></font> will suspend execution of your program for a number of seconds,
  35876. and let the operating system schedule another process.
  35877. <p>
  35878. <li>
  35879. <font color="#006699"><b>put_screen_char()</b></font> will write a character and its attributes (colors etc.)
  35880. to the screen.
  35881. <p>
  35882. <li>
  35883. <font color="#006699"><b>get_screen_char()</b></font> will read a character and its attributes from the screen.
  35884. <p>
  35885. <li>
  35886. <font color="#006699"><b>save_text_image()</b></font> now works on Linux (as well as DOS32). It copies
  35887. a rectangular text image from the screen.
  35888. <p>
  35889. <li>
  35890. <font color="#006699"><b>display_text_image()</b></font> now works under Linux (as well as DOS32). 
  35891. It writes a rectangular text image to the screen.
  35892. <p>  
  35893. <li>
  35894. The "short-circuit" warning now gives the filename and line number of the 
  35895.   possibly short-circuited call. Minor clarifications were made in some 
  35896.   other error messages as well.
  35897. <p>
  35898. <li>
  35899. Minor improvements were made to <b>ed</b> and <b>search</b>.
  35900. <p>
  35901. <li>
  35902. A portability problem in <b>how2reg.ex</b> was fixed.
  35903. <p>
  35904. <li>
  35905. <b>exu</b> is compressed better. It's actually a bit smaller now,
  35906. although functionality has been added to it. 
  35907. </ul>
  35908.  
  35909.  
  35910. <p> <br>
  35911.  
  35912. <font face="Arial, Helvetica" color="#003366">
  35913. <b><_dul>Version 2.2 alpha-test release for Linux August 24, 1999:</_dul></b></font>
  35914.  
  35915. <p>
  35916. <i>Many of these features and bug fixes will also be made available 
  35917. in Version 2.2 for <font color="#CC3366"><b>WIN32 + DOS32</b></font></i>. 
  35918. <ul>
  35919. <p>
  35920. <li>
  35921.  The documentation has been brought up-to-date to include 
  35922.   <font color="#CC3366"><b>Linux</b></font>-specific information for library
  35923.   routines and Euphoria in general.
  35924. <p>
  35925. <li>
  35926.  There is now a Complete Edition for
  35927.   <font color="#CC3366"><b>Linux</b></font>, including
  35928.   <font color="#993333"><b>binding</b></font> and 
  35929.   <font color="#993333"><b>shrouding</b></font>. See
  35930.   <font color="#5500FF"><b>register\register.doc</b></font>.
  35931. <p>
  35932. <li>
  35933.  There is now <font color="#CC3366">text mode</b></font> mouse support using
  35934.   <font color="#006699"><b>get_mouse()</b></font>. You must have <b>GPM
  35935.   server</b> running. It works in a text console or an <b>xterm</b> window.
  35936. <p>
  35937. <li>
  35938.  <font color="#CC3366"><b>Linux:</b></font>
  35939.   <font color="#006699"><b>define_c_var(name)</b></font> will return the
  35940.   address of a global C variable in a shared library.
  35941. <p>
  35942. <li>
  35943.  It was confirmed that you can call Euphoria routines from
  35944.   <font color="#CC3366"><b>Linux</b></font> C routines using exactly the same
  35945.   mechanism as in <font color="#CC3366"><b>WIN32</b></font> Euphoria.
  35946.   See <font color="#5500FF"><b>euphoria/demo/linux</b></font>.
  35947. <p>
  35948. <li>
  35949.  An example of creating your own shared library routines and calling them from
  35950.   Euphoria was added. See
  35951.   <font color="#5500FF"><b>euphoria/demo/linux</b></font>.
  35952. <p>
  35953. <li>
  35954.  <b>All platforms: <font color="#006699">crash_file(file_name)</font></b> will
  35955.   cause diagnostic messages to be written to <b>file_name</b> instead of
  35956.   <font color="#993333"><b>ex.err</b></font>. You can use 
  35957.   <font color="#006699"><b>crash_file("/dev/null")</b></font> to get
  35958.   diagnostics on screen but not in a file.<br>
  35959.   <font color="#006699"><b>crash_file("")</b></font> means
  35960.   "no diagnostics" (to screen or ex.err). 
  35961. <p>
  35962. <li>
  35963.  <font color="#993333"><b>Trace</b></font> mode in <b>xterm</b> now detects
  35964.   the <b>F1/F2</b> keys.
  35965. <p>
  35966. <li>
  35967.  <font color="#006699"><b>time()</b></font> now reports real "wall-clock" time,
  35968.   not CPU time.
  35969. <p>
  35970. <li>
  35971.  <font color="#993333"><b>search</b></font>,
  35972.   <font color="#993333"><b>guru</b></font> and
  35973.   <font color="#993333"><b>cdguru</b></font> now place their output in your
  35974.   $HOME directory instead of the current directory.
  35975. <p>
  35976. <li>
  35977.  <b>#!</b> is now restricted to just the first line of a file.
  35978. <p>
  35979. <li>
  35980.  <b>All platforms:</b> In <font color="#993333"><b>ed</b></font>, the
  35981.   <b>Esc n</b>, <b>Esc d</b>, <b>Esc f</b> and <b>Esc r</b> commands will
  35982.   immediately redisplay your last choice. You can press
  35983.   <b>up-arrow/down-arrow</b> to 
  35984.   see other choices, or clear the choice. If you start typing without
  35985.   editing, it will clear the choice and take your new input.
  35986. <p>
  35987. <li>
  35988.  <font color="#006699"><b>free_console()</b></font> will set the terminal
  35989.   parameters back to normal. Normally, when running a Euphoria program the
  35990.   parameters are set the way that <b>curses</b> wants them and they are set
  35991.   back to normal when the program terminates.
  35992.   If your program needs to terminate
  35993.   in a strange way (other than calling <font color="#006699">abort()</font>),
  35994.   <font color="#006699"><b>free_console()</b></font> should be called first. 
  35995. <p>
  35996. <li>
  35997.  <b><font color="#009999">bug fix:</font> <font color="#006699">get()</font>
  35998.   </b> now considers '\r' to be a whitespace character. This is important when
  35999.   reading DOS files.
  36000. <p>
  36001. <li>
  36002.  <b>All platforms: <font color="#009999">bug fix:</font></b> It was not
  36003.   immediately issuing a <font color="#993333"><b>type_check</b></font> 
  36004.   failure when 1 was added to an integer variable that was set to the maximum
  36005.   value for an integer (1.07 billion). Thanks to Jeff Fielding.
  36006. <p>
  36007. <li>
  36008.  <b>All platforms: <font color="#009999">bug fix:</font></b> It was not
  36009.   always detecting an improperly-formed 
  36010.   exponent on a floating-point number. Thanks to Lionel Wong.
  36011. <p>
  36012. <li>
  36013.  <b>All platforms:</b> The performance of the storage allocator has been 
  36014.   improved in certain cases. A bug that could cause the interpreter to 
  36015.   crash when you are almost out of memory has been fixed. 
  36016. </ul>       
  36017. <p> <br>
  36018.  
  36019. <font face="Arial, Helvetica" color="#003366">
  36020. <b><_dul>Version 2.2 pre-alpha #4 for Linux July 15, 1999:</_dul></b></font>
  36021. <ul>
  36022. <li>
  36023.  You can call C routines in <font color="#CC3366"><b>Linux</b></font>
  36024.   shared libraries (<b>.so</b> files). See
  36025.   <font color="#5500FF"><b>euphoria/demo/linux/callc.exu</b></font> for
  36026.   some examples.
  36027. <p>
  36028. <li>
  36029.  If your program does not output anything to the <b>xterm</b> window, 
  36030.   <font color="#993333"><b>exu</b></font> will not issue the "Press Enter"
  36031.   prompt.
  36032. <p>
  36033. <li>
  36034.   <b>All platforms: <font color="#993333">ed</font></b> now lets you recall
  36035.    previous top-line command text using <b>up-arrow</b> and <b>down-arrow</b>,
  36036.    similar to doskey in DOS and the shell history in Linux. This works with
  36037.    any strings that you type for <b>Esc n</b> (new file),
  36038.    <b>Esc d</b> (Linux command), <b>Esc f</b> (find string) or
  36039.    <b>Esc r</b> (replace string). In addition, you can now use
  36040.    <b>arrow keys</b>, <b>Home</b>, <b>End</b>, <b>Delete</b> etc. to edit
  36041.    strings before you press <b>Enter</b>. 
  36042. </ul>       
  36043. <p> <br>
  36044.  
  36045. <font face="Arial, Helvetica" color="#003366">
  36046. <b><_dul>Version 2.2 pre-alpha #3 for Linux July 8, 1999:</_dul></b></font>
  36047. <ul>
  36048. <li>
  36049.  In an <b>xterm</b> window, <font color="#993333"><b>exu</b></font> will
  36050.   prompt you to hit <b>Enter</b> before it exits. Without this, <b>xterm</b>
  36051.   restores the screen so fast that you don't see any output or error messages.
  36052. <p>
  36053. <li>
  36054.  An internal coding change was made to Euphoria's
  36055.   <font color="#006699"><b>rand()</b></font> function. 
  36056.   (The algorithm has not changed.)
  36057.   Hopefully this will
  36058.   allow <font color="#006699">rand()</font> to work on all distributions of
  36059.   <font color="#CC3366"><b>Linux</b></font>. Please let us know if
  36060.   <font color="#006699">rand()</font> still fails.
  36061. <p>
  36062. <li>
  36063.  <font color="#993333"><b>ed:</b></font> The <b>Esc h</b> command will
  36064.   display the Euphoria help files. This was broken in pre-alpha#2.
  36065. <p>
  36066. <li>
  36067.  In an <b>xterm</b> window, Euphoria's
  36068.   <font color="#006699"><b>video_config()</b></font> now reports the correct 
  36069.   number of lines and columns - this helps
  36070.   <font color="#993333"><b>ed</b></font> to work much better.
  36071.   <font color="#993333"><b>ed</b></font> will work with the initial size of
  36072.   window in effect when <font color="#993333"><b>ed</b></font> starts up.
  36073. <p>
  36074. <li>
  36075.  <font color="#993333"><b>ed:</b></font> <b>F1</b>, <b>F2</b>, <b>F3</b>,
  36076.   <b>F4</b>, <b>Home</b>, <b>End</b>, and the <b>Delete</b> key work now in
  36077.   <b>xterm</b> (under Red Hat 5.2 at least). The other F-keys were already
  36078.   working. <b>PageUp/PageDown</b> and some other keys still don't work - feel
  36079.   free to add your own alternate keys.
  36080. <p>
  36081. <li>
  36082.  <font color="#993333"><b>exu</b></font> is now even smaller - just 82K.
  36083. </ul>       
  36084. <p> <br>
  36085.  
  36086. <font face="Arial, Helvetica" color="#003366">
  36087. <b><_dul>Version 2.2 pre-alpha #2 for Linux July 6, 1999:</_dul></b></font>
  36088. <ul>
  36089. <li>
  36090.  The <b>ncurses</b> library has been statically linked into
  36091.   <font color="#993333"><b>exu</b></font>.
  36092. <p>
  36093. <li>
  36094.  <font color="#993333"><b>exu</b></font> is now a compressed executable (97K).
  36095. <p>
  36096. <li>
  36097.  <b><font color="#009999">bug fix:</font> <font color="#993333">ed</font></b>
  36098.   can now edit files with upper case letters in the name.
  36099. <p>
  36100. <li>
  36101.  The fraction of a second delay when you press the <b>Esc</b> key in
  36102.   <font color="#993333"><b>ed</b></font> has been removed.
  36103. <p>
  36104. <li>
  36105.  The correct address for subscribing to the Euphoria mailing list is in
  36106.   <font color="#5500FF"><b>web.doc</b></font> and
  36107.   <font color="#5500FF"><b>web.htm</b></font> (the old address doesn't work
  36108.   anymore).
  36109. </ul>
  36110. <p> <br>
  36111.  
  36112. <font face="Arial, Helvetica" color="#003366">
  36113. <b><_dul>Version 2.2 pre-alpha #1 for Linux July 1, 1999:</_dul></b></font>
  36114. <ul>
  36115. <li> The first version of Euphoria for
  36116.  <font color="#CC3366"><b>Linux</b></font> was released.
  36117. </ul>       
  36118. <p> <br>
  36119.  
  36120. <font face="Arial, Helvetica" color="#003366"><b>
  36121. <_dul>Version 2.1 Official Release for WIN32 + DOS32 March 29, 1999:</_dul>
  36122. </b></font>
  36123.  
  36124. <ul>
  36125. <li>
  36126.   Updates to the <font color="#993333"><b>trace</b></font> screen have been
  36127.   optimized. Unnecessary refreshes of the source code, and the variables on
  36128.   the trace screen, have been eliminated. When a refresh is necessary, it is
  36129.   now slightly faster. This makes a noticeable difference in
  36130.   <font color="#993333"><b>exw.exe</b></font>, and also in
  36131.   <font color="#993333"><b>ex.exe</b></font> in
  36132.   <font color="#CC3366">pixel-graphics modes</font>. For 
  36133.   <font color="#993333"><b>ex.exe</b></font> in 
  36134.   <font color="#CC3366">text modes</font>, it reduces screen flicker 
  36135.   slightly.
  36136. <p>
  36137. <li>
  36138.   The <font color="#993333"><b>install</b></font> program no longer requires 
  36139.   that your PATH be less than 128 characters. It will simply warn you if it 
  36140.   isn't. Newer versions of DOS allow for a longer PATH. Thanks to Steve Adams.
  36141. <p>
  36142. <li>
  36143.   An extra error check was added to
  36144.   <font color="#006699"><b>unregister_block()</b></font> in
  36145.   <font color="#5500FF"><b>safe.e</b></font>. Thanks to David Guy.
  36146. </ul>
  36147.   
  36148. <p> <br>
  36149.  
  36150. <font face="Arial, Helvetica" color="#003366">
  36151. <b><_dul>Version 2.1 beta-test release March 5, 1999:</_dul></b></font>
  36152.  
  36153. <ul>
  36154. <li>
  36155.   The rest of the files in the <font color="#5500FF"><b>euphoria\doc</b></font>
  36156.   directory have now been converted to HTML. Every <b>.doc</b> file in the
  36157.   <font color="#5500FF"><b>doc</b></font> directory now has a corresponding
  36158.   <b>.htm</b> file in the <font color="#5500FF"><b>euphoria\html</b></font>
  36159.   directory. Many improvements and clarifications were made to the
  36160.   documentation.
  36161. <p>
  36162. <li>
  36163.   You will now be warned when you have code that comes immediately
  36164.   after an <font color="#993333"><b>exit</b></font>,
  36165.   <font color="#993333"><b>return</b></font> or
  36166.   <font color="#993333"><b>abort()</b></font> statement. This code can never
  36167.   be executed. Suggested by Gabriel Boehme.
  36168. <p>
  36169. <li>
  36170.   <font color="#5500FF"><b>safe.e</b></font> no longer includes
  36171.   <font color="#5500FF"><b>graphics.e</b></font>. This eliminates possible
  36172.   naming conflicts when <font color="#5500FF"><b>safe.e</b></font> is
  36173.   substituted for <font color="#5500FF"><b>machine.e</b></font>.
  36174. <p>
  36175. <li>
  36176.   Using code supplied by David Guy, <font color="#5500FF"><b>safe.e</b></font>
  36177.   will now let you add or remove externally-allocated blocks of memory on
  36178.   the "safe address list". <font color="#006633"><b>See the new library
  36179.   routines:</b></font>
  36180.   <font color="#006699"><b>register_block()</b></font> and
  36181.   <font color="#006699"><b>unregister_block()</b></font>.
  36182. <p>
  36183. <li>
  36184.   <font color="#006699"><b>message_box()</b></font> now uses the <b>handle of
  36185.   the active window</b> rather than NULL. This forces the user to reply to
  36186.   your message before he can continue to interact with your program.
  36187.   He won't be prevented from interacting with other programs. Thanks to
  36188.   Austin C.
  36189. <p>
  36190. <li>
  36191.   <font color="#006699"><b>get()</b></font> and
  36192.   <font color="#006699"><b>value()</b></font> have been sped up by a
  36193.   further 5% thanks to Gabriel Boehme.
  36194. <p>
  36195. <li>
  36196.   <font color="#993333"><b>exw.exe</b></font> has been made less likely
  36197.   to crash mysteriously when attacked by a virus.
  36198. <p>
  36199. <li>
  36200.   <font color="#5500FF"><b>sanity.ex</b></font> now checks your installation
  36201.   of Euphoria. You'll be warned if your PATH or EUDIR variables are not set,
  36202.   or your <font color="#993333"><b>ex.exe</b></font>,
  36203.   <font color="#993333"><b>exw.exe</b></font>,
  36204.   <font color="#993333"><b>pdex.exe</b></font>, or
  36205.   <font color="#993333"><b>pdexw.exe</b></font> files have been corrupted
  36206.   or not installed correctly in
  36207.   <font color="#5500FF"><b>euphoria\bin</b></font>.
  36208. <p>
  36209. <li>
  36210.   The security of <font color="#993333"><b>bound</b></font> and
  36211.   <font color="#993333"><b>scrambled</b></font> programs has been tightened
  36212.   some more. Thanks to Rusty Davis.
  36213. <p>
  36214. <li>
  36215.   To save space in <b>euphor21.zip</b>, the
  36216.   <font color="#993333"><b>install</b></font> program now <i>generates</i> the
  36217.   HTML and DOC files from a common source, using Junko Miura's
  36218.   <font color="#993333"><b>documentation generator</b></font>. In the process,
  36219.   the generator is deleted, but you can download it from the RDS site.
  36220. <p>
  36221. <li>
  36222.   When a <font color="#993333"><b>type_check</b></font> failure occurs
  36223.   you'll be warned if the type erroneously returned a <i>sequence</i> for it's
  36224.   "true/false" result. Previously, a sequence result was simply reported
  36225.   as a type_check failure. Suggested by Ralf Nieuwenhuijsen.
  36226. <p>
  36227. <li>
  36228.  The code for <font color="#5500FF"><b>demo\win32\winwire.exw</b></font> was
  36229.  cleaned up considerably.
  36230. <p>
  36231. <li>
  36232.  The <font color="#993333"><b>install</b></font> program will warn you to
  36233.  change your <b>autoexec.bat</b> file when you install a new
  36234.  release of Euphoria onto a <i>different</i> drive.
  36235. </ul>
  36236.  
  36237. <p> <br>
  36238.  
  36239. <font face="Arial, Helvetica" color="#003366">
  36240. <b><_dul>Version 2.1 alpha-test release January 15, 1999:</_dul></b></font>
  36241.  
  36242. <ul>
  36243. <li>
  36244.  We've made a number of changes to the packaging, pricing, and registration
  36245.  incentives for the Euphoria product:
  36246.  
  36247. <ul>
  36248. <p>
  36249. <li>
  36250.      The Dual-Platform (DOS32+WIN32) package, formerly $53 has been reduced
  36251.      to $39 U.S., effective immediately.
  36252. <p>
  36253. <li>
  36254.      The Single-Platform (DOS32-only) package, formerly $32, has been
  36255.      discontinued.
  36256. <p>
  36257. <li>
  36258.      The printed manual has been discontinued. Instead, there is now an
  36259.      official HTML version of the manual, included with the Public Domain
  36260.      .zip file.
  36261. <p>
  36262. <li>
  36263.      All useful 3rd-party include files, such as <b>Win32Lib.ew</b> and many
  36264.      others, will be "stamped" by RDS with a code number that makes them
  36265.      <font color="#CC0099"><b><i>free</i></b></font>, just like the files in
  36266.      <font color="#5500FF"><b>euphoria\include</b></font>. They will not 
  36267.      add to your statement count, provided you do not significantly modify
  36268.      them. This will also allow 3rd-party developers to get better diagnostic
  36269.      information from their users.
  36270. <p>
  36271. <li>
  36272.      <font color="#993333"><b>Binding</b></font>,
  36273.      <font color="#993333"><b>shrouding</b></font> and
  36274.      <font color="#993333"><b>profiling</b></font> will now be part of the
  36275.      Complete Edition only. These are features that beginners do not require,
  36276.      but serious users might find valuable.
  36277.  
  36278. </ul>
  36279.  
  36280. <p>
  36281. <li>
  36282.  Short-form assignment operators <font color="#993333"><b>  +=  
  36283.  -=   *=   /=   &=  </b></font> have been added. 
  36284.  For example, instead of saying:
  36285. <_eucode>
  36286.            count = count + 1
  36287. </_eucode>
  36288.  You can now say:
  36289. <_eucode>
  36290.            count += 1
  36291. </_eucode>
  36292.  
  36293.  Instead of saying:
  36294. <_eucode>
  36295.            matrix[row][column] = matrix[row][column] * 5.0
  36296. </_eucode>
  36297.  You can say:
  36298. <_eucode>
  36299.            matrix[row][column] *= 5.0
  36300. </_eucode>
  36301.  
  36302.  Instead of saying:
  36303. <_eucode>
  36304.            test_scores[start..finish] = test_scores[start..finish] / 100
  36305. </_eucode>
  36306.  You can say:
  36307. <_eucode>
  36308.            test_scores[start..finish] /= 100
  36309. </_eucode>
  36310.  See <a href="refman_2.htm#assignop"><font color="#5500FF">
  36311.  <b>refman.doc</b></font></a> for the details.
  36312.  
  36313. <p>
  36314. <li>
  36315.  Euphoria now uses "short-circuit" evaluation of
  36316.  <font color="#993333"><_bq>and</_bq></font> and
  36317.  <font color="#993333"><_bq>or</_bq></font> expressions in
  36318.  <font color="#993333"><b>if/elsif/while</b></font> conditions.
  36319.  e.g. in an <font color="#993333"><_bq>and</_bq></font> condition:
  36320. <_eucode>
  36321.            if A and B then ...
  36322. </_eucode>
  36323.    the interpreter will skip the evaluation of expression B whenever 
  36324.    expression A is 0 (false), since it knows that the overall result
  36325.    must be false. In an <font color="#993333"><_bq>or</_bq></font> condition:
  36326. <_eucode>
  36327.            while A or B do ...
  36328. </_eucode>
  36329.    the interpreter will skip the evaluation of expression B whenever
  36330.    expression A is non-zero (true), since it knows that the overall result
  36331.    must be true.
  36332. <p>
  36333.    Euphoria code written prior to version 2.1 may no longer work correctly if
  36334.    expression B contains a function with <b><i>side-effects</i></b> such as
  36335.    setting a global variable, doing I/O etc. In practice this kind of code is
  36336.    very rare, but just in case, a warning will now be issued if a function
  36337.    with side-effects might be short-circuited. 
  36338. <p>
  36339.    By skipping the evaluation of B, short-circuit evaluation is typically
  36340.    faster, and will allow you to write statements such as:
  36341. <_eucode>
  36342.            if atom(x) or length(x)=1 then ...
  36343. </_eucode>
  36344.    that would generate an error on older versions of Euphoria whenever x
  36345.    was an <font color="#993333"><b>atom</b></font>, since
  36346.    <font color="#006699">length()</font> is not defined for atoms.
  36347. <p>
  36348.    See <a href="refman_2.htm#shortcir"><font color="#5500FF">
  36349.    <b>refman.doc</b></font></a> for the details.
  36350.  
  36351. <p>
  36352. <li>
  36353.  Several new routines were added.
  36354. <p>
  36355.  <font color="#006633"><_sul><b>Built-in to ex.exe/exw.exe:</b></_sul></font>
  36356. <p>
  36357.  <table border=0 cellspacing=2 cellpadding=2>
  36358.  
  36359.  <tr><td width=24 nowrap></td>
  36360.    <td width=120 nowrap></td>
  36361.    <td width=10></td>
  36362.    <td></td>
  36363.    </tr>
  36364.  
  36365.  <_4clist
  36366.    name="<font color=\"#006699\">profile()</font>"
  36367.    pos=25
  36368.    description="turns <font color=\"#993333\"><b>profiling</b></font>
  36369.     <b>on/off</b> so you can focus your
  36370.     <font color=\"#993333\"><b>profile</b></font> and
  36371.     <font color=\"#993333\"><b>profile_time</b></font> runs on particular
  36372.     events within your program."
  36373.  >
  36374.  
  36375.  <_4clist
  36376.    name="<font color=\"#006699\">system_exec()</font>"
  36377.    pos=25
  36378.    description="gives you the exit code from calling a <b>.exe</b> or
  36379.     <b>.com</b> file, or another Euphoria program."
  36380.  >
  36381.  
  36382.  <_4clist
  36383.    name="<font color=\"#006699\">equal()</font>"
  36384.    pos=25
  36385.    description="compares any 2 Euphoria objects for equality.
  36386.      equivalent to: <font color=\"#006699\">compare(a,b) = 0 </font> but
  36387.      more readable."
  36388.  >
  36389.  
  36390.  </table>
  36391.  
  36392. <p>
  36393.  <font color="#006633"><_sul><b>Added to various include files:</b></_sul>
  36394.  </font>
  36395. <p>
  36396.  <table border=0 cellspacing=2 cellpadding=2>
  36397.  
  36398.  <tr><td width=24 nowrap></td>
  36399.    <td width=120 nowrap></td>
  36400.    <td width=10></td>
  36401.    <td></td>
  36402.    </tr>
  36403.  
  36404.  <_4clist
  36405.    name="<font color=\"#006699\">walk_dir()</font>"
  36406.    pos=26
  36407.    description="recursively goes through a directory and subdirectories,
  36408.      calling a routine that you supply."
  36409.  >
  36410.  
  36411.  <_4clist
  36412.    name="<font color=\"#006699\">reverse()</font>"
  36413.    pos=26
  36414.    description="returns a sequence in reverse order."
  36415.  >
  36416.  
  36417.  <_4clist
  36418.    name="<font color=\"#006699\">sprint()</font>"
  36419.    pos=26
  36420.    description="returns the string representation of any Euphoria object."
  36421.  >
  36422.  
  36423.  <_4clist
  36424.    name="<font color=\"#006699\">arcsin()</font>"
  36425.    pos=26
  36426.    description="inverse trig function."
  36427.  >
  36428.  
  36429.  <_4clist
  36430.    name="<font color=\"#006699\">arccos()</font>"
  36431.    pos=26
  36432.    description="inverse trig function."
  36433.  >
  36434.  
  36435.  <_4clist
  36436.    name="<font color=\"#006699\">get_bytes()</font>"
  36437.    pos=26
  36438.    description="returns the next n bytes from a file."
  36439.  >
  36440.  
  36441.  <_4clist
  36442.    name="<font color=\"#006699\">prompt_number()</font>"
  36443.    pos=26
  36444.    description="prompts the user to enter a number."
  36445.  >
  36446.  
  36447.  <_4clist
  36448.    name="<font color=\"#006699\">prompt_string()</font>"
  36449.    pos=26
  36450.    description="prompts the user to enter a string."
  36451.  >
  36452.  
  36453.  <_4clist
  36454.    name="<font color=\"#006699\">instance()</font>"
  36455.    pos=26
  36456.    description="<font color=\"#CC3366\"><b>WIN32:</b></font> returns the
  36457.     instance handle of the program."
  36458.  >
  36459.  
  36460.  <_4clist
  36461.    name="PI"
  36462.    pos=26
  36463.    description="the constant PI - 3.14159... was added to
  36464.     <font color=\"#5500FF\"><b>misc.e</b></font>."
  36465.  >
  36466.  
  36467.  </table>
  36468.  
  36469. <p>
  36470.    See <a href="library.htm"><font color="#5500FF"><b>library.doc</b></font>
  36471.    </a> for the details.
  36472.  
  36473. <p>
  36474. <li>
  36475.  The main Euphoria documentation can now be viewed locally with a Web 
  36476.    browser. The plain-text files <font color="#5500FF"><b>refman.doc</b></font>
  36477.    and <font color="#5500FF"><b>library.doc</b></font> are still 
  36478.    available in the <font color="#5500FF"><b>doc</b></font> subdirectory,
  36479.    but we now have <font color="#5500FF"><b>refman.htm</b></font> and 
  36480.    <font color="#5500FF"><b>library.htm</b></font> in the new
  36481.    <font color="#5500FF"><b>html</b></font> subdirectory. We have developed
  36482.    a tool (written in Euphoria) that lets us easily maintain both an
  36483.    up-to-date HTML version, and an up-to-date plain-text version of
  36484.    <font color="#5500FF"><b>refman</b></font> and
  36485.    <font color="#5500FF"><b>library</b></font>.
  36486. <p>  
  36487.    The documentation has also been clarified and expanded in many places.
  36488.  
  36489. <p>
  36490. <li>
  36491.  <font color="#CC3366"><b>WIN32:</b></font> you can create an
  36492.  <font color="#CC0099"><b>unlimited</b></font> number of Euphoria
  36493.  call-back routines,
  36494.    as long as each routine is a function with 0 to 8 parameters. 
  36495.    See <a href="platform.htm#callback"><font color="#5500FF">
  36496.    <b>platform.doc</b></font></a>. In version 2.0 you could only have one
  36497.    call-back routine and it had to have exactly 4 parameters.
  36498.  
  36499. <p>
  36500. <li>
  36501.  The <font color="#993333"><_bq>xor</_bq></font> keyword has been added to
  36502.   complement: <font color="#993333"><b>and/or/not</b></font> and
  36503.   <font color="#006699"><b>xor_bits()</b></font> e.g.
  36504. <_eucode>
  36505.            if a xor b then...
  36506. </_eucode>
  36507.    <font color="#993333"><_bq>xor</_bq></font> works on sequences too.
  36508.    It's similar to <font color="#993333"><_bq>or</_bq></font>.
  36509.  
  36510. <p>
  36511. <li>
  36512.  The <font color="#006699"><b>dir(path)</b></font> library routine now
  36513.  officially supports the use of <b>wildcards *</b> and <b>?</b> in the path
  36514.  that you supply. This feature was always available, but wasn't
  36515.  documented until now. e.g.
  36516. <_eucode>
  36517.            info = dir("mydata\\*.d?t")
  36518. </_eucode>
  36519.  
  36520. <li>
  36521.  <font color="#CC3366"><b>optimization:</b></font>
  36522.   Subroutine call+return overhead was reduced by an average of 
  36523.    30%. The speed-up occurs for all normal function/procedure/type calls, 
  36524.    user-defined type-checks,
  36525.    <font color="#006699">call_proc()/call_func()</font> calls using a
  36526.    <font color="#993333"><b>routine id</b></font>, 
  36527.    and Windows call-backs. Only recursive calls cost the same as before. 
  36528.    Programs with a reasonably-high frequency of calls can easily be 10% faster 
  36529.    overall because of this.
  36530.  
  36531. <p>
  36532. <li>
  36533.  <font color="#CC3366"><b>optimization:</b></font>
  36534.  Branch <font color="#CC0099"><_bq><i>straightening</i></_bq></font> has been
  36535.   implemented. The compiler will optimize branches in the internal code
  36536.    such that a branch from A->B where location B contains a branch to
  36537.    location C, will be optimized to a direct branch from A->C. Even something
  36538.    like A->B->C->D can be straightened to A->D. This often occurs in
  36539.    while-loops that contain if-statements.
  36540.  
  36541. <p>
  36542. <li>
  36543.  <font color="#CC3366"><b>optimization:</b></font>
  36544.  In many cases, variable initialization checks are
  36545.    now replaced by "no-ops" after the first check is performed. Euphoria
  36546.    was already optimizing out many checks at compile-time.
  36547.  
  36548. <p>
  36549. <li>
  36550.  <font color="#CC3366"><b>optimization:</b></font>
  36551.  <font color="#006699"><b>get()</b></font> and
  36552.  <font color="#006699"><b>value()</b></font> are now much faster in most
  36553.   cases thanks to Jiri Babor and some further optimizations by RDS.
  36554.    The new v2.1 <font color="#993333"><b>ex.exe</b></font> with the new
  36555.    v2.1 <font color="#5500FF"><b>get.e</b></font> is:
  36556. <blockquote>
  36557.           <p>
  36558.           1.45x faster reading a sequence of f.p. numbers from a file and<br>
  36559.           2.25x faster when reading a sequence of integers from a file.
  36560. </blockquote>
  36561.  
  36562. <p>
  36563. <li>
  36564.  <font color="#CC3366"><b>optimization:</b></font>
  36565.  <font color="#006699"><b>power(x,2)</b></font> is converted internally
  36566.   to x*x which is faster in all cases, especially when x is a large
  36567.   integer or a f.p. number. 
  36568.  
  36569. <p>
  36570. <li>
  36571.  <font color="#CC3366"><b>optimization:</b></font> Thanks to Jiri Babor,
  36572.  <font color="#006699"><b>int_to_bits()</b></font> is at least 15% faster
  36573.    in most cases.
  36574.  
  36575. <p>
  36576. <li>
  36577.  <font color="#CC3366"><b>optimization:</b></font>
  36578.  Plotting a long sequence of pixels in 16-color graphics modes 
  36579.  is about 3% faster.
  36580.  
  36581. <p>
  36582. <li>
  36583.  <font color="#CC3366"><b>optimization:</b></font>
  36584.  <font color="#006699"><b>draw_line()</b></font> has been sped up by a
  36585.   few percent.
  36586.  
  36587. <p>
  36588. <li>
  36589.  <font color="#5500FF"><b>Language War</b></font> has had a major
  36590.  face-lift. It now runs in <font color="#CC3366"><b>pixel-graphics
  36591.    mode 18</b></font> (640 x 480 x 16 colors) instead of
  36592.    <font color="#CC3366"><b>text mode</b></font>. It also has 
  36593.    <font color="#CC0099"><_bq><i>fine-grain</i></_bq></font> parallelism,
  36594.    i.e. virtually anything can happen in parallel 
  36595.    with anything else. Multiple torpedos, phasors etc can be drawn on the 
  36596.    screen simultaneously, while ships are moving, commands are being entered,
  36597.    things are exploding etc. Even the timing needed for the PC speaker sound 
  36598.    effects is handled by the <b>task scheduler</b>. There are
  36599.    <font color="#CC0099"><b><i>no</i></b></font> time-delay "busy" 
  36600.    loops executed during the game. The galaxy scan now shows you a scaled 
  36601.    picture of the whole galaxy, rather than just a bunch of numbers.
  36602.  
  36603. <p>
  36604. <li>
  36605.  The default print format for atoms was changed from "%g" to "%<b>.</b>10g".
  36606.    This format is used by <font color="#006699">print()</font>,
  36607.    <font color="#006699"><b>?</b></font>,
  36608.    the <font color="#993333"><b>trace</b></font> facility, and
  36609.    <font color="#993333"><b>ex.err</b></font> dumps. This allows large
  36610.    integers -9,999,999,999 to +9,999,999,999
  36611.    to be printed as integers, rather than as scientific notation. It also 
  36612.    provides about 10 digits of accuracy to be displayed on fractional numbers,
  36613.    rather than just 6. Art Adamson and others made it clear that more 
  36614.    digits should be displayed.
  36615.  
  36616. <p>
  36617. <li>
  36618.  The state of all <font color="#993333"><b>with/without</b></font> settings
  36619.   is saved upon entering an <b>included file</b>, and restored at the end
  36620.   of the <b>included file</b>. An included file can change the settings,
  36621.   but they will be restored at the end of the included file. e.g. warnings
  36622.    might be turned off just within the included file (and any files it
  36623.    includes). As a result some 
  36624.    programs now display warnings where none were seen before.
  36625.  
  36626. <p>
  36627. <li>
  36628.  Warnings are now displayed
  36629.  <font color="#CC0099"><_ba><i>after</i></_ba></font> your program finishes
  36630.  execution, so they won't be erased by
  36631.  <font color="#006699">clear_screen()</font>,
  36632.  <font color="#006699">graphics_mode()</font> etc.
  36633.  Some programs now show warnings where none were seen before.
  36634.  
  36635. <p>
  36636. <li>
  36637.  The security of scrambled code and bound code has been improved thanks to 
  36638.  ideas contributed by Rusty Davis. When a bound program starts executing,
  36639.  a quick integrity check will be made to detect any corruption or tampering.
  36640.  It's still ok to add data to the end of a
  36641.  <b><font color="#993333">bound</font> .exe</b> file, as long as
  36642.  your last line is <font color="#006699"><_bq>abort(x)</_bq></font>.
  36643.  
  36644. <p>
  36645. <li>
  36646.  The <font color="#993333"><b>ed</b></font> editor now lets you view and
  36647.  edit beyond column 80.
  36648.  
  36649. <p>
  36650. <li>
  36651.  <font color="#993333"><b>ed</b></font> has a new command: <b>Esc m</b>
  36652.  (modifications). It will show the differences between the original file on
  36653.  disk and the current edit buffer. This can be very useful when you've
  36654.  forgotten what changes you've made, and you are wondering if it's safe to
  36655.  save them.
  36656.  
  36657. <p>
  36658. <li>
  36659.  The <font color="#993333"><b>trace</b></font> window now provides an upper
  36660.  case <b>Q</b> command which lets the program run to completion, ignoring
  36661.  any <font color="#006699">trace(1)</font> commands. Lower case
  36662.  <b>q</b> lets it run to the next <font color="#006699">trace(1)</font>.
  36663.  
  36664. <p>
  36665. <li>
  36666.  <font color="#5500FF"><b>safe.e</b></font> (debug version of
  36667.  <font color="#5500FF"><b>machine.e</b></font>) has been enhanced. It will now 
  36668.    automatically catch additional cases where data is illegally written just 
  36669.    <b><i>before</i></b>, or just <b><i>after</i></b>, the boundaries of an
  36670.    allocated block of memory. This can be particularly useful in
  36671.    <font color="#CC3366"><b>WIN32</b></font> where Windows might overwrite 
  36672.    one of your under-sized blocks. Without a tool such as
  36673.    <font color="#5500FF"><b>safe.e</b></font>, this type 
  36674.    of bug could take hours or even days to track down.
  36675.  
  36676. <p>
  36677. <li>
  36678.  The <font color="#5500FF"><b>euphoria\tutorial</b></font> directory
  36679.  was created to hold several small tutorial programs.
  36680.  
  36681. <p>
  36682. <li>
  36683.  The limit on the number of open files was raised to 25 from 15.
  36684.    Three of these files are 0,1,2: standard-input, standard-output 
  36685.    and standard-error, so you can now have up to 22 of your own files
  36686.    open simultaneously. (As far as we know, no one ever exceeded the old 
  36687.    limit, but it seemed wise to raise it.)
  36688.  
  36689. <p>
  36690. <li>
  36691.  When the user simply types <font color="#993333"><_bq>ex</_bq></font> or
  36692.  <font color="#993333"><_bq>exw</_bq></font> and is prompted for the 
  36693.    name of the Euphoria <b>.ex</b> or <b>.exw</b> file to run,
  36694.    <font color="#006699"><b>command_line()</b></font> will now 
  36695.    be updated to include the filename as the second command-line argument,
  36696.    just as if the user had originally typed: <_bq>ex filename</_bq>.
  36697.    Thanks to Mathew Hounsell for suggesting this.
  36698.  
  36699. <p>
  36700. <li>
  36701.  <font color="#5500FF"><b>mset.ex</b></font> now saves pictures in <b>.bmp</b>
  36702.  format. Previously it was using a non-standard, compressed format.
  36703.  
  36704. <p>
  36705. <li>
  36706.  <font color="#5500FF"><b>lines.ex</b></font>
  36707.  (<font color="#5500FF"><b>lines.bat</b></font>) now reports
  36708.  non-blank/non-comment lines as well. This is
  36709.  <font color="#CC0099"><_ba><i>not</i></_ba></font> the same as the
  36710.  "statement count" used by Euphoria for the diagnostic limit, but it's
  36711.  usually within +/- 10%, assuming you write one statement per line.
  36712.  
  36713. <p>
  36714. <li>
  36715.  Numeric literals greater than 1e308 (roughly) are now set to
  36716.  <b>+/-</b> <_bq>inf</_bq>. They used to cause a compile-time error.
  36717.  
  36718. </ul>
  36719. <hr>
  36720.  
  36721. <p> <br>
  36722.  
  36723. <font face="Arial, Helvetica" color="#003366">
  36724. <b><_dul>Version 2.0 Official Release March 25, 1998:</_dul></b></font>
  36725.  
  36726. <ul>
  36727. <li>
  36728.  The install procedure has changed. The Euphoria .zip file now contains a 
  36729.    large <_bq>bundle.dat</_bq> file that contains over 100 files. This
  36730.    makes it easier for people to locate the important files:
  36731.    <font color="#5500FF"><b>readme.doc</b></font>,
  36732.    <font color="#5500FF"><b>install.bat</b></font>, etc. 
  36733.    that they should look at before installing. The .zip file is also 35K
  36734.    smaller as a result.
  36735.  
  36736. <p>
  36737. <li>
  36738.  <font color="#993333"><b>shroud</b></font> will warn you to use
  36739.  <font color="#993333"><b>bind/bindw</b></font> if you try to create a
  36740.  shrouded source file with a name ending in "<b>.</b>exe".
  36741.  
  36742. </ul>
  36743.  
  36744. <p> <br>
  36745.  
  36746. <font face="Arial, Helvetica" color="#003366">
  36747. <b><_dul>Version 2.0 (beta) February 26, 1998:</_dul></b></font>
  36748.  
  36749. <ul>
  36750. <li>
  36751.  The WIN32 interpreter, <font color="#993333"><b>exw.exe</b></font>, is now
  36752.  a <font color="#006633"><b>true WIN32 GUI</b></font> program. In 
  36753.  2.0 alpha it was a WIN32 <_bq><i>console</i></_bq> program that was always
  36754.  associated with a <_bq><i>console</i></_bq> or DOS-window. A DOS-style
  36755.  console window will now be created only if your program needs one.
  36756.  <font color="#993333"><b>exw</b></font> will automatically create 
  36757.  a new console window the first time your program writes to the screen, reads 
  36758.  from the keyboard, or calls any library routine that requires a console to 
  36759.  work. The console will disappear automatically when your program finishes 
  36760.  execution. 
  36761.  
  36762. <p>
  36763. <li>
  36764.  A new library routine, <font color="#006699"><b>free_console()</b></font>,
  36765.  will immediately delete the console window if you currently have one.
  36766.  
  36767. <p>
  36768. <li>
  36769.  The Complete Edition of Euphoria now provides a
  36770.  <font color="#993333"><b>-scramble</b></font> option of
  36771.  <font color="#993333"><b>bind</b></font> and
  36772.  <font color="#993333"><b>shroud</b></font> to improve the security of
  36773.  programs that you distribute.
  36774.  
  36775. <p>
  36776. <li>
  36777.  You can now pass Euphoria <font color="#993333"><b>atoms</b></font> to
  36778.  C routines as 64-bit C double type floating-point arguments, and you can
  36779.  receive a floating-point result back from a C function.
  36780.  
  36781. <p>
  36782. <li>
  36783.  <font color="#993333"><b>exw.exe (beta)</b></font> runs 10 to 15% faster
  36784.  than <font color="#993333"><b>exw.exe (alpha)</b></font> (based on 
  36785.  <font color="#5500FF"><b>sieve.ex</b></font>,
  36786.  <font color="#5500FF"><b>shell.ex</b></font>, etc.). The WATCOM C compiler
  36787.  was doing a bad job of optimizing a critical section of the interpreter
  36788.  when building exw.exe, but was producing excellent code when building
  36789.  <font color="#993333"><b>ex.exe</b></font>.
  36790.  With some trivial changes to the interpreter C code, WATCOM now produces
  36791.  excellent code for both platforms.
  36792.  
  36793. <p>
  36794. <li>
  36795.  The average program now has 60K more memory available before having to 
  36796.  use the swap file.
  36797.  
  36798. <p>
  36799. <li>
  36800.  The limit on the size of a single procedure, function or type has been 
  36801.  eliminated. 
  36802.  
  36803. <p>
  36804. <li>
  36805.  The limit on the size of a single top-level statement has been eliminated.
  36806.  
  36807. <p>
  36808. <li>
  36809.  The limit on the total number of include files that can make up a program
  36810.    has been increased to 256 from 150.
  36811.  
  36812. <p>
  36813. <li>
  36814.  Some <font color="#CC3366"><b>optimizations</b></font> were added. The
  36815.  following general forms of expression are now faster:
  36816. <_eucode>
  36817.            2 * x 
  36818.            x * 2 
  36819.            1 + x 
  36820. </_eucode>
  36821.      where x can be any expression, and have type atom or sequence.
  36822.  
  36823. <p>
  36824. <li>
  36825.  There is a new documentation file,
  36826.  <font color="#5500FF"><b>perform.doc</b></font> with lots of tips for
  36827.  performance-obsessed programmers.
  36828.  
  36829. <p>
  36830. <li>
  36831.  If you call a C routine using <font color="#006699"><b>c_func()</b></font>,
  36832.  but you linked the C routine using
  36833.  <font color="#006699"><b>define_c_proc()</b></font> you will get an error
  36834.  message. Similarly, if you call it using
  36835.  <font color="#006699"><b>c_proc()</b></font>, but you linked it using
  36836.  <font color="#006699"><b>define_c_func()</b></font> you'll get 
  36837.  an error message. This restriction was documented, but not actually 
  36838.  enforced in 2.0 alpha. Some programs written for the alpha release will 
  36839.  have to be corrected.
  36840.  
  36841. <p>
  36842. <li>
  36843.  You will now see the actual name of the C or Euphoria routine that you
  36844.  were attempting to call, when you get an error message from
  36845.  <font color="#006699"><b>call_proc()</b></font>,
  36846.  <font color="#006699"><b>call_func()</b></font>,
  36847.  <font color="#006699"><b>c_proc()</b></font>,
  36848.  or <font color="#006699"><b>c_func()</b></font>.
  36849.  
  36850. <p>
  36851. <li>
  36852.  A new <b>-clear_routines</b> option of
  36853.   <font color="#993333"><b>bind</b></font> and
  36854.   <font color="#993333"><b>shroud</b></font> will leave the names of
  36855.   all routines unshrouded. This is necessary if your program calls 
  36856.   <font color="#006699"><b>routine_id()</b></font>. You'll be warned if you
  36857.   use routine_id() and do not choose this option. (Registered users can
  36858.   use <font color="#993333"><b>-scramble</b></font> together with
  36859.   <b>-clear_routines</b> to restore a high level of shrouding.)
  36860.  
  36861. <p>
  36862. <li>
  36863.  If a name conflict arises with a global symbol, the
  36864.   <font color="#993333"><b>shrouder</b></font> will now warn you, and then
  36865.   choose a new name. It used to abort with a message.
  36866.  
  36867. <p>
  36868. <li>
  36869.  It is no longer possible to <font color="#993333"><b>trace</b></font>
  36870.  or <font color="#993333"><b>profile</b></font> shrouded code.
  36871.  
  36872. <p>
  36873. <li>
  36874.  A new demo program, <font color="#5500FF"><b>hash.ex</b></font>, was added
  36875.   to <font color="#5500FF"><b>euphoria\demo</b></font>.
  36876.  
  36877. <p>
  36878. <li>
  36879.  <font color="#5500FF"><b>freq.ex</b></font> was moved from
  36880.  <font color="#5500FF"><b>euphoria\bin</b></font> to
  36881.  <font color="#5500FF"><b>euphoria\demo</b></font> and renamed as
  36882.  <font color="#5500FF"><b>tree.ex</b></font>.
  36883.  
  36884. <p>
  36885. <li>
  36886.  A new documentation file, <font color="#5500FF"><b>bind.doc</b></font>
  36887.  describes all the features of <font color="#5500FF"><b>bind.bat</b></font>
  36888.  and <font color="#5500FF"><b>shroud.bat</b></font>. The previous description
  36889.  in <font color="#5500FF"><b>refman.doc</b></font> has been shrunk.
  36890.  
  36891. <p>
  36892. <li>
  36893.  The file <font color="#5500FF"><b>overview.doc</b></font> gives a quick
  36894.  overview of all documentation files.
  36895.  
  36896. <p>
  36897. <li>
  36898.  The description of <font color="#006699"><b>get_mouse()</b></font> in
  36899.  <font color="#5500FF"><b>library.doc</b></font> discusses the problem of
  36900.  320-wide graphics modes (you must divide the x coordinate value by 2).
  36901.  
  36902. </ul>
  36903.  
  36904. <p> <br>
  36905.  
  36906. <font face="Arial, Helvetica" color="#003366">
  36907. <b><_dul>Version 2.0 (alpha) November 5, 1997:</_dul></b></font>
  36908.  
  36909. <ul>
  36910. <li>
  36911.  A <font color="#CC0099"><b><i>new platform</i></b></font> is now supported.
  36912.  <font color="#993333"><b>exw.exe</b></font> will run Euphoria programs using
  36913.  the <font color="#CC3366"><b>WIN32</b></font> (Windows 32-bit) operating
  36914.  system. <font color="#993333"><b>ex.exe</b></font> will run programs
  36915.  using <font color="#CC3366"><b>DOS32</b></font> (extended DOS).
  36916.  See <font color="#5500FF"><b>platform.doc</b></font> for further details.
  36917.  
  36918. <p>
  36919. <li>
  36920.  The following library routines have been introduced.
  36921. <p>
  36922.  <font color="#006633"><_sul><b>For both DOS32 and WIN32:</b></_sul></font>
  36923. <p>
  36924.  <table border=0 cellspacing=2 cellpadding=2>
  36925.  
  36926.  <tr><td width=24 nowrap></td>
  36927.    <td width=120 nowrap></td>
  36928.    <td width=10></td>
  36929.    <td></td>
  36930.    </tr>
  36931.  
  36932.  <_4clist
  36933.    name="<font color=\"#006699\">platform()</font>"
  36934.    pos=25
  36935.    description="find out which platform you are executing on. (The 
  36936.    PLATFORM constant is available in Euphoria 2.2 and later)."
  36937.  >
  36938.  
  36939.  <_4clist
  36940.    name="<font color=\"#006699\">routine_id()</font>"
  36941.    pos=25
  36942.    description="get a small integer id number for a Euphoria procedure or
  36943.     function."
  36944.  >
  36945.  
  36946.  <_4clist
  36947.    name="<font color=\"#006699\">call_proc()</font>"
  36948.    pos=25
  36949.    description="call a Euphoria procedure by using its id."
  36950.  >
  36951.  
  36952.  <_4clist
  36953.    name="<font color=\"#006699\">call_func()</font>"
  36954.    pos=25
  36955.    description="call a Euphoria function by using its id."
  36956.  >
  36957.  
  36958.  <_4clist
  36959.    name="<font color=\"#006699\">custom_sort()</font>"
  36960.    pos=25
  36961.    description="sort a sequence using a compare function that you specify."
  36962.  >
  36963.  
  36964.  <_4clist
  36965.    name="<font color=\"#006699\">poke4()</font>"
  36966.    pos=25
  36967.    description="store a number into 4 bytes of memory.
  36968.      <font color=\"#006699\">poke4(address, value)</font> is at least 10x
  36969.      faster than:
  36970.      <font color=\"#006699\">poke(address, int_to_bytes(value))</font>.
  36971.      poke4() also works with sequences of values."
  36972.  >
  36973.  
  36974.  <_4clist
  36975.    name="<font color=\"#006699\">peek4s()</font>"
  36976.    pos=25
  36977.    description="read 4 bytes of memory as a signed integer (works on
  36978.      sequences too)."
  36979.  >
  36980.  
  36981.  <_4clist
  36982.    name="<font color=\"#006699\">peek4u()</font>"
  36983.    pos=25
  36984.    description="read 4 bytes of memory as an unsigned integer (works on
  36985.      sequences too). <font color=\"#006699\">peek4u(address)</font> is 10x
  36986.      faster than:
  36987.      <font color=\"#006699\">bytes_to_int(peek({address, 4}))</font>."
  36988.  >
  36989.  
  36990.  <_4clist
  36991.    name="<font color=\"#006699\">allocate_string()</font>"
  36992.    pos=25
  36993.    description="allocate and store a 0-terminated string in memory."
  36994.  >
  36995.  
  36996. </table>
  36997.  
  36998. <p>
  36999.  <font color="#006633"><_sul><b>For WIN32 only:</b></_sul></font>
  37000. <p>
  37001.  <table border=0 cellspacing=2 cellpadding=2>
  37002.  
  37003.  <tr><td width=24 nowrap></td>
  37004.    <td width=120 nowrap></td>
  37005.    <td width=10></td>
  37006.    <td></td>
  37007.    </tr>
  37008.  
  37009.  <_4clist
  37010.    name="<font color=\"#006699\">open_dll()</font>"
  37011.    pos=26
  37012.    description="open a Windows <b>.</b>dll file."
  37013.  >
  37014.  
  37015.  <_4clist
  37016.    name="<font color=\"#006699\">define_c_proc()</font>"
  37017.    pos=26
  37018.    description="define a C routine that will be called from Euphoria
  37019.      (no value returned)."
  37020.  >
  37021.  
  37022.  <_4clist
  37023.    name="<font color=\"#006699\">define_c_func()</font>"
  37024.    pos=26
  37025.    description="define a C routine that will be called from Euphoria
  37026.      (a value will be returned)."
  37027.  >
  37028.  
  37029.  <_4clist
  37030.    name="<font color=\"#006699\">call_c_proc()</font>"
  37031.    pos=26
  37032.    description="call a C routine from Euphoria (no value is returned)."
  37033.  >
  37034.  
  37035.  <_4clist
  37036.    name="<font color=\"#006699\">call_c_func()</font>"
  37037.    pos=26
  37038.    description="call a C routine from Euphoria (a value is returned)."
  37039.  >
  37040.  
  37041.  <_4clist
  37042.    name="<font color=\"#006699\">call_back()</font>"
  37043.    pos=26
  37044.    description="get a <b><i>call-back address</i></b>, so Windows can call
  37045.      your Euphoria routine when the user interacts with your window."
  37046.  >
  37047.  
  37048.  <_4clist
  37049.    name="<font color=\"#006699\">message_box()</font>"
  37050.    pos=26
  37051.    description="display a simple <b>Yes/No/Cancel</b> window."
  37052.  >
  37053.  
  37054. </table>
  37055.  
  37056. <p>
  37057. <li>
  37058.  New Demo programs:
  37059.  
  37060. <ul>
  37061. <p><li>
  37062. <font color="#5500FF"><b>csort.ex</b></font>
  37063. <p><li>
  37064. <font color="#5500FF"><b>email.exw</b></font>
  37065. <p><li>
  37066. <font color="#5500FF"><b>window.exw</b></font>
  37067. <p><li>
  37068. <font color="#5500FF"><b>winwire.exw</b></font>
  37069. <p><li>
  37070. <font color="#5500FF"><b>dsearch.exw</b></font>
  37071. </ul>
  37072.  
  37073. <p>
  37074. <li>
  37075.  New include files:
  37076. <p>
  37077.  <table border=0 cellspacing=2 cellpadding=2>
  37078.  
  37079.  <_4clist
  37080.    name="<font color=\"#5500FF\">safe.e</font>"
  37081.    pos=22
  37082.    description="debug version of
  37083.     <font color=\"#5500FF\"><b>machine.e</b></font>"
  37084.  >
  37085.  
  37086.  <_4clist
  37087.    name="<font color=\"#5500FF\">misc.e</font>"
  37088.    pos=22
  37089.    description="miscellaneous"
  37090.  >
  37091.  
  37092.  <_4clist
  37093.    name="<font color=\"#5500FF\">dll.e</font>"
  37094.    pos=22
  37095.    description="dll access"
  37096.  >
  37097.  
  37098.  <_4clist
  37099.    name="<font color=\"#5500FF\">msgbox.e</font>"
  37100.    pos=22
  37101.    description="Windows message box"
  37102.  >
  37103.  
  37104. </table>
  37105.  
  37106. <p>
  37107. <li>
  37108.  The following additional improvements have been made to the
  37109.   <font color="#CC3366"><b>DOS32</b></font> version:
  37110.  
  37111. <ul>
  37112. <p><li>
  37113.     On Pentium and higher systems, floating-point calculations are now
  37114.     about 20% faster (and floating-point in
  37115.     <font color="#993333"><b>exw</b></font> is a further 20%
  37116.     faster than <font color="#993333"><b>ex</b></font> for 2.0).
  37117.  
  37118. <p><li>
  37119.     <font color="#006699"><b>printf()</b></font> to the screen, and
  37120.     <font color="#006699"><b>print()</b></font> to the screen are both 
  37121.     significantly faster in most cases.
  37122.  
  37123. <p><li>
  37124.     The <font color="#993333"><b>trace</b></font> screen is updated a bit
  37125.     faster.
  37126.  
  37127. <p><li>
  37128.     The <font color="#993333"><b>time profile</b></font> is more accurate
  37129.     regarding <font color="#006699"><b>getc()</b></font>.
  37130.  
  37131. <p><li>
  37132.     The <font color="#5500FF"><b>mset.ex</b></font> demo runs 30% faster.
  37133. </ul>
  37134.  
  37135. </ul>
  37136.  
  37137. <hr>
  37138.  
  37139. <p> 
  37140.  
  37141. <_center><font face="Arial, Helvetica" color="#006633"><b>
  37142. <br>
  37143.                       Highlights of Older Releases:<br>
  37144. </b></font></_center>
  37145.  
  37146. <p> <br>
  37147.  
  37148. <font face="Arial, Helvetica" color="#003366">
  37149. <b><_dul>Version 1.5a June 13, 1997:</_dul></b></font>
  37150.  
  37151. <ul>
  37152. <li>
  37153.  Many operations and library routines were optimized. 
  37154.  
  37155. <ul>
  37156. <p><li>
  37157.    <font color="#006699"><b>get_key()</b></font> is
  37158.    100x faster when there is no key in the buffer.
  37159.  
  37160. <p><li>
  37161.    <font color="#006699"><b>get_all_palette()</b></font> is over 100x faster
  37162.    and this makes <font color="#006699"><b>save_screen()</b></font> much faster.
  37163.  
  37164. <p><li>
  37165.    The following routines have now been built directly into
  37166.    <font color="#993333"><b>ex.exe</b></font>, to avoid the overhead of
  37167.    calling <font color="#006699">machine_proc()</font> or
  37168.    <font color="#006699">machine_func()</font>:
  37169.    <font color="#006699"><b>pixel()</b></font>, 
  37170.    <font color="#006699"><b>get_pixel()</b></font>,
  37171.    <font color="#006699"><b>mem_set()</b></font>,
  37172.    <font color="#006699"><b>mem_copy()</b></font>.
  37173.  
  37174. <p><li>
  37175.    <font color="#006699"><b>poke()</b></font> of a long sequence into memory,
  37176.    other than video memory, is 50% faster.
  37177.  
  37178. <p><li>
  37179.    <font color="#006699"><b>pixel()</b></font> is 4x faster in mode 19.
  37180.  
  37181. <p><li>
  37182.    <font color="#006699"><b>get_pixel()</b></font> is faster in all modes.
  37183.  
  37184. <p><li>
  37185.    <font color="#006699"><b>display_image()</b></font> is about 30% faster in
  37186.    most modes and up to 4x faster in mode 19, 
  37187.    because <br><font color="#006699">pixel()</font> is faster.
  37188.  
  37189. <p><li>
  37190.    All arithmetic and bitwise operations applied to sequences of integers are 
  37191.    now 29% faster.  
  37192.  
  37193. <p><li>
  37194.    a <font color="#993333"><b>&</b></font> b (concatenation) is 15% faster
  37195.    in most cases, and is dramatically faster in the case where you grow a
  37196.    very long sequence by concatenating many small sequences onto it. 
  37197.  
  37198. <p><li>
  37199.    <font color="#006699"><b>getc()</b></font> is 12% faster.
  37200.  
  37201. <p><li>
  37202.    <font color="#006699"><b>match()</b></font> is 8% faster in typical cases.
  37203.  
  37204. <p><li>
  37205.    <font color="#006699"><b>append()/prepend()</b></font> are 15% faster in
  37206.    many cases.
  37207.  
  37208. <p><li>
  37209.    <font color="#006699"><b>find()</b></font> of an integer within a
  37210.    sequence of integers is 64% faster.
  37211.  
  37212. <p><li>
  37213.    Formation of a 2-element sequence <b>{a,b}</b> is 11% faster.
  37214.  
  37215. <p><li>
  37216.    Internal copying of a shared sequence when it can no longer be shared is
  37217.    15% faster.
  37218. </ul>
  37219.  
  37220. </ul>
  37221.  
  37222. <p> <br>
  37223.  
  37224. <font face="Arial, Helvetica" color="#003366">
  37225. <b><_dul>Version 1.5 March 21, 1997:</_dul></b></font>
  37226.  
  37227. <ul>
  37228. <li>
  37229.  The following library routines were added. They are described fully
  37230.    in <font color="#5500FF"><b>library.doc</b></font>.
  37231.  
  37232. <ul>
  37233. <p><li>
  37234.         <font color="#006699"><b>allow_break()</b></font>
  37235. <p><li>
  37236.         <font color="#006699"><b>check_break()</b></font>
  37237. <p><li>
  37238.         <font color="#006699"><b>mem_copy()</b></font>
  37239. <p><li>
  37240.         <font color="#006699"><b>mem_set()</b></font>
  37241. <p><li>
  37242.         <font color="#006699"><b>atom_to_float32()</b></font>
  37243. <p><li>
  37244.         <font color="#006699"><b>atom_to_float64()</b></font>
  37245. <p><li>
  37246.         <font color="#006699"><b>float32_to_atom()</b></font>
  37247. <p><li>
  37248.         <font color="#006699"><b>float64_to_atom()</b></font>
  37249. <p><li>
  37250.         <font color="#006699"><b>get_all_palette()</b></font>
  37251. <p><li>
  37252.         <font color="#006699"><b>save_bitmap()</b></font>
  37253. <p><li>
  37254.         <font color="#006699"><b>save_screen()</b></font>
  37255. <p><li>
  37256.         <font color="#006699"><b>arctan()</b></font>
  37257. <p><li>
  37258.         <font color="#006699"><b>and_bits()</b></font>
  37259. <p><li>
  37260.         <font color="#006699"><b>or_bits()</b></font>
  37261. <p><li>
  37262.         <font color="#006699"><b>xor_bits()</b></font>
  37263. <p><li>
  37264.         <font color="#006699"><b>not_bits()</b></font>
  37265. <p><li>
  37266.     <font color="#006699"><b>get_vector()</b></font>
  37267. <p><li>
  37268.     <font color="#006699"><b>set_vector()</b></font>
  37269. <p><li>
  37270.     <font color="#006699"><b>lock_memory()</b></font>
  37271. <p><li>
  37272.     <font color="#006699"><b>tick_rate()</b></font>
  37273. </ul>
  37274.  
  37275. <p>
  37276. <li>
  37277.  <font color="#993333"><b>with profile_time</b></font> (time profiling for
  37278.  DOS32) was added.
  37279.  
  37280. </ul>
  37281.  
  37282. <p> <br>
  37283.  
  37284. <font face="Arial, Helvetica" color="#003366">
  37285. <b><_dul>Version 1.4b, October 1996:</_dul></b></font>
  37286.  
  37287. <ul>
  37288. <li>
  37289.  <font color="#5500FF"><b>mset.ex</b></font> has a more visible selector
  37290.  box on it's grid. It has also been sped up.
  37291.  
  37292. <p>
  37293. <li>
  37294.  <font color="#5500FF"><b>ed.ex</b></font> now allows special characters
  37295.  greater than ASCII 127 to be entered by pressing the <b>Alt</b> key and
  37296.  typing digits on the numeric keypad.
  37297.  
  37298. </ul>
  37299.  
  37300. <p> <br>
  37301.  
  37302. <font face="Arial, Helvetica" color="#003366">
  37303. <b><_dul>Version 1.4a, July 1996:</_dul></b></font>
  37304.  
  37305. <ul>
  37306. <li>
  37307.  <font color="#006699"><b>crash_message()</b></font> library routine was
  37308.  added.
  37309.  
  37310. <p>
  37311. <li>
  37312.  Programs <font color="#993333"><b>bound</b></font> by registered users
  37313.  will now produce run-time error diagnostics regardless of the size of the
  37314.  program.
  37315.  
  37316. <p>
  37317. <li>
  37318.  <font color="#5500FF"><b>shroud.bat</b></font> has a new option
  37319.  <_bq>-full_keywords</_bq>.
  37320.  
  37321. </ul>
  37322.  
  37323. <p> <br>
  37324.  
  37325. <font face="Arial, Helvetica" color="#003366">
  37326. <b><_dul>Version 1.4, May 1996:</_dul></b></font>
  37327.  
  37328. <ul>
  37329. <li>
  37330.  You can now convert any Euphoria program into a
  37331.  <font color="#CC0099"><b>stand-alone .exe</b></font> file.
  37332.  
  37333. <p>
  37334. <li>
  37335.  The separate DOS4GW.EXE DOS extender file has been eliminated. 
  37336.  
  37337. <p>
  37338. <li>
  37339.  Windows 95 long filename support.
  37340.  
  37341. <p>
  37342. <li>
  37343.  Support for DOS software interrupts.
  37344.  
  37345. <p>
  37346. <li>
  37347.  New utility programs: <font color="#5500FF"><b>key.ex</b></font>,
  37348.  <font color="#5500FF"><b>where.ex</b></font>,
  37349.  <font color="#5500FF"><b>ascii.ex</b></font>,
  37350.  <font color="#5500FF"><b>guru.ex</b></font>.
  37351.  
  37352. <p>
  37353. <li>
  37354.  New demo program: <font color="#5500FF"><b>dosint.ex</b></font>.
  37355.  
  37356. <p>
  37357. <li>
  37358.  New library routines: <font color="#006699"><b>set_rand()</b></font>,
  37359.  <font color="#006699"><b>use_vesa()</b></font>.
  37360.  
  37361. <p>
  37362. <li>
  37363.  You can peek or poke an entire sequence of bytes.
  37364.  
  37365. <p>
  37366. <li>
  37367.  Editor enhancements.
  37368.  
  37369. <p>
  37370. <li>
  37371.  Reduction in space overhead for sequences.
  37372.  
  37373. </ul>
  37374.  
  37375. <p> <br>
  37376.  
  37377. <font face="Arial, Helvetica" color="#003366">
  37378. <b><_dul>Version 1.3, June 1995:</_dul></b></font>
  37379.  
  37380. <ul>
  37381. <li>
  37382.  You can now edit multiple files using multiple edit windows. 
  37383.  
  37384. <p>
  37385. <li>
  37386.  20 new library routines were added.
  37387.  
  37388. <p>
  37389. <li>
  37390.  Graphics performance was greatly improved.
  37391.  
  37392. </ul>
  37393.  
  37394. <p> <br>
  37395.  
  37396. <font face="Arial, Helvetica" color="#003366">
  37397. <b><_dul>Version 1.2, March 1994:</_dul></b></font>
  37398.  
  37399. <ul>
  37400. <li>
  37401.   A problem that prevented Euphoria from running in a DOS prompt under 
  37402.   Windows was eliminated.
  37403.  
  37404. </ul>
  37405.  
  37406. <p> <br>
  37407.  
  37408. <font face="Arial, Helvetica" color="#003366">
  37409. <b><_dul>Version 1.1, January 1994:</_dul></b></font>
  37410.  
  37411. <ul>
  37412. <li>
  37413.   Several language features and demo programs were added.
  37414.  
  37415. </ul>
  37416.  
  37417. <p> <br>
  37418.  
  37419. <font face="Arial, Helvetica" color="#003366">
  37420. <b><_dul>Version 1.0, July 1993:</_dul></b></font>
  37421.  
  37422. <ul>
  37423. <li>
  37424.   Euphoria was first released after 3 years of research and development
  37425.   and 6 months of Beta testing. Many of the ideas behind Euphoria came
  37426.   from Robert Craig's Master's Thesis in Computer Science at the University
  37427.   of Toronto. That thesis was strongly influenced by the work of John Backus
  37428.   on functional programming (FP) languages.
  37429.  
  37430. </ul>
  37431.  
  37432. <p> 
  37433.  
  37434. </_width>
  37435. </body>
  37436. </html>
  37437. TEXT.E
  37438. 12014
  37439. constant WIDTH = 80, UL_INDENT = 7, DL_INDENT = 7, BLQ_INDENT = 4
  37440. constant NOT_IN_DL = 0, FIRST_DL_LEVEL = 1, FIRST_UL_LEVEL = 1
  37441. integer in_ampersand, in_whitespace
  37442. integer inTitle, inCenter, ulLevel
  37443. integer dlLevel
  37444. integer dulFound, sulFound, dulStart, dulEnd, sulStart, sulEnd
  37445. integer column, indent, rememberIndent
  37446. integer rememberPos, firstEucodeLine 
  37447. sequence word, line           
  37448. function delete_trailing_white(sequence text)
  37449. while length(text) > 0 and whitespace(text[length(text)]) do
  37450. text = text[1..length(text)-1]
  37451. end while
  37452. return text
  37453. end function
  37454. procedure underline()
  37455. if dulFound and sulFound then
  37456. if dulStart < sulStart then
  37457. write(repeat(' ', dulStart - 1) & 
  37458. repeat('=', dulEnd - dulStart + 1) &
  37459. repeat(' ', sulStart - dulEnd - 1) &
  37460. repeat('-', sulEnd - sulStart + 1))
  37461. else
  37462. write(repeat(' ', sulStart - 1) & 
  37463. repeat('=', sulEnd - sulStart + 1) &
  37464. repeat(' ', dulStart - sulEnd - 1) &
  37465. repeat('-', dulEnd - dulStart + 1))
  37466. end if
  37467. write('\n')
  37468. dulFound = FALSE
  37469. sulFound = FALSE
  37470. elsif dulFound then
  37471. write(repeat(' ', dulStart - 1) & 
  37472. repeat('=', dulEnd - dulStart + 1))
  37473. write('\n')
  37474. dulFound = FALSE
  37475. elsif sulFound then
  37476. write(repeat(' ', sulStart - 1) &
  37477. repeat('-', sulEnd - sulStart + 1))
  37478. write('\n')
  37479. sulFound = FALSE
  37480. end if
  37481. end procedure
  37482. procedure resetLineAndWord()
  37483. line = repeat(' ', indent - 1)
  37484. column = indent
  37485. word = ""
  37486. in_whitespace = TRUE 
  37487. end procedure
  37488. procedure getReadyNewLine()
  37489. write(delete_trailing_white(line) & '\n')
  37490. underline()
  37491. line = repeat(' ', indent - 1)
  37492. column = indent
  37493. in_whitespace = TRUE 
  37494. end procedure
  37495. procedure writeText(sequence text)
  37496. integer len
  37497. len = length(word)
  37498. if column + len > WIDTH then
  37499. getReadyNewLine()
  37500. end if
  37501. line &= word
  37502. column += len
  37503. word = ""
  37504. for i = 1 to length(text) do
  37505. line &= text[i]
  37506. column += 1
  37507. if text[i] = '\n' then
  37508. getReadyNewLine()
  37509. end if
  37510. end for
  37511. end procedure
  37512. procedure tag_literal(integer raw_text, sequence param_list)
  37513. if inTitle then      
  37514. return
  37515. end if
  37516. if inPre or (inEuCode and not inTable) then
  37517. write(raw_text)
  37518. return
  37519. end if
  37520. if inEuCode then      
  37521. if raw_text = '\n' then
  37522. if firstEucodeLine and all_white(line) then
  37523. firstEucodeLine = FALSE
  37524. write(repeat(' ', rememberPos - 1))
  37525. else
  37526. write("\n" & repeat(' ', rememberPos - 1))
  37527. end if
  37528. else 
  37529. write(raw_text)
  37530. end if      
  37531. return
  37532. end if
  37533. if whitespace(raw_text) then
  37534. raw_text = ' '
  37535. end if
  37536. if inCenter then
  37537. write(raw_text)
  37538. return
  37539. end if
  37540. if in_ampersand then 
  37541. if whitespace(raw_text) or raw_text = '\'' then
  37542. in_ampersand = FALSE
  37543. writeText({raw_text})
  37544. if whitespace(raw_text) then
  37545. in_whitespace = TRUE
  37546. end if
  37547. elsif raw_text = ';' then
  37548. in_ampersand = FALSE
  37549. word = " "
  37550. writeText("")
  37551. else
  37552. word &= raw_text
  37553. end if
  37554. return
  37555. elsif raw_text = '&' then
  37556. in_ampersand = TRUE
  37557. writeText("")
  37558. word = "&"
  37559. return
  37560. end if
  37561. if whitespace(raw_text) then
  37562. if in_whitespace then
  37563. return
  37564. end if
  37565. in_whitespace = TRUE
  37566. writeText({raw_text})
  37567. else
  37568. in_whitespace = FALSE
  37569. word &= raw_text
  37570. end if
  37571. end procedure
  37572. procedure tag_dul(sequence raw_text, sequence param_list)
  37573. dulFound = TRUE
  37574. dulStart = column
  37575. end procedure
  37576. procedure tag_end_dul(sequence raw_text, sequence param_list)
  37577. writeText("")
  37578. dulEnd   = column - 1
  37579. end procedure
  37580. procedure tag_sul(sequence raw_text, sequence param_list)
  37581. sulFound = TRUE
  37582. sulStart = column
  37583. end procedure
  37584. procedure tag_end_sul(sequence raw_text, sequence param_list)
  37585. writeText("")
  37586. sulEnd = column - 1
  37587. end procedure
  37588. procedure tag_comment(sequence raw_text, sequence param_list)
  37589. end procedure
  37590. procedure tag_default(sequence raw_text, sequence param_list)
  37591. end procedure
  37592. procedure outputString(sequence str)
  37593. integer firstCharFound, i
  37594. sequence tempStr
  37595. firstCharFound = FALSE
  37596. i = 1
  37597. while i <= length(str) do
  37598. if str[i] = '<' then 
  37599. if str[i + 1] != '=' and not whitespace(str[i + 1]) then
  37600. tempStr = "<"
  37601. i += 1
  37602. while i <= length(str) and str[i] != '>' do
  37603. tempStr &= str[i]
  37604. i += 1
  37605. end while
  37606. if i > length(str) then
  37607. quit("closing '>'for a tag is missing inside <_Nclist> tag")
  37608. else
  37609. i += 1
  37610. end if
  37611. tempStr = lower(tempStr)
  37612. if equal(tempStr, "<p") then
  37613. if column = indent then
  37614. writeText("\n")
  37615. else
  37616. writeText("\n\n")
  37617. end if
  37618. firstCharFound = FALSE
  37619. elsif equal(tempStr, "<br") then
  37620. writeText("\n")
  37621. firstCharFound = FALSE
  37622. end if
  37623. else
  37624. word &= str[i]
  37625. i += 1
  37626. firstCharFound = TRUE
  37627. end if
  37628. elsif whitespace(str[i]) then
  37629. if firstCharFound then
  37630. writeText(" ")
  37631. end if
  37632. while i <= length(str) and whitespace(str[i]) do
  37633. i += 1
  37634. end while
  37635. else
  37636. word &= str[i]
  37637. i += 1
  37638. firstCharFound = TRUE
  37639. end if
  37640. end while
  37641. end procedure
  37642. procedure tag_rowEntry(sequence raw_text, sequence param_list, 
  37643. sequence str, integer colnum)
  37644. object s
  37645. integer j
  37646. if all_white(line) then
  37647. resetLineAndWord()
  37648. else
  37649. writeText("\n")
  37650. end if
  37651. outputString(pval("name", param_list))
  37652. writeText("")
  37653. s = pval("pos", param_list)
  37654. if atom(s) then
  37655. rememberPos = colnum
  37656. else
  37657. s = value(s)
  37658. if s[1] != GET_SUCCESS then
  37659. quit("invalid pos information in <_Nclist>, where N is 2 to 4")
  37660. end if
  37661. rememberPos = s[2]
  37662. end if
  37663. if rememberPos < column + length(str) then
  37664. rememberPos = column + length(str)
  37665. end if
  37666. writeText(repeat(' ', rememberPos - length(str) - column) & str)
  37667. j = indent
  37668. indent = rememberPos
  37669. outputString(pval("description", param_list))
  37670. writeText("\n")
  37671. indent = j
  37672. writeText("\n")
  37673. end procedure
  37674. procedure tag_4clist(sequence raw_text, sequence param_list)
  37675. object temp
  37676. temp = pval("col3", param_list)
  37677. if atom(temp) then
  37678. tag_rowEntry(raw_text, param_list, "- ", 20)
  37679. else
  37680. tag_rowEntry(raw_text, param_list, temp, 20)
  37681. end if
  37682. end procedure
  37683. procedure tag_3clist(sequence raw_text, sequence param_list)
  37684. tag_rowEntry(raw_text, param_list, "- ", 20)
  37685. end procedure
  37686. procedure tag_2clist(sequence raw_text, sequence param_list)
  37687. tag_rowEntry(raw_text, param_list, " ", 15)
  37688. end procedure
  37689. procedure tag_routine(sequence raw_text, sequence param_list)
  37690. sequence name       
  37691. integer len1, len2, j
  37692. name = pval("name", param_list)
  37693. len1 = length(name) + 2 + 1  
  37694. len2 = floor((WIDTH - len1) / 2)
  37695. j = indent
  37696. indent = 2
  37697. writeText("\n")
  37698. writeText(repeat('─', len2) & "<" & name & ">" & 
  37699. repeat('─', WIDTH - len2 - len1))
  37700. indent = j
  37701. writeText("\n")
  37702. end procedure
  37703. procedure tag_table(sequence raw_text, sequence param_list)
  37704. inTable = TRUE
  37705. end procedure
  37706. procedure tag_end_table(sequence raw_text, sequence param_list)
  37707. inTable = FALSE
  37708. end procedure
  37709. procedure tag_p(sequence raw_text, sequence param_list)
  37710. if column = indent then
  37711. writeText("\n")
  37712. else
  37713. writeText("\n\n")
  37714. end if
  37715. end procedure
  37716. procedure tag_br(sequence raw_text, sequence param_list)
  37717. writeText("\n")
  37718. end procedure
  37719. procedure tag_pre(sequence raw_text, sequence param_list)
  37720. writeText("\n")
  37721. inPre = TRUE
  37722. end procedure
  37723. procedure tag_end_pre(sequence raw_text, sequence param_list)
  37724. inPre = FALSE
  37725. getReadyNewLine()
  37726. end procedure
  37727. procedure tag_eucode(sequence raw_text, sequence param_list)
  37728. if inTable and all_white(line)then
  37729. resetLineAndWord()
  37730. firstEucodeLine = TRUE
  37731. else
  37732. writeText("\n")
  37733. end if
  37734. inEuCode = TRUE
  37735. end procedure
  37736. procedure tag_end_eucode(sequence raw_text, sequence param_list)
  37737. inEuCode = FALSE
  37738. getReadyNewLine()
  37739. end procedure
  37740. procedure tag_title(sequence raw_text, sequence param_list)
  37741. inTitle = TRUE
  37742. end procedure
  37743. procedure tag_end_title(sequence raw_text, sequence param_list)
  37744. inTitle = FALSE
  37745. end procedure
  37746. procedure tag_center(sequence raw_text, sequence param_list)
  37747. inCenter = TRUE
  37748. write("\n")
  37749. end procedure
  37750. procedure tag_end_center(sequence raw_text, sequence param_list)
  37751. inCenter = FALSE
  37752. getReadyNewLine()
  37753. end procedure
  37754. procedure tag_ul(sequence raw_text, sequence param_list)
  37755. ulLevel += 1
  37756. indent += UL_INDENT
  37757. if ulLevel = FIRST_UL_LEVEL then
  37758. writeText("\n\n")
  37759. else
  37760. writeText("\n")
  37761. end if
  37762. end procedure
  37763. procedure tag_end_ul(sequence raw_text, sequence param_list)
  37764. writeText("") 
  37765. ulLevel -= 1
  37766. indent -= UL_INDENT
  37767. getReadyNewLine()
  37768. end procedure
  37769. procedure tag_li(sequence raw_text, sequence param_list)
  37770. indent -= 2
  37771. if all_white(line) then
  37772. resetLineAndWord()
  37773. writeText("* ")
  37774. else
  37775. writeText("\n* ")
  37776. end if
  37777. indent += 2
  37778. in_whitespace = TRUE
  37779. end procedure
  37780. procedure tag_dl(sequence raw_text, sequence param_list)
  37781. writeText("")
  37782. dlLevel += 1
  37783. if dlLevel = FIRST_DL_LEVEL then
  37784. rememberIndent = indent
  37785. getReadyNewLine()
  37786. end if
  37787. end procedure
  37788. procedure tag_end_dl(sequence raw_text, sequence param_list)
  37789. writeText("")
  37790. dlLevel -= 1
  37791. if dlLevel = NOT_IN_DL then
  37792. indent = rememberIndent
  37793. writeText("\n\n")
  37794. end if
  37795. end procedure
  37796. procedure tag_dt(sequence raw_text, sequence param_list)
  37797. writeText("")
  37798. indent = rememberIndent + (dlLevel - FIRST_DL_LEVEL) * DL_INDENT
  37799. getReadyNewLine()
  37800. end procedure
  37801. procedure tag_dd(sequence raw_text, sequence param_list)
  37802. writeText("")
  37803. indent = rememberIndent + (dlLevel - FIRST_DL_LEVEL) * DL_INDENT 
  37804. + DL_INDENT
  37805. getReadyNewLine()
  37806. end procedure
  37807. procedure tag_bq(sequence raw_text, sequence param_list)
  37808. tag_literal('"', "")
  37809. end procedure
  37810. procedure tag_end_bq(sequence raw_text, sequence param_list)
  37811. tag_literal('"', "")
  37812. end procedure
  37813. procedure tag_bsq(sequence raw_text, sequence param_list)
  37814. tag_literal('\'', "")
  37815. end procedure
  37816. procedure tag_end_bsq(sequence raw_text, sequence param_list)
  37817. tag_literal('\'', "")
  37818. end procedure
  37819. procedure tag_ba(sequence raw_text, sequence param_list)
  37820. tag_literal('*', "")
  37821. end procedure
  37822. procedure tag_end_ba(sequence raw_text, sequence param_list)
  37823. tag_literal('*', "")
  37824. end procedure
  37825. procedure tag_blockquote(sequence raw_text, sequence param_list)
  37826. indent += BLQ_INDENT
  37827. getReadyNewLine()
  37828. end procedure
  37829. procedure tag_end_blockquote(sequence raw_text, sequence param_list)
  37830. indent -= BLQ_INDENT
  37831. getReadyNewLine()
  37832. end procedure
  37833. global procedure text_init()
  37834. add_handler("!--",      routine_id("tag_comment"))
  37835. add_handler("title",    routine_id("tag_title"))
  37836. add_handler("/title",   routine_id("tag_end_title"))
  37837. add_handler("blockquote",  routine_id("tag_blockquote"))
  37838. add_handler("/blockquote", routine_id("tag_end_blockquote"))
  37839. add_handler("pre",      routine_id("tag_pre"))
  37840. add_handler("/pre",     routine_id("tag_end_pre"))
  37841. add_handler("_center",  routine_id("tag_center"))
  37842. add_handler("/_center", routine_id("tag_end_center"))
  37843. add_handler("_bsq",     routine_id("tag_bsq"))
  37844. add_handler("/_bsq",    routine_id("tag_end_bsq"))
  37845. add_handler("_dul",     routine_id("tag_dul"))
  37846. add_handler("/_dul",    routine_id("tag_end_dul"))
  37847. add_handler("_sul",     routine_id("tag_sul"))
  37848. add_handler("/_sul",    routine_id("tag_end_sul"))
  37849. add_handler("_routine", routine_id("tag_routine"))
  37850. add_handler("br",       routine_id("tag_br"))
  37851. add_handler("_ba",      routine_id("tag_ba"))
  37852. add_handler("/_ba",     routine_id("tag_end_ba"))
  37853. add_handler("_bq",      routine_id("tag_bq"))
  37854. add_handler("/_bq",     routine_id("tag_end_bq"))
  37855. add_handler("dl",       routine_id("tag_dl"))
  37856. add_handler("/dl",      routine_id("tag_end_dl"))
  37857. add_handler("dt",       routine_id("tag_dt"))
  37858. add_handler("dd",       routine_id("tag_dd"))
  37859. add_handler("table",    routine_id("tag_table"))
  37860. add_handler("/table",   routine_id("tag_end_table"))
  37861. add_handler("ul",       routine_id("tag_ul"))
  37862. add_handler("/ul",      routine_id("tag_end_ul"))
  37863. add_handler("li",       routine_id("tag_li"))
  37864. add_handler("_eucode",  routine_id("tag_eucode"))
  37865. add_handler("/_eucode", routine_id("tag_end_eucode"))
  37866. add_handler("_4clist",  routine_id("tag_4clist"))
  37867. add_handler("_3clist",  routine_id("tag_3clist"))
  37868. add_handler("_2clist",  routine_id("tag_2clist"))
  37869. add_handler("p",        routine_id("tag_p"))
  37870. add_handler("_default", routine_id("tag_default"))
  37871. add_handler("_literal", routine_id("tag_literal"))
  37872. out_type = "doc"
  37873. in_ampersand  = FALSE
  37874. in_whitespace = TRUE
  37875. inTitle       = FALSE
  37876. inCenter      = FALSE
  37877. ulLevel       = 0
  37878. dlLevel       = NOT_IN_DL
  37879. dulFound      = FALSE
  37880. sulFound      = FALSE
  37881. indent = 2
  37882. column = indent
  37883. word = ""
  37884. line = " "
  37885. end procedure
  37886. global procedure text_end()
  37887. writeText("\n\n")
  37888. end procedure
  37889. TROUBLE.HTX
  37890. 20237
  37891. <_init_comment>
  37892. <html>
  37893. <head><title>Euphoria Trouble-Shooting Guide</title>
  37894. </head>
  37895. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  37896. <_width>
  37897. <_center><font face="Arial, Helvetica" color="#FF0099" size=+2>
  37898. <br>
  37899.                     Euphoria Trouble-Shooting Guide
  37900. </font></_center>
  37901. <p> <br>
  37902. <font face="Arial, Helvetica" color="#003366">
  37903. <b><_sul>If you get stuck, here are some things you can do:</_sul></b></font>
  37904. <p>
  37905.  <table border=0 cellspacing=2 cellpadding=2>
  37906.  
  37907. <_4clist
  37908.   name="1."
  37909.   pos=10
  37910.   description="Type: <font color=\"#993333\"><b>guru</b></font><br>
  37911.    followed by some keywords associated with your problem.
  37912.    <p>
  37913.    For example,<br>
  37914.    <b>guru declare global include</b>"
  37915. >
  37916.  
  37917. <_4clist
  37918.   name="2."
  37919.   pos=10
  37920.   description="Check the list of common problems
  37921.    (<a href=\"trouble.htm#commonp\">below</a>)."
  37922. >
  37923.  
  37924. <_4clist
  37925.   name="3."
  37926.   pos=10
  37927.   description="Read the relevant parts of the documentation, i.e.
  37928.   <a href=\"refman.htm\"><font color=\"#5500FF\"><b>refman.doc</b></font></a>
  37929.   or
  37930. <a href=\"library.htm\"><font color=\"#5500FF\"><b>library.doc</b></font></a>."
  37931. >
  37932.  
  37933. <_4clist
  37934.   name="4."
  37935.   pos=10
  37936.   description="Try running your program with the statements:"
  37937. >
  37938. <_eucode>
  37939.         with trace
  37940.         trace(1)
  37941. </_eucode>
  37942.  
  37943. <_4clist
  37944.   col3=""
  37945.   name=""
  37946.   pos=10
  37947.   description="at the top of your main <b>.ex</b> file so you can see
  37948.    what's going on."
  37949. >
  37950.  
  37951. <_4clist
  37952.   name="5."
  37953.   pos=10
  37954.   description="The Web interface to the Euphoria <b>mailing list</b></a> has
  37955.    a search facility. You can search the archive of all previous messages.
  37956.    There's a good chance that your question has already been discussed.
  37957.    The mailing list is discussed in
  37958.    <a href=\"web.htm\"><font color=\"#5500FF\"><b>web.doc</b></font></a>."
  37959. >
  37960.  
  37961. <_4clist
  37962.   name="6."
  37963.   pos=10
  37964.   description="Post a message on the mailing list."
  37965. >
  37966.  
  37967. </table>
  37968.  
  37969. <p> <br>
  37970. <a name=commonp></a>
  37971.  
  37972. <b><_sul><font face="Arial, Helvetica" color="#003366">Here are some commonly
  37973.  reported problems (</font>
  37974.  <font face="Arial, Helvetica" color="#009999">P:</font>
  37975.  <font face="Arial, Helvetica" color="#003366">) and their solutions (</font>
  37976.  <font face="Arial, Helvetica" color="#FF0099">S:</font>
  37977.  <font face="Arial, Helvetica" color="#003366">).</font></_sul></b>
  37978.  
  37979. <p>
  37980. <table border=0 cellspacing=2 cellpadding=2>
  37981.  
  37982. <_2clist
  37983.   name="<font color=\"#009999\">P:</font>"
  37984.   pos=7
  37985.   description="I ran my program with <font color=\"#993333\"><b>exw</b></font>
  37986.    and the console window disappeared before I could read the output."
  37987.  >
  37988.  
  37989. <_2clist
  37990.   name="<font color=\"#FF0099\">S:</font>"
  37991.   pos=7
  37992.   description="The console window will only appear if required, and will
  37993.    disappear immediately when your program finishes execution. Perhaps you
  37994.    should code something like:"
  37995.  >
  37996.  
  37997. <_eucode>
  37998.         puts(1, "\nPress Enter\n")
  37999.         if getc(0) then
  38000.         end if
  38001. </_eucode>
  38002.  
  38003. <_2clist
  38004.   name=""
  38005.   pos=7
  38006.   description="at the end of your program."
  38007.  >
  38008.  
  38009. </table>
  38010.  
  38011. <p>
  38012. <table border=0 cellspacing=2 cellpadding=2>
  38013.  
  38014. <_2clist
  38015.   name="<font color=\"#009999\">P:</font>"
  38016.   pos=7
  38017.   description="I would like to change the properties of the console window."
  38018.  >
  38019.  
  38020. <_2clist
  38021.   name="<font color=\"#FF0099\">S:</font>"
  38022.   pos=7
  38023.   description="Right click on <b>c:\windows\system\conagent.exe</b> and
  38024.    select \"properties\". You can change the font and several other items."
  38025.  >
  38026.  
  38027. </table>
  38028.  
  38029. <p>
  38030. <table border=0 cellspacing=2 cellpadding=2>
  38031.  
  38032. <_2clist
  38033.   name="<font color=\"#009999\">P:</font>"
  38034.   pos=7
  38035.   description="When I run <font color=\"#993333\"><b>ex.exe</b></font> on
  38036.    Windows 95/98 it makes my small DOS window go to full screen."
  38037.  >
  38038.  
  38039. <_2clist
  38040.   name="<font color=\"#FF0099\">S:</font>"
  38041.   pos=7
  38042.   description="This will only happen the first time you run
  38043.    <font color=\"#993333\"><b>ex.exe</b></font> after creating a new small
  38044.    DOS window. You can make the window small again by pressing
  38045.    <b>Alt-Enter</b>. It will stay small after that. Your Euphoria program
  38046.    can keep the window small by executing:"
  38047.  >
  38048.  
  38049. <_eucode>
  38050.         if graphics_mode(-1) then
  38051.         end if
  38052. </_eucode>
  38053.    
  38054. <_2clist
  38055.   name=""
  38056.   pos=7
  38057.   description="at the start of execution. This may cause some brief screen
  38058.    flicker. Your program can force a text window to be full-screen 
  38059.    by executing:"
  38060.  >
  38061. <_eucode>
  38062.         if graphics_mode(3) then
  38063.         end if
  38064. </_eucode>
  38065.  
  38066. </table>
  38067.  
  38068. <p>
  38069. <table border=0 cellspacing=2 cellpadding=2>
  38070.  
  38071. <_2clist
  38072.   name="<font color=\"#009999\">P:</font>"
  38073.   pos=7
  38074.   description="I try to run a program with
  38075.    <font color=\"#993333\"><b>exw</b></font> and it says \"this is a Windows
  38076.    NT character-mode executable\"."
  38077.  >
  38078.  
  38079. <_2clist
  38080.   name="<font color=\"#FF0099\">S:</font>"
  38081.   pos=7
  38082.   description="<font color=\"#993333\"><b>exw.exe</b></font> is a
  38083.    <font color=\"#CC3366\"><b>32-bit Windows program</b></font>. It must be
  38084.    run under Windows 95/98 or Windows NT. It will not work under plain DOS.
  38085.    <font color=\"#993333\"><b>ex.exe</b></font> <b><i>will</i></b> work under
  38086.    <font color=\"#CC3366\"><b>plain DOS</b></font>."
  38087.  >
  38088.  
  38089. </table>
  38090.  
  38091. <p>
  38092. <table border=0 cellspacing=2 cellpadding=2>
  38093.  
  38094. <_2clist
  38095.   name="<font color=\"#009999\">P:</font>"
  38096.   pos=7
  38097.   description="How do I read/write ports?"
  38098.  >
  38099.  
  38100. <_2clist
  38101.   name="<font color=\"#FF0099\">S:</font>"
  38102.   pos=7
  38103.   description="Get <b>Jacques Deschenes</b>' collection of machine-level and
  38104.    DOS system routines from the
  38105.    <a href=\"http://www.RapidEuphoria.com\">Euphoria Web page</a>. See his
  38106.    file <b>ports.e</b>."
  38107.  >
  38108.  
  38109. </table>
  38110.  
  38111. <p>
  38112. <table border=0 cellspacing=2 cellpadding=2>
  38113.  
  38114. <_2clist
  38115.   name="<font color=\"#009999\">P:</font>"
  38116.   pos=7
  38117.   description="I'm having trouble running a
  38118.    <font color=\"#CC3366\"><b>DOS32</b></font> graphics program. I hit
  38119.    control-Break and now my system seems to be dead."
  38120.  >
  38121.  
  38122. <_2clist
  38123.   name="<font color=\"#FF0099\">S:</font>"
  38124.   pos=7
  38125.   description="Some graphics programs will not run unless you start them from
  38126.    DOS or from a full-screen DOS window under Windows. Sometimes you
  38127.    have to edit the program source to use a lower resolution graphics mode,
  38128.    such as mode 18. Some SVGA graphics modes might not work for you under a
  38129.    Windows 95/98 DOS window, but will work when you restart your machine in
  38130.    MS-DOS mode. A better driver for your video card might fix this.
  38131.    <p>
  38132.    You should stop a program using the method that the program documentation
  38133.    recommends. If you abort a program with control-c or control-Break you may
  38134.    find that your screen is left in a funny graphics mode using funny colors.
  38135.    When you type something, it may be difficult or even impossible to read
  38136.    what you are typing. <i>The system may even appear dead, when in fact it
  38137.    is <b>not</b></i>.
  38138.    <p>
  38139.    Try the following DOS commands, in the following order, until you clear
  38140.    things up:
  38141.    <p>
  38142.       1. type: <b>cls</b><br>
  38143.          Even when you can't see any keystrokes echoed on the screen
  38144.          this may clear the screen for you.
  38145.    <p>
  38146.       2. type: <b>ex</b><br>
  38147.          The Euphoria interpreter will try to restore a normal
  38148.          <font color=\"#CC3366\">text mode</font> screen for you.
  38149.    <p>
  38150.       3. type: <b>exit</b><br>
  38151.          If you are running under Windows, this will terminate the
  38152.          DOS session for you.
  38153.    <p>
  38154.       4. type: <b>Control-Alt-Delete</b><br>
  38155.          This will let you kill the current DOS session under Windows,
  38156.          or will soft-reboot your computer if you are running under DOS.
  38157.    <p>
  38158.       5. If all else fails, reset or power your computer off and back on.
  38159.          You should immediately run <b>scandisk</b> when the system
  38160.          comes back up."
  38161.  >
  38162.  
  38163. </table>
  38164.  
  38165. <p>
  38166. <table border=0 cellspacing=2 cellpadding=2>
  38167.  
  38168. <_2clist
  38169.   name="<font color=\"#009999\">P:</font>"
  38170.   pos=7
  38171.   description="When I run Euphoria programs in SVGA, the output on the screen
  38172.    is crammed into the top part of the screen."
  38173.  >
  38174.  
  38175. <_2clist
  38176.   name="<font color=\"#FF0099\">S:</font>"
  38177.   pos=7
  38178.   description="Try: <font color=\"#006699\"><b>use_vesa(1)</b></font> in
  38179.    <font color=\"#5500FF\"><b>machine.e</b></font>.
  38180.    <p>
  38181.    Try downloading the latest driver for your video card from the Internet.
  38182.    ATI's site is:
  38183.    <p>
  38184.    <a href=\"http://www.atitech.com\">http://www.atitech.com</a>
  38185.    <p>
  38186.    Others have had their video problems clear up after installing the latest
  38187.    version of DirectX."
  38188.  >
  38189.  
  38190. </table>
  38191.  
  38192. <p>
  38193. <table border=0 cellspacing=2 cellpadding=2>
  38194.  
  38195. <_2clist
  38196.   name="<font color=\"#009999\">P:</font>"
  38197.   pos=7
  38198.   description="My program leaves the DOS window in a messy
  38199.    state. I want it to leave me with a normal text window."
  38200.  >
  38201.  
  38202. <_2clist
  38203.   name="<font color=\"#FF0099\">S:</font>"
  38204.   pos=7
  38205.   description="When your program is finished, it should call the function
  38206.   graphics_mode(-1) to set the DOS window back to normal. e.g."
  38207.  >
  38208. <_eucode>
  38209.         if graphics_mode(-1) then
  38210.         end if
  38211. </_eucode>
  38212.  
  38213. </table>
  38214.  
  38215. <p>
  38216. <table border=0 cellspacing=2 cellpadding=2>
  38217.  
  38218. <_2clist
  38219.   name="<font color=\"#009999\">P:</font>"
  38220.   pos=7
  38221.   description="When I run my program from the editor and I hit control-c,
  38222.    the program dies with an operating system error."
  38223.  >
  38224.  
  38225. <_2clist
  38226.   name="<font color=\"#FF0099\">S:</font>"
  38227.   pos=7
  38228.   description="This is a known problem. Run your program from the command-line,
  38229.    outside the editor, if you might have to hit control-c or control-Break."
  38230.  >
  38231.  
  38232. </table>
  38233.  
  38234. <p>
  38235. <table border=0 cellspacing=2 cellpadding=2>
  38236.  
  38237. <_2clist
  38238.   name="<font color=\"#009999\">P:</font>"
  38239.   pos=7
  38240.   description="When I run my program there are no errors but nothing happens."
  38241.  >
  38242.  
  38243. <_2clist
  38244.   name="<font color=\"#FF0099\">S:</font>"
  38245.   pos=7
  38246.   description="You probably forgot to call your main procedure. You need
  38247.    a top-level statement that comes after your main procedure to call the
  38248.    main procedure and start execution."
  38249.  >
  38250.  
  38251. </table>
  38252.  
  38253. <p>
  38254. <table border=0 cellspacing=2 cellpadding=2>
  38255.  
  38256. <_2clist
  38257.   name="<font color=\"#009999\">P:</font>"
  38258.   pos=7
  38259.   description="I'm trying to call a routine documented in
  38260.    <font color=\"#5500FF\"><b>library.doc</b></font>, but it keeps saying
  38261.    the routine has not been declared."
  38262.  >
  38263.  
  38264. <_2clist
  38265.   name="<font color=\"#FF0099\">S:</font>"
  38266.   pos=7
  38267.   description="Did you remember to include the necessary <b>.e</b> file from
  38268.    the <font color=\"#5500FF\"><b>euphoria\include</b></font> directory? If
  38269.    the syntax of the routine says for example, \"include graphics.e\", then
  38270.    your program must have \"<b>include graphics.e</b>\" (without the quotes)
  38271.    before the place where you first call the routine."
  38272.  >
  38273.  
  38274. </table>
  38275.  
  38276. <p>
  38277. <table border=0 cellspacing=2 cellpadding=2>
  38278.  
  38279. <_2clist
  38280.   name="<font color=\"#009999\">P:</font>"
  38281.   pos=7
  38282.   description="I have an include file with a routine in it that I want to
  38283.    call, but when I try to call the routine it says the routine has not been
  38284.    declared. But it <b><i>has</i></b> been declared."
  38285.  >
  38286.  
  38287. <_2clist
  38288.   name="<font color=\"#FF0099\">S:</font>"
  38289.   pos=7
  38290.   description="Did you remember to define the routine with
  38291.    \"<b>global</b>\" in front of it in the include file? Without \"global\"
  38292.    the routine is not visible <i><b>outside</b></i> of its own file."
  38293.  >
  38294.  
  38295. </table>
  38296.  
  38297. <p>
  38298. <table border=0 cellspacing=2 cellpadding=2>
  38299.  
  38300. <_2clist
  38301.   name="<font color=\"#009999\">P:</font>"
  38302.   pos=7
  38303.   description="How do I input a line of text from the user?"
  38304.  >
  38305.  
  38306. <_2clist
  38307.   name="<font color=\"#FF0099\">S:</font>"
  38308.   pos=7
  38309.   description="See <font color=\"#006699\"><b>gets()</b></font> in
  38310.    <a href=\"lib_e_g.htm#gets\"><font color=\"#5500FF\"><b>library.doc</b></font></a>.
  38311.    <font color=\"#006699\">gets(0)</font> will read a line from <b>standard
  38312.    input</b>, which is normally the <b>keyboard</b>. The line will always
  38313.    have <b>\n</b> on the end. To remove the trailing \n character do:"
  38314.  >
  38315.  
  38316. <_eucode>
  38317.         line = line[1..length(line)-1]
  38318. </_eucode>
  38319.  
  38320. <_2clist
  38321.   name=""
  38322.   pos=7
  38323.   description="Also see <font color=\"#006699\"><b>prompt_string()</b></font>
  38324.    in <font color=\"#5500FF\"><b>get.e</b></font>."
  38325.  >
  38326.  
  38327. </table>
  38328.  
  38329. <p>
  38330. <table border=0 cellspacing=2 cellpadding=2>
  38331.  
  38332. <_2clist
  38333.   name="<font color=\"#009999\">P:</font>"
  38334.   pos=7
  38335.   description="After inputting a string from the user with
  38336.    <font color=\"#006699\"><b>gets()</b></font>, the next line that comes
  38337.    out on the screen does not start at the left margin."
  38338.  >
  38339.  
  38340. <_2clist
  38341.   name="<font color=\"#FF0099\">S:</font>"
  38342.   pos=7
  38343.   description="Your program should output a <i>new-line</i> character e.g.
  38344.    <font color=\"#006699\"><b>puts(SCREEN, '\n')</b></font> after you do a
  38345.    <font color=\"#006699\">gets()</font>. It does not happen automatically."
  38346.  >
  38347.  
  38348. </table>
  38349.  
  38350. <p>
  38351. <table border=0 cellspacing=2 cellpadding=2>
  38352.  
  38353. <_2clist
  38354.   name="<font color=\"#009999\">P:</font>"
  38355.   pos=7
  38356.   description="How do I convert a number to a string?"
  38357.  >
  38358.  
  38359. <_2clist
  38360.   name="<font color=\"#FF0099\">S:</font>"
  38361.   pos=7
  38362.   description="Use <font color=\"#006699\"><b>sprintf()</b></font> in
  38363.    <font color=\"#5500FF\"><b>library.doc</b></font>. e.g."
  38364.  >
  38365.  
  38366. <_eucode>
  38367.         string = sprintf("%d", number)
  38368. </_eucode>
  38369.  
  38370. <_2clist
  38371.   name=""
  38372.   pos=7
  38373.   description="Besides <b>%d</b>, you can also try other formats, such as
  38374.    <b>%x</b> (Hex) or <b>%f</b> (floating-point)."
  38375.  >
  38376.  
  38377. </table>
  38378.  
  38379. <p>
  38380. <table border=0 cellspacing=2 cellpadding=2>
  38381.  
  38382. <_2clist
  38383.   name="<font color=\"#009999\">P:</font>"
  38384.   pos=7
  38385.   description="How do I convert a string to a number?"
  38386.  >
  38387.  
  38388. <_2clist
  38389.   name="<font color=\"#FF0099\">S:</font>"
  38390.   pos=7
  38391.   description="Use <font color=\"#006699\"><b>value()</b></font> in
  38392.    <font color=\"#5500FF\"><b>library.doc</b></font>, or, if you are reading
  38393.    from a file or the keyboard, use
  38394.    <font color=\"#006699\"><b>get()</b></font>."
  38395.  >
  38396.  
  38397. </table>
  38398.  
  38399. <p>
  38400. <table border=0 cellspacing=2 cellpadding=2>
  38401.  
  38402. <_2clist
  38403.   name="<font color=\"#009999\">P:</font>"
  38404.   pos=7
  38405.   description="It says I'm attempting to redefine my for-loop variable."
  38406.  >
  38407.  
  38408. <_2clist
  38409.   name="<font color=\"#FF0099\">S:</font>"
  38410.   pos=7
  38411.   description="For-loop variables are declared automatically.
  38412.    Apparently you already have a declaration with the same name earlier in
  38413.    your routine or your program. Remove that earlier declaration or change
  38414.    the name of your loop variable."
  38415.  >
  38416.  
  38417. </table>
  38418.  
  38419. <p>
  38420. <table border=0 cellspacing=2 cellpadding=2>
  38421.  
  38422. <_2clist
  38423.   name="<font color=\"#009999\">P:</font>"
  38424.   pos=7
  38425.   description="I get the message \"unknown escape character\" on a line
  38426.    where I am trying to specify a file name."
  38427.  >
  38428.  
  38429. <_2clist
  38430.   name="<font color=\"#FF0099\">S:</font>"
  38431.   pos=7
  38432.   description="<b><i>Do not</i></b> say \"C:\TMP\MYFILE\". You need to say
  38433.    <b>\"C:\\TMP\\MYFILE\"</b>. Backslash is used for escape characters such
  38434.    as <b>\n</b> or <b>\t</b>. To specify a single backslash in a string you
  38435.    need to type <b>\\</b>."
  38436.  >
  38437.  
  38438. </table>
  38439.  
  38440. <p>
  38441. <table border=0 cellspacing=2 cellpadding=2>
  38442.  
  38443. <_2clist
  38444.   name="<font color=\"#009999\">P:</font>"
  38445.   pos=7
  38446.   description="I'm trying to use mouse input in a SVGA graphics mode but it
  38447.    just doesn't work."
  38448.  >
  38449.  
  38450. <_2clist
  38451.   name="<font color=\"#FF0099\">S:</font>"
  38452.   pos=7
  38453.   description="<font color=\"#CC3366\"><b>DOS</b></font> does not support
  38454.    mouse input in modes beyond graphics mode 18 (640x480 16 color).
  38455.    <font color=\"#CC3366\"><b>DOS 7.0 (part of Windows 95/98)</b></font> does
  38456.    seem to let you at least read the x-y coordinate and the buttons in high
  38457.    resolution modes, but you may have to draw your own mouse pointer in the
  38458.    high-res modes. <b>Graeme Burke</b>, <b>Peter Blue</b> and others have good
  38459.    solutions to this problem. See their files on the
  38460.    <a href=\"http://www.RapidEuphoria.com/exestuff.htm\">Euphoria Archive
  38461.    Web page</a>."
  38462.  >
  38463.  
  38464. </table>
  38465.  
  38466. <p>
  38467. <table border=0 cellspacing=2 cellpadding=2>
  38468.  
  38469. <_2clist
  38470.   name="<font color=\"#009999\">P:</font>"
  38471.   pos=7
  38472.   description="I'm trying to print a string using
  38473.    <font color=\"#006699\"><b>printf()</b></font> but only the first character
  38474.    comes out."
  38475.  >
  38476.  
  38477. <_2clist
  38478.   name="<font color=\"#FF0099\">S:</font>"
  38479.   pos=7
  38480.   description="See the <font color=\"#006699\"><b>printf()</b></font>
  38481.    description in <font color=\"#5500FF\"><b>library.doc</b></font>. You may
  38482.    need to put braces around your string so it is seen as a single value to
  38483.    be printed, e.g. you wrote:"
  38484.  >
  38485.  
  38486. <_eucode>
  38487.         printf(1, "Hello %s", mystring)
  38488. </_eucode>
  38489.  
  38490. <_2clist
  38491.   name=""
  38492.   pos=7
  38493.   description="where you should have said:"
  38494.  >
  38495.  
  38496. <_eucode>
  38497.         printf(1, "Hello %s", {mystring})
  38498. </_eucode>
  38499.  
  38500. </table>
  38501.  
  38502. <p>
  38503. <table border=0 cellspacing=2 cellpadding=2>
  38504.  
  38505. <_2clist
  38506.   name="<font color=\"#009999\">P:</font>"
  38507.   pos=7
  38508.   description="When I print numbers using
  38509.    <font color=\"#006699\"><b>print()</b></font> or
  38510.    <font color=\"#006699\"><b>?</b></font>, only 10 significant digits are
  38511.    displayed."
  38512.  >
  38513.  
  38514. <_2clist
  38515.   name="<font color=\"#FF0099\">S:</font>"
  38516.   pos=7
  38517.   description="Euphoria normally only shows about 10 digits. Internally, all
  38518.    calculations are performed using at least 15 significant digits. To see
  38519.    more digits you have to use <font color=\"#006699\"><b>printf()</b></font>.
  38520.    For example,"
  38521.  >
  38522.  
  38523. <_eucode>
  38524.         printf(1, "%.15f", 1/3)
  38525. </_eucode>
  38526.  
  38527. <_2clist
  38528.   name=""
  38529.   pos=7
  38530.   description="This will display 15 digits."
  38531.  >
  38532.  
  38533. </table>
  38534.  
  38535. <p>
  38536. <table border=0 cellspacing=2 cellpadding=2>
  38537.  
  38538. <_2clist
  38539.   name="<font color=\"#009999\">P:</font>"
  38540.   pos=7
  38541.   description="It complains about my routine declaration, saying \"a type is
  38542.    expected here\"."
  38543.  >
  38544.  
  38545. <_2clist
  38546.   name="<font color=\"#FF0099\">S:</font>"
  38547.   pos=7
  38548.   description="When declaring subroutine parameters, Euphoria requires you to
  38549.    provide an explicit type for each individual parameter. e.g."
  38550.  >
  38551.  
  38552. <_eucode>
  38553.         procedure foo(integer x, y)         -- WRONG
  38554.         procedure foo(integer x, integer y) -- RIGHT
  38555. </_eucode>
  38556.  
  38557. <_2clist
  38558.   name=""
  38559.   pos=7
  38560.   description="In all other contexts it is ok to make a list:"
  38561.  >
  38562.  
  38563. <_eucode>
  38564.         atom a, b, c, d, e
  38565. </_eucode>
  38566.  
  38567. </table>
  38568.  
  38569. <p>
  38570. <table border=0 cellspacing=2 cellpadding=2>
  38571.  
  38572. <_2clist
  38573.   name="<font color=\"#009999\">P:</font>"
  38574.   pos=7
  38575.   description="I'm declaring some variables in the middle of a routine and
  38576.    it gives me a syntax error."
  38577.  >
  38578.  
  38579. <_2clist
  38580.   name="<font color=\"#FF0099\">S:</font>"
  38581.   pos=7
  38582.   description="All of your <i>private</i> variable declarations must come
  38583.    at the beginning of your <b>subroutine</b>, before any executable
  38584.    statements. (At the top-level of a program, <b>outside of any routine</b>,
  38585.    it is ok to declare variables anywhere.)"
  38586.  >
  38587.  
  38588. </table>
  38589.  
  38590. <p>
  38591. <table border=0 cellspacing=2 cellpadding=2>
  38592.  
  38593. <_2clist
  38594.   name="<font color=\"#009999\">P:</font>"
  38595.   pos=7
  38596.   description="It says:<br>
  38597.    Syntax Error - expected to see possibly 'xxx', not 'yyy'"
  38598.  >
  38599.  
  38600. <_2clist
  38601.   name="<font color=\"#FF0099\">S:</font>"
  38602.   pos=7
  38603.   description="At this point in your program you have typed a variable,
  38604.    keyword, number or punctuation symbol, yyy, that does not fit syntactically
  38605.    with what has come before it. The compiler is offering you one example,
  38606.    xxx, of something that would be accepted at this point in place of yyy.
  38607.    Note that there may be many other legal (and much better) possibilities
  38608.    at this point than xxx, but xxx might at least give you a clue as to what
  38609.    the compiler is \"thinking\"."
  38610.  >
  38611.  
  38612. </table>
  38613.  
  38614. <p>
  38615. <table border=0 cellspacing=2 cellpadding=2>
  38616.  
  38617. <_2clist
  38618.   name="<font color=\"#009999\">P:</font>"
  38619.   pos=7
  38620.   description="I'm having problems running Euphoria with DR-DOS."
  38621.  >
  38622.  
  38623. <_2clist
  38624.   name="<font color=\"#FF0099\">S:</font>"
  38625.   pos=7
  38626.   description="Your <b>config.sys</b> should have just HIMEM.SYS but not
  38627.    EMM386.EXE in it."
  38628.  >
  38629.  
  38630. </table>
  38631.  
  38632. <p> 
  38633.  
  38634. </_width>
  38635. </body>
  38636. </html>
  38637.  
  38638. WEB.HTX
  38639. 5519
  38640. <_init_comment>
  38641. <html>
  38642. <head><title>Euphoria Resources Available on the Internet</title>
  38643. </head>
  38644. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  38645. <_width>
  38646. <_center><font face="Arial, Helvetica" color="#FF0099" size=+2>
  38647. <br>
  38648.               Euphoria Resources Available on the Internet
  38649. </font></_center>
  38650. <p>
  38651.  
  38652. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  38653. <br>
  38654.  
  38655. <_sul>Euphoria Web Page</_sul>
  38656.  
  38657. </font>
  38658. <p>
  38659.  Check out the Official Euphoria Programming Page on the World Wide Web:
  38660. <dl>
  38661. <dt>
  38662. <dd> <a href="http://www.RapidEuphoria.com">
  38663.      <b>http://www.RapidEuphoria.com</b></a>
  38664. </dl>
  38665.  
  38666. <p>
  38667.  The latest version of Euphoria is always downloadable from this page. You
  38668.  will also find news about Euphoria, a large archive of free downloadable
  38669.  software, and links to Euphoria pages set up by enthusiastic users.
  38670.  You can also view and subscribe to the mailing list from this Web site.
  38671.  
  38672. <p>
  38673.  
  38674. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  38675. <br>
  38676.  
  38677. <_sul>Automated Euphoria Mailing List</_sul>
  38678.  
  38679. </font>
  38680. <p>
  38681.  Anyone who is interested in discussions about Euphoria can add their e-mail
  38682.  address to the Euphoria mailing list. Euphoria enthusiasts are using the
  38683.  mailing list to exchange ideas and solve problems. All you have to do is
  38684.  send e-mail to:
  38685. <dl>
  38686. <dt>
  38687. <dd> <a href="mailto:LISTSERV@LISTSERV.MUOHIO.EDU">
  38688.      <b>LISTSERV@LISTSERV.MUOHIO.EDU</b></a>
  38689. </dl>
  38690.  
  38691. <p>
  38692.  If your name is <b>John Smith</b> the <i>body of your message</i> would be: 
  38693. <pre>
  38694.         <font color="#003366">subscribe euphoria John Smith</font>
  38695. </pre>
  38696.  
  38697.  Specify your first and last name - <b><i>not</i></b> your e-mail address.
  38698.  The list server will pick up your e-mail address automatically. It will
  38699.  then reply to you with full instructions on how to participate. You do
  38700.  not have to be a registered user.
  38701.  
  38702. <p>
  38703.  After subscribing, you can e-mail a message to
  38704.  <a href="mailto:EUPHORIA@LISTSERV.MUOHIO.EDU">
  38705.  EUPHORIA@LISTSERV.MUOHIO.EDU</a> and your message will automatically be
  38706.  forwarded to everyone on the list. There are special commands for removing
  38707.  yourself from the list, and customizing various features to your liking.
  38708.  
  38709. <p>
  38710.  Everyone benefits from exchanges of ideas and useful Euphoria code. These 
  38711.  discussions and code samples are archived so you can retrieve them at any 
  38712.  time.
  38713.  
  38714. <p>
  38715.  To leave the list, send an e-mail message to:
  38716. <dl>
  38717. <dt>
  38718. <dd> <a href="mailto:LISTSERV@LISTSERV.MUOHIO.EDU">
  38719.      <b>LISTSERV@LISTSERV.MUOHIO.EDU</b></a>
  38720. </dl>
  38721.  
  38722. <p>
  38723.  The subject of your message doesn't matter, but the <i>body of your
  38724.  message</i> must be:
  38725. <pre>
  38726.         <font color="#003366">signoff euphoria</font>
  38727. </pre>
  38728.  
  38729.  Feel free to subscribe again at another time.
  38730.  
  38731. <p>
  38732.  <font color="#006633"><b>You can also interact with the mailing list
  38733.  through the Web interface.</b></font> Go to the
  38734.  <a href="http://www.RapidEuphoria.com">main Euphoria page</a> and
  38735.  click <_bq>most recent messages</_bq>.
  38736.  
  38737. <p>
  38738.  
  38739. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  38740. <br>
  38741.  
  38742. <_sul>Euphoria Newsgroup</_sul>
  38743.  
  38744. </font>
  38745. <p>
  38746.  There's an Internet newsgroup, <b>alt.lang.euphoria</b>, that is lightly used.
  38747.  Most users seem to prefer the SPAM-free environment of the mailing list.
  38748.  The mailing list operates just like a newsgroup. Feel free to post to the
  38749.  newsgroup or the mailing list, but you will probably get quicker feedback
  38750.  from the mailing list. At some point we may outgrow the mailing list and
  38751.  start making more use of the newsgroup.
  38752.  
  38753. <p>
  38754.  
  38755. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  38756. <br>
  38757.  
  38758. <_sul>Third Party Add-On Libraries and Programs</_sul>
  38759.  
  38760. </font>
  38761. <p>
  38762.  Enthusiastic users of Euphoria have contributed hundreds of excellent
  38763.  programs and library routines that you can download. This software is
  38764.  available on the Web, either at the Official Euphoria Programming Page, 
  38765.  or on a user's own Web page. Most of it is <b>Public Domain</b> and includes
  38766.  full source code, however please check the code or README file for any
  38767.  restrictions. At the RDS site you should check the
  38768.  <a href="http://www.RapidEuphoria.com/exestuff.htm">Archive page</a> and
  38769.  the <a href="http://www.RapidEuphoria.com/contrib.htm">Recent User
  38770.  Contributions page</a>.
  38771.  
  38772. <p>
  38773.  
  38774. <font face="Arial, Helvetica" color="#FF0099" size=+1>
  38775. <br>
  38776.  
  38777. <_sul>The Euphoria Micro-Economy</_sul>
  38778.  
  38779. </font>
  38780. <p>
  38781.  <font face="Comic Sans MS">GET RICH QUICK working in your spare time
  38782.  at home!</font>
  38783.  
  38784. <p>
  38785.  Anyone with an e-mail address has heard that one before, but with the
  38786.  system we call the
  38787.  <font color="#009999"><b>Euphoria Micro-Economy</b></font> you can
  38788.  potentially make a few bucks (very few) working very long hours at home
  38789.  in your spare time.
  38790.  
  38791. <p>
  38792.  Briefly, the way it works is that each month, registered users of Euphoria
  38793.  are encouraged to send e-mail to RDS donating $1.00 U.S.
  38794.  <_ba><i>of RDS's money</i></_ba> to any file on the RDS Archive or
  38795.  Recent User Contributions pages. You can split your dollar across multiple
  38796.  files as you see fit. Gradually, those who have contributed useful programs,
  38797.  documentation, or whatever to the Euphoria community will build up dollars
  38798.  that they can use to reduce or even eliminate the cost of registering or
  38799.  upgrading. There's no limit to what you can make (but don't expect to get
  38800.  rich quick!).
  38801.  
  38802. <p>
  38803.  For full details, please go to the
  38804.  <a href="http://www.RapidEuphoria.com">Euphoria Web site</a>.
  38805.  
  38806. <p> 
  38807.  
  38808. </_width>
  38809. </body>
  38810. </html>
  38811.  
  38812. WHAT2DO.HTX
  38813. 5596
  38814. <_init_comment>
  38815. <html>
  38816. <head><title>What to Do?</title>
  38817. </head>
  38818. <body bgcolor="#FFFFFF" link="#003366" vlink="#006699">
  38819. <_width>
  38820. <_center><font face="Arial, Helvetica" color="#FF0099" size=+2>
  38821. <br>
  38822.                               What to Do?
  38823. </font></_center>
  38824. <p> <br>
  38825. <font face="Arial, Helvetica" color="#003366">
  38826. <b><_sul>Now that you have installed Euphoria, here are some things you
  38827.  can try:</_sul></b></font>
  38828.  
  38829. <ul>
  38830. <li>
  38831.  Run each of the demo programs in the <font color="#5500FF"><b>demo</b></font>
  38832.   directory. You just type <font color="#993333"><b>ex</b></font> or
  38833.   <font color="#993333"><b>exw</b></font> or
  38834.   <font color="#993333"><b>exu</b></font> followed by the name of the
  38835.   <b>.ex</b> or <b>.exw</b> or <b>.exu</b> file, e.g.
  38836.  
  38837. <pre>
  38838.            ex buzz
  38839. </pre>
  38840.  
  38841.    will run the file <font color="#5500FF"><b>buzz.ex</b></font>. (Depending
  38842.    on your graphics card you may have to edit a line in some of the <b>.ex</b>
  38843.    files to select a different graphics mode. Most demos will try to use
  38844.    <b>SVGA</b> modes. You need DOS mouse support to run
  38845.    <font color="#5500FF"><b>mouse.ex</b></font> and
  38846.    <font color="#5500FF"><b>ttt.ex</b></font>).
  38847. <p>
  38848.    You can also double-click on a <b>.ex</b> (<b>.exw</b>) file
  38849.    from <font color="#CC3366"><b>Windows</b></font>, but you will 
  38850.    have to "associate" <b>.ex</b> files with
  38851.    <font color="#993333"><b>ex.exe</b></font> and <b>.exw</b> files with
  38852.    <font color="#993333"><b>exw.exe</b></font>. A few of the demos are meant
  38853.    to be run from the command line, but most will look ok from Windows.
  38854. <p>
  38855. <li>
  38856.  Use the Euphoria editor, <font color="#993333"><b>ed</b></font>, to edit a
  38857.   Euphoria file. Notice the use of
  38858.   colors. <b><font color="#006633">You can adjust these colors along with
  38859.   the cursor size and many other "user-modifiable" parameters by editing
  38860.   constant declarations in</font>
  38861.   <font color="#5500FF">ed.ex</font><font color="#006633">.</font></b>
  38862.   Use <b>Esc q</b> to quit the editor or <b>Esc h</b> for help.
  38863. <p>
  38864. <li>
  38865.  Try the benchmarks in <font color="#5500FF"><b>demo\bench</b></font>.
  38866.   Do you get the same ratios as we did in comparison with QBasic (or Perl or
  38867.   Python)? If you
  38868.    have a C/C++ compiler, how much faster can you get these benchmarks to
  38869.    run? We bet you'll be surprised, especially when you consider that
  38870.    <font color="#CC0099"><b><i>Euphoria runs the benchmarks with
  38871.    subscript checking and a host of other run-time checks</i></b></font>.
  38872. <p>
  38873. <li>
  38874.  Read the manual in <font color="#5500FF"><b>doc\refman.doc</b></font> or 
  38875.  <a href="refman.htm"><b>view the HTML version of the manual</b></a> by
  38876.   double-clicking it and starting your Web browser. The simple expressive
  38877.    power of Euphoria makes this manual much shorter than manuals for other
  38878.    languages. If you have a specific question, type
  38879.    <font color="#993333"><_bq>guru</_bq></font> followed by a list of words.
  38880.    The <font color="#993333"><b>guru</b></font> program will search all the
  38881.    <b>.doc</b> files as well as all the example programs and other files,
  38882.    and will present you with a <i>sorted</i> list of the most
  38883.    relevant chunks of text that might answer your enquiry.
  38884. <p>
  38885. <li>
  38886.  Try running a Euphoria program with
  38887.   <font color="#993333"><b>tracing</b></font> turned on. Add:
  38888. <_eucode>
  38889.            with trace
  38890.            trace(1)
  38891. </_eucode>
  38892.  
  38893.    at the beginning of any <b>.ex</b> or <b>.exw</b> file.
  38894. <p>
  38895. <li>
  38896.  Run some of the tutorial programs in
  38897.   <font color="#5500FF"><b>euphoria\tutorial</b></font>.
  38898. <p>
  38899. <li>
  38900.  Try modifying some of the demo programs.
  38901. <p>
  38902.    First some <font color="#009999"><b><i>simple</i></b></font> modifications
  38903.    (takes less than a minute):
  38904.   <blockquote>
  38905.   <p>
  38906.      What if there were 100 C++ ships in
  38907.      <font color="#5500FF"><b>Language Wars</b></font>? What if
  38908.      <font color="#5500FF"><b>sb.ex</b></font> had to move 1000 balls
  38909.      instead of 125? Change some parameters in
  38910.      <font color="#5500FF"><b>polygon.ex</b></font>. Can you get prettier
  38911.      pictures to appear? Add some funny phrases to
  38912.      <font color="#5500FF"><b>buzz.ex</b></font>.
  38913.    </blockquote>
  38914.    <p>
  38915.  
  38916.    Then, some <font color="#009999"><b><i>slightly harder</i></b></font> ones
  38917.    (takes a few minutes):
  38918.    <blockquote>
  38919.    <p>
  38920.      Define a new function of x and y in
  38921.      <font color="#5500FF"><b>plot3d.ex</b></font>.
  38922.    </blockquote>
  38923.    <p>
  38924.    
  38925.    Then a <font color="#009999"><b><i>challenging</i></b></font> one
  38926.    (takes an hour or more):
  38927.    <blockquote>
  38928.    <p>
  38929.      Set up your own customized database by defining the 
  38930.      fields in <font color="#5500FF"><b>mydata.ex</b></font>.
  38931.    </blockquote>
  38932.    <p>
  38933.  
  38934.    Then a <font color="#009999"><b><i>major</i></b></font> project
  38935.    (several days or weeks): 
  38936.    <blockquote>
  38937.    <p>
  38938.      Write a <i>smarter</i> 3D TicTacToe algorithm.
  38939.    </blockquote>
  38940.  
  38941. <p>
  38942. <li>
  38943.  Try writing your own program in Euphoria. A program can be as simple as:
  38944.  
  38945. <_eucode>
  38946.            ? 2+2
  38947. </_eucode>
  38948.  
  38949.    <font color="#006633"><b>Remember that after any error you can simply
  38950.    type</b></font> <font color="#993333"><_bq>ed</_bq></font>
  38951.    <font color="#006633"><b>to jump into the editor at the offending file
  38952.    and line.</b></font>
  38953. <p>
  38954.    Once you get used to it, you'll be developing programs
  38955.    <font color="#CC0099"><b><i>much</i></b></font> faster in
  38956.    Euphoria than you could in BASIC, Fortran, Pascal, C/C++ or any other
  38957.    language that we are aware of.
  38958.  
  38959. </ul>
  38960.  
  38961. <p> 
  38962.  
  38963. </_width>
  38964. </body>
  38965. </html>
  38966.  
  38967. DLL.E
  38968. 1786
  38969. -- routines and constants for dynamic linking to C functions
  38970.  
  38971. -- C types for arguments and return value:
  38972. global constant 
  38973.      C_CHAR    = #01000001,
  38974.      C_UCHAR   = #02000001,
  38975.      C_SHORT   = #01000002,
  38976.      C_USHORT  = #02000002,
  38977.      C_INT     = #01000004,
  38978.      C_UINT    = #02000004,
  38979.      C_LONG    = C_INT,
  38980.      C_ULONG   = C_UINT,
  38981.      C_POINTER = C_ULONG,
  38982.      C_FLOAT   = #03000004,
  38983.      C_DOUBLE  = #03000008
  38984.  
  38985. global constant NULL = 0 -- NULL pointer
  38986.  
  38987. constant M_OPEN_DLL  = 50,
  38988.      M_DEFINE_C  = 51,
  38989.      M_CALL_BACK = 52,
  38990.      M_FREE_CONSOLE = 54,
  38991.      M_DEFINE_VAR = 56
  38992.      
  38993. global function open_dll(sequence file_name)
  38994. -- Open a .DLL file
  38995.     return machine_func(M_OPEN_DLL, file_name)
  38996. end function
  38997.  
  38998. global function define_c_var(atom lib, sequence variable_name)
  38999. -- get the memory address where a global C variable is stored
  39000.     return machine_func(M_DEFINE_VAR, {lib, variable_name})
  39001. end function
  39002.  
  39003. global function define_c_proc(atom lib, sequence routine_name, 
  39004.                   sequence arg_sizes)
  39005. -- define a C function with VOID return type, or where the
  39006. -- return value will always be ignored
  39007.     return machine_func(M_DEFINE_C, {lib, routine_name, arg_sizes, 0})
  39008. end function
  39009.  
  39010. global function define_c_func(atom lib, sequence routine_name, 
  39011.                   sequence arg_sizes, atom return_type)
  39012. -- define a C function
  39013.     return machine_func(M_DEFINE_C, {lib, routine_name, arg_sizes, return_type})
  39014. end function
  39015.  
  39016. global function call_back(integer id)
  39017. -- return a 32-bit call-back address for a Euphoria routine
  39018.     return machine_func(M_CALL_BACK, id)
  39019. end function
  39020.  
  39021. global procedure free_console()
  39022. -- delete the console text-window (if one currently exists)
  39023.     machine_proc(M_FREE_CONSOLE, 0)
  39024. end procedure
  39025.  
  39026. -- This file (unless modified) counts as 0 statements.
  39027. with 24851813 -- delete this statement if it causes an error
  39028.  
  39029. FILE.E
  39030. 5791
  39031.         -- Directory and File Operations --
  39032.  
  39033. include sort.e
  39034. include misc.e
  39035.  
  39036. constant M_SEEK  = 19,
  39037.      M_WHERE = 20,
  39038.      M_DIR   = 22,
  39039.      M_CURRENT_DIR = 23,
  39040.      M_ALLOW_BREAK = 42,
  39041.      M_CHECK_BREAK = 43,
  39042.      M_FLUSH = 60,
  39043.      M_LOCK_FILE = 61,
  39044.      M_UNLOCK_FILE = 62,
  39045.      M_CHDIR = 63
  39046.  
  39047. type file_number(integer f)
  39048.     return f >= 0
  39049. end type
  39050.  
  39051. type file_position(integer p)
  39052.     return p >= -1
  39053. end type
  39054.  
  39055. type boolean(integer b)
  39056.     return b = 0 or b = 1
  39057. end type
  39058.  
  39059. global function seek(file_number fn, file_position pos)
  39060. -- seeks to a byte position in the file, 
  39061. -- or to end of file if pos is -1
  39062.     return machine_func(M_SEEK, {fn, pos})
  39063. end function
  39064.  
  39065. global function where(file_number fn)
  39066. -- returns the current byte position in the file
  39067.     return machine_func(M_WHERE, fn)
  39068. end function
  39069.  
  39070. global procedure flush(file_number fn)
  39071. -- flush out the buffer associated with file fn
  39072.     machine_proc(M_FLUSH, fn)
  39073. end procedure
  39074.  
  39075. global constant LOCK_SHARED = 1, 
  39076.         LOCK_EXCLUSIVE = 2
  39077.      
  39078. type lock_type(integer t)
  39079.     if platform()=LINUX then
  39080.     return t = LOCK_SHARED or t = LOCK_EXCLUSIVE
  39081.     else
  39082.     return 1
  39083.     end if
  39084. end type
  39085.  
  39086. type byte_range(sequence r)
  39087.     if length(r) = 0 then
  39088.     return 1
  39089.     elsif length(r) = 2 and r[1] <= r[2] then
  39090.     return 1
  39091.     else
  39092.     return 0
  39093.     end if
  39094. end type
  39095.  
  39096. global function lock_file(file_number fn, lock_type t, byte_range r)
  39097. -- Attempt to lock a file so other processes won't interfere with it.
  39098. -- The byte range can be {} if you want to lock the whole file
  39099.     return machine_func(M_LOCK_FILE, {fn, t, r})
  39100. end function
  39101.  
  39102. global procedure unlock_file(file_number fn, byte_range r) 
  39103. -- The byte range can be {} if you want to unlock the whole file.
  39104.     machine_proc(M_UNLOCK_FILE, {fn, r})
  39105. end procedure
  39106.  
  39107. global constant 
  39108.     D_NAME = 1,
  39109.     D_ATTRIBUTES = 2,
  39110.     D_SIZE = 3,
  39111.  
  39112.     D_YEAR = 4,
  39113.     D_MONTH = 5,
  39114.     D_DAY = 6,
  39115.  
  39116.     D_HOUR = 7,
  39117.     D_MINUTE = 8,
  39118.     D_SECOND = 9
  39119. global function dir(sequence name)
  39120. -- returns directory information, given the name
  39121. -- of a file or directory. Format returned is:
  39122. -- {
  39123. --  {"name1", attributes, size, year, month, day, hour, minute, second},
  39124. --  {"name2", ...                                                     },
  39125. -- }
  39126.     return machine_func(M_DIR, name)
  39127. end function
  39128.  
  39129. global function current_dir()
  39130. -- returns name of current working directory
  39131.     return machine_func(M_CURRENT_DIR, 0)
  39132. end function
  39133.  
  39134. global function chdir(sequence newdir)
  39135. -- Changes the current directory. Returns 1 - success, 0 - fail.
  39136.     return machine_func(M_CHDIR, newdir)
  39137. end function
  39138.  
  39139. global procedure allow_break(boolean b)
  39140. -- If b is TRUE then allow control-c/control-break to
  39141. -- terminate the program. If b is FALSE then don't allow it.
  39142. -- Initially they *will* terminate the program, but only when it
  39143. -- tries to read input from the keyboard.
  39144.     machine_proc(M_ALLOW_BREAK, b)
  39145. end procedure
  39146.  
  39147. global function check_break()
  39148. -- returns the number of times that control-c or control-break
  39149. -- were pressed since the last time check_break() was called
  39150.     return machine_func(M_CHECK_BREAK, 0)
  39151. end function
  39152.  
  39153. -- Generalized recursive directory walker
  39154.  
  39155. global constant W_BAD_PATH = -1 -- error code
  39156.  
  39157. function default_dir(sequence path)
  39158. -- Default directory sorting function for walk_dir().
  39159. -- * sorts by name *
  39160.     object d
  39161.     
  39162.     d = dir(path)
  39163.     if atom(d) then
  39164.     return d
  39165.     else
  39166.     -- sort by name
  39167.     return sort(d)
  39168.     end if
  39169. end function
  39170.  
  39171. integer SLASH
  39172. if platform() = LINUX then
  39173.     SLASH='/'
  39174. else
  39175.     SLASH='\\'
  39176. end if
  39177.  
  39178. -- override the dir sorting function with your own routine id
  39179. constant DEFAULT = -2
  39180. global integer my_dir 
  39181. my_dir = DEFAULT  -- it's better not to use routine_id() here,
  39182.           -- or else users will have to bind with clear routine names
  39183.  
  39184. global function walk_dir(sequence path_name, integer your_function, 
  39185.              integer scan_subdirs)
  39186. -- Generalized Directory Walker
  39187. -- Walk through a directory and (optionally) its subdirectories,
  39188. -- "visiting" each file and subdirectory. Your function will be called
  39189. -- via its routine id. The visits will occur in alphabetical order.
  39190. -- Your function should accept the path name and dir() entry for
  39191. -- each file and subdirectory. It should return 0 to keep going,
  39192. -- or an error code (greater than 0) to quit, or it can return
  39193. -- any sequence or atom other than 0 as a useful diagnostic value.
  39194.     object d, abort_now
  39195.     
  39196.     -- get the full directory information
  39197.     if my_dir = DEFAULT then
  39198.     d = default_dir(path_name)
  39199.     else
  39200.     d = call_func(my_dir, {path_name})
  39201.     end if
  39202.     if atom(d) then
  39203.     return W_BAD_PATH
  39204.     end if
  39205.     
  39206.     -- trim any trailing blanks or '\' characters from the path
  39207.     while find(path_name[length(path_name)], {' ', SLASH}) do
  39208.     path_name = path_name[1..length(path_name)-1]
  39209.     end while
  39210.     
  39211.     for i = 1 to length(d) do
  39212.     if find('d', d[i][D_ATTRIBUTES]) then
  39213.         -- a directory
  39214.         if not find(d[i][D_NAME], {".", ".."}) then
  39215.         abort_now = call_func(your_function, {path_name, d[i]})
  39216.         if not equal(abort_now, 0) then
  39217.             return abort_now
  39218.         end if
  39219.         if scan_subdirs then
  39220.             abort_now = walk_dir(path_name & SLASH & d[i][D_NAME],
  39221.                      your_function, scan_subdirs)
  39222.             
  39223.             if not equal(abort_now, 0) and 
  39224.                not equal(abort_now, W_BAD_PATH) then
  39225.             -- allow BAD PATH, user might delete a file or directory 
  39226.             return abort_now
  39227.             end if
  39228.         end if
  39229.         end if
  39230.     else
  39231.         -- a file
  39232.         abort_now = call_func(your_function, {path_name, d[i]})
  39233.         if not equal(abort_now, 0) then
  39234.         return abort_now
  39235.         end if
  39236.     end if
  39237.     end for
  39238.     return 0
  39239. end function
  39240.  
  39241.  
  39242. -- This file (unless modified) is FREE - 0 statements.
  39243. with 11356118 -- delete this statement if it causes an error
  39244.  
  39245. GET.E
  39246. 7701
  39247.         ------------------------------------
  39248.         -- Input and Conversion Routines: --
  39249.         -- get()                          --
  39250.         -- value()                        --
  39251.         -- wait_key()                     --
  39252.         ------------------------------------
  39253.  
  39254. -- error status values returned from get() and value():
  39255. global constant GET_SUCCESS = 0,
  39256.         GET_EOF = -1,
  39257.         GET_FAIL = 1
  39258.  
  39259. constant M_WAIT_KEY = 26
  39260.  
  39261. constant DIGITS = "0123456789",
  39262.      HEX_DIGITS = DIGITS & "ABCDEF",
  39263.      START_NUMERIC = DIGITS & "-+.#"
  39264.  
  39265. constant TRUE = 1
  39266.  
  39267. type natural(integer x)
  39268.     return x >= 0
  39269. end type
  39270.  
  39271. type char(integer x)
  39272.     return x >= -1 and x <= 255
  39273. end type
  39274.  
  39275. natural input_file  -- file to be read from
  39276.  
  39277. object input_string -- string to be read from
  39278. natural string_next
  39279.  
  39280. char ch  -- the current character
  39281.  
  39282. global function wait_key()
  39283. -- Get the next key pressed by the user.
  39284. -- Wait until a key is pressed.
  39285.     return machine_func(M_WAIT_KEY, 0)
  39286. end function
  39287.  
  39288. procedure get_ch()
  39289. -- set ch to the next character in the input stream (either string or file)
  39290.  
  39291.     if sequence(input_string) then
  39292.     if string_next <= length(input_string) then
  39293.         ch = input_string[string_next]
  39294.         string_next += 1
  39295.     else
  39296.         ch = GET_EOF
  39297.     end if
  39298.     else    
  39299.     ch = getc(input_file)
  39300.     end if
  39301. end procedure
  39302.  
  39303. procedure skip_blanks()
  39304. -- skip white space
  39305. -- ch is "live" at entry and exit
  39306.  
  39307.     while find(ch, " \t\n\r") do
  39308.     get_ch()
  39309.     end while
  39310. end procedure
  39311.  
  39312. constant ESCAPE_CHARS = "nt'\"\\r",
  39313.      ESCAPED_CHARS = "\n\t'\"\\\r"
  39314.  
  39315. function escape_char(char c)
  39316. -- return escape character
  39317.     natural i
  39318.  
  39319.     i = find(c, ESCAPE_CHARS)
  39320.     if i = 0 then
  39321.     return GET_FAIL
  39322.     else
  39323.     return ESCAPED_CHARS[i]
  39324.     end if
  39325. end function
  39326.  
  39327. function get_qchar()
  39328. -- get a single-quoted character
  39329. -- ch is "live" at exit
  39330.     char c
  39331.     
  39332.     get_ch()
  39333.     c = ch
  39334.     if ch = '\\' then
  39335.     get_ch()
  39336.     c = escape_char(ch)
  39337.     if c = GET_FAIL then
  39338.         return {GET_FAIL, 0}
  39339.     end if
  39340.     elsif ch = '\'' then
  39341.     return {GET_FAIL, 0}
  39342.     end if
  39343.     get_ch()
  39344.     if ch != '\'' then
  39345.     return {GET_FAIL, 0}
  39346.     else
  39347.     get_ch()
  39348.     return {GET_SUCCESS, c}
  39349.     end if
  39350. end function
  39351.  
  39352. function get_string()
  39353. -- get a double-quoted character string
  39354. -- ch is "live" at exit
  39355.     sequence text
  39356.  
  39357.     text = ""
  39358.     while TRUE do
  39359.     get_ch()
  39360.     if ch = GET_EOF or ch = '\n' then
  39361.         return {GET_FAIL, 0}
  39362.     elsif ch = '"' then
  39363.         get_ch()
  39364.         return {GET_SUCCESS, text}
  39365.     elsif ch = '\\' then
  39366.         get_ch()
  39367.         ch = escape_char(ch)
  39368.         if ch = GET_FAIL then
  39369.         return {GET_FAIL, 0}
  39370.         end if
  39371.     end if
  39372.     text = text & ch
  39373.     end while
  39374. end function
  39375.  
  39376. type plus_or_minus(integer x)
  39377.     return x = -1 or x = +1
  39378. end type
  39379.  
  39380. function get_number()
  39381. -- read a number
  39382. -- ch is "live" at entry and exit
  39383.     plus_or_minus sign, e_sign
  39384.     natural ndigits
  39385.     integer hex_digit
  39386.     atom mantissa, dec, e_mag
  39387.  
  39388.     sign = +1
  39389.     mantissa = 0
  39390.     ndigits = 0
  39391.  
  39392.     -- process sign
  39393.     if ch = '-' then
  39394.     sign = -1
  39395.     get_ch()
  39396.     elsif ch = '+' then
  39397.     get_ch()
  39398.     end if
  39399.  
  39400.     -- get mantissa
  39401.     if ch = '#' then
  39402.     -- process hex integer and return
  39403.     get_ch()
  39404.     while TRUE do
  39405.         hex_digit = find(ch, HEX_DIGITS)-1
  39406.         if hex_digit >= 0 then
  39407.         ndigits += 1
  39408.         mantissa = mantissa * 16 + hex_digit
  39409.         get_ch()
  39410.         else
  39411.         if ndigits > 0 then
  39412.             return {GET_SUCCESS, sign * mantissa}
  39413.         else
  39414.             return {GET_FAIL, 0}
  39415.         end if
  39416.         end if
  39417.     end while       
  39418.     end if
  39419.     
  39420.     -- decimal integer or floating point
  39421.     while ch >= '0' and ch <= '9' do
  39422.     ndigits += 1
  39423.     mantissa = mantissa * 10 + (ch - '0')
  39424.     get_ch()
  39425.     end while
  39426.     
  39427.     if ch = '.' then
  39428.     -- get fraction
  39429.     get_ch()
  39430.     dec = 10
  39431.     while ch >= '0' and ch <= '9' do
  39432.         ndigits += 1
  39433.         mantissa += (ch - '0') / dec
  39434.         dec *= 10
  39435.         get_ch()
  39436.     end while
  39437.     end if
  39438.     
  39439.     if ndigits = 0 then
  39440.     return {GET_FAIL, 0}
  39441.     end if
  39442.     
  39443.     mantissa = sign * mantissa
  39444.     
  39445.     if ch = 'e' or ch = 'E' then
  39446.     -- get exponent sign
  39447.     e_sign = +1
  39448.     e_mag = 0
  39449.     get_ch()
  39450.     if ch = '-' then
  39451.         e_sign = -1
  39452.         get_ch()
  39453.     elsif ch = '+' then
  39454.         get_ch()
  39455.     end if
  39456.     -- get exponent magnitude 
  39457.     if ch >= '0' and ch <= '9' then
  39458.         e_mag = ch - '0'
  39459.         get_ch()
  39460.         while ch >= '0' and ch <= '9' do
  39461.         e_mag = e_mag * 10 + ch - '0'
  39462.         get_ch()                          
  39463.         end while
  39464.     else
  39465.         return {GET_FAIL, 0} -- no exponent
  39466.     end if
  39467.     e_mag *= e_sign 
  39468.     if e_mag > 308 then
  39469.         -- rare case: avoid power() overflow
  39470.         mantissa *= power(10, 308)
  39471.         if e_mag > 1000 then
  39472.         e_mag = 1000 
  39473.         end if
  39474.         for i = 1 to e_mag - 308 do
  39475.         mantissa *= 10
  39476.         end for
  39477.     else
  39478.         mantissa *= power(10, e_mag)
  39479.     end if
  39480.     end if
  39481.     
  39482.     return {GET_SUCCESS, mantissa}
  39483. end function
  39484.  
  39485. function Get()
  39486. -- read a Euphoria data object as a string of characters
  39487. -- and return {error_flag, value}
  39488. -- Note: ch is "live" at entry and exit of this routine
  39489.     sequence s, e
  39490.  
  39491.     skip_blanks()
  39492.  
  39493.     if find(ch, START_NUMERIC) then
  39494.     return get_number()
  39495.  
  39496.     elsif ch = '{' then
  39497.     -- process a sequence
  39498.     s = {}
  39499.     get_ch()
  39500.     skip_blanks()
  39501.     if ch = '}' then
  39502.         get_ch()
  39503.         return {GET_SUCCESS, s} -- empty sequence
  39504.     end if
  39505.     
  39506.     while TRUE do
  39507.         e = Get() -- read next element
  39508.         if e[1] != GET_SUCCESS then
  39509.         return e
  39510.         end if
  39511.         s = append(s, e[2])
  39512.         skip_blanks()
  39513.         if ch = '}' then
  39514.         get_ch()
  39515.         return {GET_SUCCESS, s}
  39516.         elsif ch != ',' then
  39517.         return {GET_FAIL, 0}
  39518.         end if
  39519.         get_ch() -- skip comma
  39520.     end while
  39521.  
  39522.     elsif ch = '\"' then
  39523.     return get_string()
  39524.  
  39525.     elsif ch = '\'' then
  39526.     return get_qchar()
  39527.  
  39528.     elsif ch = -1 then
  39529.     return {GET_EOF, 0}
  39530.  
  39531.     else
  39532.     return {GET_FAIL, 0}
  39533.  
  39534.     end if
  39535. end function
  39536.  
  39537. global function get(integer file)
  39538. -- Read the string representation of a Euphoria object 
  39539. -- from a file. Convert to the value of the object.
  39540. -- Return {error_status, value}.
  39541.     input_file = file
  39542.     input_string = 0
  39543.     get_ch()
  39544.     return Get()
  39545. end function
  39546.  
  39547. global function value(sequence string)
  39548. -- Read the representation of a Euphoria object
  39549. -- from a sequence of characters. Convert to the value of the object.
  39550. -- Return {error_status, value).
  39551.     input_string = string
  39552.     string_next = 1
  39553.     get_ch()
  39554.     return Get()
  39555. end function
  39556.  
  39557. global function prompt_number(sequence prompt, sequence range)
  39558. -- Prompt the user to enter a number. 
  39559. -- A range of allowed values may be specified.
  39560.     object answer
  39561.     
  39562.     while 1 do
  39563.      puts(1, prompt)
  39564.      answer = gets(0) -- make sure whole line is read
  39565.      puts(1, '\n')
  39566.  
  39567.      answer = value(answer)
  39568.      if answer[1] != GET_SUCCESS or sequence(answer[2]) then
  39569.           puts(1, "A number is expected - try again\n")
  39570.      else
  39571.          if length(range) = 2 then
  39572.           if range[1] <= answer[2] and answer[2] <= range[2] then
  39573.               return answer[2]
  39574.           else
  39575.               printf(1,
  39576.               "A number from %g to %g is expected here - try again\n",
  39577.                range)
  39578.           end if
  39579.           else
  39580.           return answer[2]
  39581.           end if
  39582.      end if
  39583.     end while
  39584. end function
  39585.  
  39586. global function prompt_string(sequence prompt)
  39587. -- Prompt the user to enter a string
  39588.     object answer
  39589.     
  39590.     puts(1, prompt)
  39591.     answer = gets(0)
  39592.     puts(1, '\n')
  39593.     if sequence(answer) and length(answer) > 0 then
  39594.     return answer[1..length(answer)-1] -- trim the \n
  39595.     else
  39596.     return ""
  39597.     end if
  39598. end function
  39599.  
  39600. global function get_bytes(integer fn, integer n)
  39601. -- Return a sequence of n bytes (maximum) from an open file.
  39602. -- If n > 0 and fewer than n bytes are returned, 
  39603. -- you've reached the end of file.
  39604.     sequence s
  39605.     integer c
  39606.     
  39607.     if n = 0 then
  39608.     return {}
  39609.     end if
  39610.     c = getc(fn)
  39611.     if c = -1 then
  39612.     return {}
  39613.     end if
  39614.     s = repeat(c, n)
  39615.     for i = 2 to n do
  39616.     s[i] = getc(fn)
  39617.     end for
  39618.     while s[n] = -1 do
  39619.     n -= 1
  39620.     end while
  39621.     return s[1..n]
  39622. end function
  39623.  
  39624. -- This file (unless modified) counts as 0 statements.
  39625. with 662503241 -- delete this statement if it causes an error
  39626.  
  39627. GRAPHICS.E
  39628. 6271
  39629.         ----------------------
  39630.         -- Graphics & Sound --
  39631.         ----------------------
  39632.  
  39633. --    GRAPHICS MODES --  argument to graphics_mode()
  39634.  
  39635. -- mode  description
  39636. -- ----  -----------
  39637. --   -1  restore to original default mode
  39638. --    0  40 x 25 text, 16 grey
  39639. --    1  40 x 25 text, 16/8 color
  39640. --    2  80 x 25 text, 16 grey
  39641. --    3  80 x 25 text, 16/8 color
  39642. --    4  320 x 200, 4 color
  39643. --    5  320 x 200, 4 grey
  39644. --    6  640 x 200, BW
  39645. --    7  80 x 25 text, BW
  39646. --   11  720 x 350, BW  (many video cards are lacking this one)
  39647. --   13  320 x 200, 16 color
  39648. --   14  640 x 200, 16 color
  39649. --   15  640 x 350, BW  (may be 4-color with blinking)
  39650. --   16  640 x 350, 4 or 16 color
  39651. --   17  640 x 480, BW
  39652. --   18  640 x 480, 16 color
  39653. --   19  320 x 200, 256 color
  39654. --  256  640 x 400, 256 color  (some cards are missing this one)
  39655. --  257  640 x 480, 256 color  (some cards are missing this one)
  39656. --  258  800 x 600, 16 color
  39657. --  259  800 x 600, 256 color
  39658. --  260  1024 x 768, 16 color
  39659. --  261  1024 x 768, 256 color
  39660.  
  39661. -- COLOR values -- for characters and pixels
  39662. global constant 
  39663.      BLACK = 0,  -- in graphics modes this is "transparent"
  39664.      GREEN = 2,
  39665.      MAGENTA = 5,
  39666.      WHITE = 7,
  39667.      GRAY  = 8,
  39668.      BRIGHT_GREEN = 10,
  39669.      BRIGHT_MAGENTA = 13,
  39670.      BRIGHT_WHITE = 15
  39671. global integer 
  39672.      BLUE, CYAN, RED, BROWN, BRIGHT_BLUE, BRIGHT_CYAN, BRIGHT_RED, YELLOW
  39673.  
  39674. include misc.e
  39675.  
  39676. if platform() = LINUX then
  39677.     BLUE  = 4
  39678.     CYAN =  6
  39679.     RED   = 1
  39680.     BROWN = 3
  39681.     BRIGHT_BLUE = 12
  39682.     BRIGHT_CYAN = 14
  39683.     BRIGHT_RED = 9
  39684.     YELLOW = 11
  39685. else
  39686.     BLUE  = 1
  39687.     CYAN =  3
  39688.     RED   = 4
  39689.     BROWN = 6
  39690.     BRIGHT_BLUE = 9
  39691.     BRIGHT_CYAN = 11
  39692.     BRIGHT_RED = 12
  39693.     YELLOW = 14
  39694. end if
  39695.  
  39696. global constant BLINKING = 16  -- add to color to get blinking text
  39697.  
  39698. -- machine() commands
  39699. constant M_SOUND          = 1,
  39700.      M_LINE           = 2,
  39701.      M_PALETTE        = 3,
  39702.      M_GRAPHICS_MODE  = 5,
  39703.      M_CURSOR         = 6,
  39704.      M_WRAP           = 7,
  39705.      M_SCROLL         = 8,
  39706.      M_SET_T_COLOR    = 9,
  39707.      M_SET_B_COLOR    = 10,
  39708.      M_POLYGON        = 11,
  39709.      M_TEXTROWS       = 12,
  39710.      M_VIDEO_CONFIG   = 13,
  39711.      M_ELLIPSE        = 18,
  39712.      M_GET_POSITION   = 25,
  39713.      M_ALL_PALETTE    = 27
  39714.  
  39715. type mode(integer x)
  39716.     return (x >= -3 and x <= 19) or (x >= 256 and x <= 263)
  39717. end type
  39718.  
  39719. type color(integer x)
  39720.     return x >= 0 and x <= 255
  39721. end type
  39722.  
  39723. type boolean(integer x)
  39724.     return x = 0 or x = 1
  39725. end type
  39726.  
  39727. type positive_int(integer x)
  39728.     return x >= 1
  39729. end type
  39730.  
  39731. type point(sequence x)
  39732.     return length(x) = 2
  39733. end type
  39734.  
  39735. type multi_point(sequence x)
  39736.     return length(x) = 2 or length(x) = 3
  39737. end type
  39738.  
  39739. type point_sequence(sequence x)
  39740.     return length(x) >= 2
  39741. end type
  39742.  
  39743. global procedure draw_line(color c, point_sequence xyarray)
  39744. -- draw a line connecting the 2 or more points
  39745. -- in xyarray: {{x1, y1}, {x2, y2}, ...}
  39746. -- using a certain color 
  39747.     machine_proc(M_LINE, {c, 0, xyarray})
  39748. end procedure
  39749.  
  39750. global procedure polygon(color c,
  39751.              boolean fill,
  39752.              point_sequence xyarray)
  39753. -- draw a polygon using a certain color
  39754. -- fill the area if fill is TRUE
  39755. -- 3 or more vertices are given in xyarray
  39756.     machine_proc(M_POLYGON, {c, fill, xyarray})
  39757. end procedure
  39758.  
  39759. global procedure ellipse(color c, boolean fill, point p1, point p2)
  39760. -- draw an ellipse with a certain color that fits in the
  39761. -- rectangle defined by diagonal points p1 and p2, i.e. 
  39762. -- {x1, y1} and {x2, y2}. The ellipse may be filled or just an outline.   
  39763.     machine_proc(M_ELLIPSE, {c, fill, p1, p2})
  39764. end procedure
  39765.  
  39766. global function graphics_mode(mode m)
  39767. -- try to set up a new graphics mode
  39768. -- return 0 if successful, non-zero if failed
  39769.    return machine_func(M_GRAPHICS_MODE, m)
  39770. end function
  39771.  
  39772. global constant VC_COLOR = 1,
  39773.         VC_MODE  = 2,
  39774.         VC_LINES = 3,
  39775.         VC_COLUMNS = 4,
  39776.         VC_XPIXELS = 5,
  39777.         VC_YPIXELS = 6,
  39778.         VC_NCOLORS = 7,
  39779.         VC_PAGES = 8
  39780. global function video_config()
  39781. -- return sequence of information on video configuration
  39782. -- {color?, mode, text lines, text columns, xpixels, ypixels, #colors, pages}
  39783.     return machine_func(M_VIDEO_CONFIG, 0)
  39784. end function
  39785.  
  39786. -- cursor styles:
  39787. global constant NO_CURSOR       = #2000,
  39788.      UNDERLINE_CURSOR       = #0607,
  39789.      THICK_UNDERLINE_CURSOR = #0507,
  39790.      HALF_BLOCK_CURSOR      = #0407,
  39791.      BLOCK_CURSOR           = #0007
  39792.      
  39793.  
  39794. global procedure cursor(integer style)
  39795. -- choose a cursor style
  39796.     machine_proc(M_CURSOR, style)
  39797. end procedure
  39798.  
  39799. global function get_position()
  39800. -- return {line, column} of current cursor position
  39801.     return machine_func(M_GET_POSITION, 0)
  39802. end function
  39803.  
  39804. global function text_rows(positive_int rows)
  39805.     return machine_func(M_TEXTROWS, rows)
  39806. end function
  39807.  
  39808. global procedure wrap(boolean on)
  39809. -- on = 1: characters will wrap at end of long line
  39810. -- on = 0: lines will be truncated
  39811.     machine_proc(M_WRAP, on)
  39812. end procedure
  39813.  
  39814. global procedure scroll(integer amount, 
  39815.             positive_int top_line, 
  39816.             positive_int bottom_line)
  39817. -- scroll lines of text on screen between top_line and bottom_line
  39818. -- amount > 0: scroll text up by amount lines
  39819. -- amount < 0: scroll text down by amount lines
  39820. -- (had only the first parameter in v1.2)   
  39821.     machine_proc(M_SCROLL, {amount, top_line, bottom_line})
  39822. end procedure
  39823.  
  39824. global procedure text_color(color c)
  39825. -- set the foreground text color to c - text or graphics modes
  39826. -- add 16 to get blinking
  39827.     machine_proc(M_SET_T_COLOR, c)
  39828. end procedure
  39829.  
  39830. global procedure bk_color(color c)
  39831. -- set the background color to c - text or graphics modes
  39832.     machine_proc(M_SET_B_COLOR, c)
  39833. end procedure
  39834.  
  39835. type mixture(sequence s)
  39836.     return length(s) = 3 -- {red, green, blue}
  39837. end type
  39838.  
  39839. global function palette(color c, mixture s)
  39840. -- choose a new mix of {red, green, blue} to be shown on the screen for
  39841. -- color number c. Returns previous mixture as {red, green, blue}.
  39842.     return machine_func(M_PALETTE, {c, s})
  39843. end function
  39844.  
  39845. global procedure all_palette(sequence s)
  39846. -- s is a sequence of the form: {{r,g,b},{r,g,b}, ...{r,g,b}}
  39847. -- that specifies new color intensities for the entire set of
  39848. -- colors in the current graphics mode.  
  39849.     machine_proc(M_ALL_PALETTE, s)
  39850. end procedure
  39851.  
  39852. -- Sound Effects --
  39853.  
  39854. type frequency(integer x)
  39855.     return x >= 0
  39856. end type
  39857.  
  39858. global procedure sound(frequency f)
  39859. -- turn on speaker at frequency f
  39860. -- turn off speaker if f is 0
  39861.     machine_proc(M_SOUND, f)
  39862. end procedure
  39863.  
  39864.  
  39865. -- This file (unless modified) counts as 0 statements.
  39866. with 26547076 -- delete this statement if it causes an error
  39867.  
  39868. IMAGE.E
  39869. 19749
  39870. -- Graphical Image routines
  39871.  
  39872. include machine.e
  39873. include graphics.e
  39874. include misc.e
  39875.  
  39876. constant BMPFILEHDRSIZE = 14
  39877. constant OLDHDRSIZE = 12, NEWHDRSIZE = 40
  39878. constant EOF = -1
  39879.  
  39880. -- error codes returned by read_bitmap(), save_bitmap() and save_screen()
  39881. global constant BMP_SUCCESS = 0,
  39882.         BMP_OPEN_FAILED = 1,
  39883.         BMP_UNEXPECTED_EOF = 2,
  39884.         BMP_UNSUPPORTED_FORMAT = 3,
  39885.         BMP_INVALID_MODE = 4
  39886.      
  39887. integer fn, error_code
  39888.  
  39889. function get_word()
  39890. -- read 2 bytes
  39891.     integer lower, upper
  39892.     
  39893.     lower = getc(fn)
  39894.     upper = getc(fn)
  39895.     if upper = EOF then
  39896.     error_code = BMP_UNEXPECTED_EOF
  39897.     end if
  39898.     return upper * 256 + lower
  39899. end function
  39900.  
  39901. function get_dword()
  39902. -- read 4 bytes
  39903.     integer lower, upper
  39904.     
  39905.     lower = get_word()
  39906.     upper = get_word()
  39907.     return upper * 65536 + lower
  39908. end function
  39909.  
  39910. function get_c_block(integer num_bytes)
  39911. -- read num_bytes bytes
  39912.     sequence s
  39913.     
  39914.     s = repeat(0, num_bytes)
  39915.     for i = 1 to num_bytes do
  39916.     s[i] = getc(fn)
  39917.     end for
  39918.     if s[length(s)] = EOF then
  39919.     error_code = BMP_UNEXPECTED_EOF
  39920.     end if
  39921.     return s
  39922. end function
  39923.  
  39924. function get_rgb(integer set_size)
  39925. -- get red, green, blue palette values
  39926.     integer red, green, blue
  39927.     
  39928.     blue = getc(fn)
  39929.     green = getc(fn)
  39930.     red = getc(fn)
  39931.     if set_size = 4 then
  39932.     if getc(fn) then
  39933.     end if
  39934.     end if
  39935.     return {red, green, blue}
  39936. end function
  39937.  
  39938. function get_rgb_block(integer num_dwords, integer set_size)
  39939. -- reads palette 
  39940.     sequence s
  39941.  
  39942.     s = {}
  39943.     for i = 1 to num_dwords do
  39944.     s = append(s, get_rgb(set_size))
  39945.     end for
  39946.     if s[length(s)][3] = EOF then
  39947.     error_code = BMP_UNEXPECTED_EOF
  39948.     end if
  39949.     return s
  39950. end function
  39951.  
  39952. function row_bytes(atom BitCount, atom Width)
  39953. -- number of bytes per row of pixel data
  39954.     return floor(((BitCount * Width) + 31) / 32) * 4
  39955. end function
  39956.  
  39957. function unpack(sequence image, integer BitCount, integer Width, integer Height)
  39958. -- unpack the 1-d byte sequence into a 2-d sequence of pixels
  39959.     sequence pic_2d, row, bits
  39960.     integer bytes, next_byte, byte
  39961.     
  39962.     pic_2d = {}
  39963.     bytes = row_bytes(BitCount, Width)
  39964.     next_byte = 1
  39965.     for i = 1 to Height do
  39966.     row = {}
  39967.     if BitCount = 1 then
  39968.         for j = 1 to bytes do
  39969.         byte = image[next_byte]
  39970.         next_byte += 1
  39971.         bits = repeat(0, 8)
  39972.         for k = 8 to 1 by -1 do
  39973.             bits[k] = and_bits(byte, 1)
  39974.             byte = floor(byte/2)
  39975.         end for
  39976.         row &= bits
  39977.         end for
  39978.     elsif BitCount = 2 then
  39979.         for j = 1 to bytes do
  39980.         byte = image[next_byte]
  39981.         next_byte += 1
  39982.         bits = repeat(0, 4)
  39983.         for k = 4 to 1 by -1 do
  39984.             bits[k] = and_bits(byte, 3)
  39985.             byte = floor(byte/4)
  39986.         end for
  39987.         row &= bits
  39988.         end for
  39989.     elsif BitCount = 4 then
  39990.         for j = 1 to bytes do
  39991.         byte = image[next_byte]
  39992.         row = append(row, floor(byte/16))
  39993.         row = append(row, and_bits(byte, 15))
  39994.         next_byte += 1
  39995.         end for
  39996.     elsif BitCount = 8 then
  39997.         row = image[next_byte..next_byte+bytes-1]
  39998.         next_byte += bytes
  39999.     else
  40000.         error_code = BMP_UNSUPPORTED_FORMAT
  40001.         exit
  40002.     end if
  40003.     pic_2d = prepend(pic_2d, row[1..Width])
  40004.     end for
  40005.     return pic_2d
  40006. end function
  40007.  
  40008. global function read_bitmap(sequence file_name)
  40009. -- read a bitmap (.BMP) file into a 2-d sequence of sequences (image)
  40010. -- return {palette,image}   
  40011.     atom Size 
  40012.     integer Type, Xhot, Yhot, Planes, BitCount
  40013.     atom Width, Height, Compression, OffBits, SizeHeader, 
  40014.      SizeImage, XPelsPerMeter, YPelsPerMeter, ClrUsed,
  40015.      ClrImportant, NumColors
  40016.     sequence Palette, Bits, two_d_bits
  40017.  
  40018.     error_code = 0
  40019.     fn = open(file_name, "rb")
  40020.     if fn = -1 then
  40021.     return BMP_OPEN_FAILED
  40022.     end if
  40023.     Type = get_word()
  40024.     Size = get_dword()
  40025.     Xhot = get_word()
  40026.     Yhot = get_word()
  40027.     OffBits = get_dword()
  40028.     SizeHeader = get_dword()
  40029.  
  40030.     if SizeHeader = NEWHDRSIZE then
  40031.     Width = get_dword()
  40032.     Height = get_dword()
  40033.     Planes = get_word()
  40034.     BitCount = get_word()
  40035.     Compression = get_dword()
  40036.     if Compression != 0 then
  40037.         close(fn)
  40038.         return BMP_UNSUPPORTED_FORMAT
  40039.     end if
  40040.     SizeImage = get_dword()
  40041.     XPelsPerMeter = get_dword()
  40042.     YPelsPerMeter = get_dword()
  40043.     ClrUsed = get_dword()
  40044.     ClrImportant = get_dword()
  40045.     NumColors = (OffBits - SizeHeader - BMPFILEHDRSIZE) / 4
  40046.     if NumColors < 2 or NumColors > 256 then
  40047.         close(fn)
  40048.         return BMP_UNSUPPORTED_FORMAT
  40049.     end if
  40050.     Palette = get_rgb_block(NumColors, 4) 
  40051.     
  40052.     elsif SizeHeader = OLDHDRSIZE then 
  40053.     Width = get_word()
  40054.     Height = get_word()
  40055.     Planes = get_word()
  40056.     BitCount = get_word()
  40057.     NumColors = (OffBits - SizeHeader - BMPFILEHDRSIZE) / 3
  40058.     SizeImage = row_bytes(BitCount, Width) * Height
  40059.     Palette = get_rgb_block(NumColors, 3) 
  40060.     else
  40061.     close(fn)
  40062.     return BMP_UNSUPPORTED_FORMAT
  40063.     end if
  40064.     if Planes != 1 or Height <= 0 or Width <= 0 then
  40065.     close(fn)
  40066.     return BMP_UNSUPPORTED_FORMAT
  40067.     end if
  40068.     Bits = get_c_block(row_bytes(BitCount, Width) * Height)
  40069.     close(fn)
  40070.     two_d_bits = unpack(Bits, BitCount, Width, Height)
  40071.     if error_code then
  40072.     return error_code 
  40073.     end if
  40074.     return {Palette, two_d_bits}
  40075. end function
  40076.  
  40077. type graphics_point(sequence p)
  40078.     return length(p) = 2 and p[1] >= 0 and p[2] >= 0
  40079. end type
  40080.  
  40081. type text_point(sequence p)
  40082.     return length(p) = 2 and p[1] >= 1 and p[2] >= 1 
  40083.        and p[1] <= 200 and p[2] <= 500 -- rough sanity check
  40084. end type
  40085.  
  40086. global procedure display_image(graphics_point xy, sequence pixels)
  40087. -- display a 2-d sequence of pixels at location xy
  40088. -- N.B. coordinates are {x, y} with {0,0} at top left of screen
  40089. -- and x values increasing towards the right, 
  40090. -- and y values increasing towards the bottom of the screen
  40091.     for i = 1 to length(pixels) do
  40092.     pixel(pixels[i], xy)
  40093.     xy[2] = xy[2] + 1
  40094.     end for
  40095. end procedure
  40096.  
  40097. global function save_image(graphics_point top_left, graphics_point bottom_right)
  40098. -- Save a rectangular region on a graphics screen,
  40099. -- given the {x, y} coordinates of the top-left and bottom-right 
  40100. -- corner pixels. The result is a 2-d sequence of pixels suitable 
  40101. -- for use in display_image() above.
  40102.     integer x, width
  40103.     sequence save
  40104.     
  40105.     x = top_left[1]
  40106.     width = bottom_right[1] - x + 1
  40107.     save = {}
  40108.     for y = top_left[2] to bottom_right[2] do
  40109.     save = append(save, get_pixel({x, y, width}))
  40110.     end for
  40111.     return save
  40112. end function
  40113.  
  40114. constant COLOR_TEXT_MEMORY = #B8000,
  40115.       MONO_TEXT_MEMORY = #B0000
  40116.  
  40117. constant M_GET_DISPLAY_PAGE = 28,
  40118.      M_SET_DISPLAY_PAGE = 29,
  40119.      M_GET_ACTIVE_PAGE = 30,
  40120.      M_SET_ACTIVE_PAGE = 31
  40121.  
  40122. constant BYTES_PER_CHAR = 2
  40123.  
  40124. type page_number(integer p)
  40125.     return p >= 0 and p <= 7
  40126. end type
  40127.  
  40128. global function get_display_page()
  40129. -- return current page# mapped to the monitor   
  40130.     return machine_func(M_GET_DISPLAY_PAGE, 0)
  40131. end function
  40132.  
  40133. global procedure set_display_page(page_number page)
  40134. -- select a page to be displayed
  40135.     machine_proc(M_SET_DISPLAY_PAGE, page)
  40136. end procedure
  40137.  
  40138. global function get_active_page()
  40139. -- return current page# that screen output is sent to
  40140.     return machine_func(M_GET_ACTIVE_PAGE, 0)
  40141. end function
  40142.  
  40143. global procedure set_active_page(page_number page)
  40144. -- select a page for screen output
  40145.     machine_proc(M_SET_ACTIVE_PAGE, page)
  40146. end procedure
  40147.  
  40148. constant M_GET_SCREEN_CHAR = 58,
  40149.      M_PUT_SCREEN_CHAR = 59
  40150.  
  40151. type positive_atom(atom x)
  40152.     return x >= 1
  40153. end type
  40154.  
  40155. function DOS_scr_addr(sequence vc, text_point xy)
  40156. -- calculate address in DOS screen memory for a given line, column
  40157.     atom screen_memory
  40158.     integer page_size
  40159.     
  40160.     if vc[VC_MODE] = 7 then
  40161.     screen_memory = MONO_TEXT_MEMORY
  40162.     else
  40163.     screen_memory = COLOR_TEXT_MEMORY
  40164.     end if
  40165.     page_size = vc[VC_LINES] * vc[VC_COLUMNS] * BYTES_PER_CHAR
  40166.     page_size = 1024 * floor((page_size + 1023) / 1024)
  40167.     screen_memory = screen_memory + get_active_page() * page_size
  40168.     return screen_memory + ((xy[1]-1) * vc[VC_COLUMNS] + (xy[2]-1)) 
  40169.                * BYTES_PER_CHAR
  40170. end function
  40171.  
  40172. global function get_screen_char(positive_atom line, positive_atom column)
  40173. -- returns {character, attributes} of the single character
  40174. -- at the given (line, column) position on the screen
  40175.     atom scr_addr
  40176.     sequence vc
  40177.     
  40178.     if platform() = DOS32 then
  40179.     vc = video_config()
  40180.     if line >= 1 and line <= vc[VC_LINES] and
  40181.        column >= 1 and column <= vc[VC_COLUMNS] then
  40182.         scr_addr = DOS_scr_addr(vc, {line, column})
  40183.         return peek({scr_addr, 2})
  40184.     else
  40185.         return {0,0}
  40186.     end if
  40187.     else    
  40188.     return machine_func(M_GET_SCREEN_CHAR, {line, column})
  40189.     end if
  40190. end function
  40191.  
  40192. global procedure put_screen_char(positive_atom line, positive_atom column, 
  40193.                  sequence char_attr)
  40194. -- stores {character, attributes, character, attributes, ...} 
  40195. -- of 1 or more characters at position (line, column) on the screen
  40196.     atom scr_addr
  40197.     sequence vc
  40198.     integer overflow
  40199.     
  40200.     if platform() = DOS32 then
  40201.     vc = video_config()
  40202.     if line <= vc[VC_LINES] and column <= vc[VC_COLUMNS] then
  40203.         scr_addr = DOS_scr_addr(vc, {line, column})
  40204.         overflow = length(char_attr) - 2 * (vc[VC_COLUMNS] - column + 1)
  40205.         if overflow then
  40206.         poke(scr_addr, char_attr[1..length(char_attr) - overflow])  
  40207.         else
  40208.         poke(scr_addr, char_attr)
  40209.         end if
  40210.     end if
  40211.     else    
  40212.     machine_proc(M_PUT_SCREEN_CHAR, {line, column, char_attr})
  40213.     end if
  40214. end procedure
  40215.  
  40216. global procedure display_text_image(text_point xy, sequence text)
  40217. -- Display a text image at line xy[1], column xy[2] in any text mode.
  40218. -- N.B. coordinates are {line, column} with {1,1} at the top left of screen
  40219. -- Displays to the active text page.
  40220.     atom scr_addr
  40221.     integer screen_width, extra_col2, extra_lines
  40222.     sequence vc, one_row
  40223.     
  40224.     vc = video_config()
  40225.     if platform() = DOS32 then
  40226.     screen_width = vc[VC_COLUMNS] * BYTES_PER_CHAR
  40227.     scr_addr = DOS_scr_addr(vc, xy)
  40228.     end if
  40229.     if xy[1] < 1 or xy[2] < 1 then
  40230.     return -- bad starting point
  40231.     end if
  40232.     extra_lines = vc[VC_LINES] - xy[1] + 1 
  40233.     if length(text) > extra_lines then
  40234.     if extra_lines <= 0 then
  40235.         return -- nothing to display
  40236.     end if
  40237.     text = text[1..extra_lines] -- truncate
  40238.     end if
  40239.     extra_col2 = 2 * (vc[VC_COLUMNS] - xy[2] + 1)
  40240.     for row = 1 to length(text) do
  40241.     one_row = text[row]
  40242.     if length(one_row) > extra_col2 then
  40243.         if extra_col2 <= 0 then
  40244.         return -- nothing to display
  40245.         end if
  40246.         one_row = one_row[1..extra_col2] -- truncate
  40247.     end if
  40248.     if platform() = DOS32 then
  40249.         poke(scr_addr, one_row)
  40250.         scr_addr += screen_width
  40251.     else
  40252.         -- Linux
  40253.         machine_proc(M_PUT_SCREEN_CHAR, {xy[1]+row-1, xy[2], one_row})
  40254.     end if
  40255.     end for
  40256. end procedure
  40257.  
  40258. global function save_text_image(text_point top_left, text_point bottom_right)
  40259. -- Copy a rectangular block of text out of screen memory,
  40260. -- given the coordinates of the top-left and bottom-right corners.
  40261. -- Reads from the active text page.
  40262.     sequence image, row_chars, vc
  40263.     atom scr_addr, screen_memory
  40264.     integer screen_width, image_width
  40265.     integer page_size
  40266.     
  40267.     vc = video_config()
  40268.     screen_width = vc[VC_COLUMNS] * BYTES_PER_CHAR
  40269.     if platform() = DOS32 then
  40270.     if vc[VC_MODE] = 7 then
  40271.         screen_memory = MONO_TEXT_MEMORY
  40272.     else
  40273.         screen_memory = COLOR_TEXT_MEMORY
  40274.     end if
  40275.     page_size = vc[VC_LINES] * screen_width
  40276.     page_size = 1024 * floor((page_size + 1023) / 1024)
  40277.     screen_memory = screen_memory + get_active_page() * page_size
  40278.     scr_addr = screen_memory + 
  40279.         (top_left[1]-1) * screen_width + 
  40280.         (top_left[2]-1) * BYTES_PER_CHAR
  40281.     end if
  40282.     image = {}
  40283.     image_width = (bottom_right[2] - top_left[2] + 1) * BYTES_PER_CHAR
  40284.     for row = top_left[1] to bottom_right[1] do
  40285.     if platform() = DOS32 then
  40286.         row_chars = peek({scr_addr, image_width})
  40287.         scr_addr += screen_width
  40288.     else
  40289.         -- Linux
  40290.         row_chars = {}
  40291.         for col = top_left[2] to bottom_right[2] do
  40292.         row_chars &= machine_func(M_GET_SCREEN_CHAR, {row, col})
  40293.         end for
  40294.     end if
  40295.     image = append(image, row_chars)
  40296.     end for
  40297.     return image
  40298. end function
  40299.  
  40300.  
  40301. -- save_screen() and related functions were written by 
  40302. -- Junko C. Miura of Rapid Deployment Software.  
  40303.  
  40304. integer numXPixels, numYPixels, bitCount, numRowBytes
  40305. integer startXPixel, startYPixel, endYPixel
  40306.  
  40307. type region(object r)
  40308.     -- a region on the screen
  40309.     if atom(r) then
  40310.     return r = 0
  40311.     else
  40312.     return length(r) = 2 and graphics_point(r[1]) and
  40313.                  graphics_point(r[2])
  40314.     end if
  40315. end type
  40316.  
  40317. type two_seq(sequence s)
  40318.     -- a two element sequence, both elements are sequences
  40319.     return length(s) = 2 and sequence(s[1]) and sequence(s[2])
  40320. end type
  40321.  
  40322. procedure putBmpFileHeader(integer numColors)
  40323.     integer offBytes
  40324.     
  40325.     -- calculate bitCount, ie, color bits per pixel, (1, 2, 4, 8, or error) 
  40326.     if numColors = 256 then
  40327.     bitCount = 8            -- 8 bits per pixel
  40328.     elsif numColors = 16 then
  40329.     bitCount = 4            -- 4 bits per pixel
  40330.     elsif numColors = 4 then
  40331.     bitCount = 2            -- 2 bits per pixel 
  40332.     elsif numColors = 2 then
  40333.     bitCount = 1            -- 1 bit per pixel
  40334.     else 
  40335.     error_code = BMP_INVALID_MODE
  40336.     return
  40337.     end if
  40338.  
  40339.     puts(fn, "BM")  -- file-type field in the file header
  40340.     offBytes = 4 * numColors + BMPFILEHDRSIZE + NEWHDRSIZE
  40341.     numRowBytes = row_bytes(bitCount, numXPixels)
  40342.     -- put total size of the file
  40343.     puts(fn, int_to_bytes(offBytes + numRowBytes * numYPixels))
  40344.  
  40345.     puts(fn, {0, 0, 0, 0})              -- reserved fields, must be 0
  40346.     puts(fn, int_to_bytes(offBytes))    -- offBytes is the offset to the start
  40347.                     --   of the bitmap information
  40348.     puts(fn, int_to_bytes(NEWHDRSIZE))  -- size of the secondary header
  40349.     puts(fn, int_to_bytes(numXPixels))  -- width of the bitmap in pixels
  40350.     puts(fn, int_to_bytes(numYPixels))  -- height of the bitmap in pixels
  40351.     
  40352.     puts(fn, {1, 0})                    -- planes, must be a word of value 1
  40353.     
  40354.     puts(fn, {bitCount, 0})     -- bitCount
  40355.     
  40356.     puts(fn, {0, 0, 0, 0})      -- compression scheme
  40357.     puts(fn, {0, 0, 0, 0})      -- size image, not required
  40358.     puts(fn, {0, 0, 0, 0})      -- XPelsPerMeter, not required 
  40359.     puts(fn, {0, 0, 0, 0})      -- YPelsPerMeter, not required
  40360.     puts(fn, int_to_bytes(numColors))   -- num colors used in the image
  40361.     puts(fn, int_to_bytes(numColors))   -- num important colors in the image
  40362. end procedure
  40363.  
  40364. procedure putOneRowImage(sequence x, integer numPixelsPerByte, integer shift)
  40365. -- write out one row of image data
  40366.     integer  j, byte, numBytesFilled
  40367.     
  40368.     x &= repeat(0, 7)   -- 7 zeros is safe enough
  40369.     
  40370.     numBytesFilled = 0
  40371.     j = 1
  40372.     while j <= numXPixels do
  40373.     byte = x[j]
  40374.     for k = 1 to numPixelsPerByte - 1 do
  40375.         byte = byte * shift + x[j + k]
  40376.     end for
  40377.     
  40378.     puts(fn, byte)
  40379.     numBytesFilled += 1
  40380.     j += numPixelsPerByte
  40381.     end while
  40382.     
  40383.     for m = 1 to numRowBytes - numBytesFilled do
  40384.     puts(fn, 0)
  40385.     end for
  40386. end procedure
  40387.  
  40388. procedure putImage()
  40389. -- Write image data packed according to the bitCount information, in the order
  40390. -- last row ... first row. Data for each row is padded to a 4-byte boundary.
  40391.     sequence x
  40392.     integer  numPixelsPerByte, shift
  40393.     
  40394.     numPixelsPerByte = 8 / bitCount
  40395.     shift = power(2, bitCount)
  40396.     for i = endYPixel to startYPixel by -1 do
  40397.     x = get_pixel({startXPixel, i, numXPixels})
  40398.     putOneRowImage(x, numPixelsPerByte, shift)
  40399.     end for
  40400. end procedure
  40401.  
  40402. global function get_all_palette()
  40403. -- Get color intensities for the entire set of colors in the current 
  40404. -- graphics mode. Returned sequence is {{r,g,b},{r,g,b},...,{r,g,b}}. 
  40405. -- Intensity values are in the range 0 to 63.
  40406.     integer mem, numColors
  40407.     sequence vc, reg, colors
  40408.     
  40409.     vc = video_config()
  40410.     numColors = vc[VC_NCOLORS]
  40411.     reg = repeat(0, REG_LIST_SIZE)
  40412.     mem = allocate_low(numColors*3)
  40413.     if mem then
  40414.     reg[REG_AX] = #1017
  40415.     reg[REG_BX] = 0
  40416.     reg[REG_CX] = numColors
  40417.     reg[REG_ES] = floor(mem/16)
  40418.     reg[REG_DX] = and_bits(mem, 15)
  40419.     reg = dos_interrupt(#10, reg)
  40420.     colors = {}
  40421.     for col = mem to mem+(numColors-1)*3 by 3 do
  40422.         colors = append(colors, peek({col,3}))
  40423.     end for
  40424.     free_low(mem)
  40425.     return colors
  40426.     else
  40427.     return {} -- unlikely
  40428.     end if
  40429. end function
  40430.  
  40431. procedure putColorTable(integer numColors, sequence pal)
  40432. -- Write color table information to the .BMP file. 
  40433. -- palette data is given as a sequence {{r,g,b},..,{r,g,b}}, where each
  40434. -- r, g, or b value is 0 to 255. 
  40435.  
  40436.     for i = 1 to numColors do
  40437.     puts(fn, pal[i][3])     -- blue first in .BMP file
  40438.     puts(fn, pal[i][2])     -- green second 
  40439.     puts(fn, pal[i][1])     -- red third
  40440.     puts(fn, 0)             -- reserved, must be 0
  40441.     end for
  40442. end procedure
  40443.  
  40444. global function save_screen(region r, sequence file_name)
  40445. -- Capture the whole screen or a region of the screen, and create a Windows
  40446. -- bitmap (.BMP) file. The file name is given as a parameter. Region r is
  40447. -- either a sequence of 2 sequences: {{topLeftXPixel, topLeftYPixel},
  40448. -- {bottomRightXPixel, bottomRightYPixel}} defining a region,
  40449. -- or the integer 0 if you want to save the whole screen.
  40450.     sequence vc
  40451.     integer numColors
  40452.  
  40453.     error_code = BMP_SUCCESS
  40454.     fn = open(file_name, "wb")
  40455.     if fn = -1 then
  40456.     return BMP_OPEN_FAILED
  40457.     end if
  40458.  
  40459.     vc = video_config()
  40460.     if sequence(r) then
  40461.     numXPixels = r[2][1] - r[1][1] + 1
  40462.     numYPixels = r[2][2] - r[1][2] + 1
  40463.     if r[2][1] >= vc[VC_XPIXELS] or r[2][2] >= vc[VC_YPIXELS] then
  40464.         close(fn)
  40465.         return BMP_INVALID_MODE   -- not a valid argument 
  40466.     end if
  40467.     startXPixel = r[1][1]
  40468.     startYPixel = r[1][2]
  40469.     endYPixel   = r[2][2]
  40470.     else
  40471.     numXPixels = vc[VC_XPIXELS]
  40472.     numYPixels = vc[VC_YPIXELS]
  40473.     startXPixel = 0
  40474.     startYPixel = 0
  40475.     endYPixel   = numYPixels - 1
  40476.     end if
  40477.     
  40478.     if numXPixels <= 0 or numYPixels <= 0 then
  40479.     -- not a valid graphics mode or not a valid argument 
  40480.     close(fn)
  40481.     return BMP_INVALID_MODE
  40482.     end if
  40483.     
  40484.     numColors = vc[VC_NCOLORS]
  40485.     putBmpFileHeader(numColors)
  40486.     
  40487.     if error_code = BMP_SUCCESS then
  40488.     putColorTable(numColors, get_all_palette()*4)
  40489.     end if
  40490.     if error_code = BMP_SUCCESS then
  40491.     putImage()
  40492.     end if
  40493.     close(fn)
  40494.     return error_code
  40495. end function    
  40496.  
  40497. procedure putImage1(sequence image)
  40498. -- Write image data packed according to the bitCount information, in the order
  40499. -- last row ... first row. Data for each row is padded to a 4-byte boundary.
  40500. -- Image data is given as a 2-d sequence in the order first row... last row.
  40501.     object   x
  40502.     integer  numPixelsPerByte, shift
  40503.     
  40504.     numPixelsPerByte = 8 / bitCount
  40505.     shift = power(2, bitCount)
  40506.     for i = numYPixels to 1 by -1 do
  40507.     x = image[i]
  40508.     if atom(x) then
  40509.         error_code = BMP_INVALID_MODE
  40510.         return
  40511.     elsif length(x) != numXPixels then
  40512.         error_code = BMP_INVALID_MODE
  40513.         return
  40514.     end if
  40515.     putOneRowImage(x, numPixelsPerByte, shift) 
  40516.     end for
  40517. end procedure
  40518.  
  40519. global function save_bitmap(two_seq palette_n_image, sequence file_name)
  40520. -- Create a .BMP bitmap file, given a palette and a 2-d sequence of sequences.
  40521. -- The opposite of read_bitmap().
  40522.     sequence color, image
  40523.     integer numColors
  40524.  
  40525.     error_code = BMP_SUCCESS
  40526.     fn = open(file_name, "wb")
  40527.     if fn = -1 then
  40528.     return BMP_OPEN_FAILED
  40529.     end if
  40530.     
  40531.     color = palette_n_image[1]
  40532.     image = palette_n_image[2]
  40533.     numYPixels = length(image)
  40534.     numXPixels = length(image[1])   -- assume the same length with each row
  40535.     numColors = length(color)
  40536.     
  40537.     putBmpFileHeader(numColors)
  40538.     
  40539.     if error_code = BMP_SUCCESS then
  40540.     putColorTable(numColors, color) 
  40541.     putImage1(image)
  40542.     end if
  40543.     close(fn)
  40544.     return error_code
  40545. end function
  40546.  
  40547.  
  40548. -- This file (unless modified) is FREE - 0 statements.
  40549. with 472333662 -- delete this statement if it causes an error
  40550.  
  40551. MACHINE.E
  40552. 9072
  40553.         ----------------------------------------
  40554.         -- Machine Level Programming for 386+ --
  40555.         ----------------------------------------
  40556.  
  40557. -- Warning: Some of these routines require a knowledge of 
  40558. -- machine-level programming. You could crash your system!
  40559.  
  40560. -- These routines, along with peek(), poke() and call(), let you access all 
  40561. -- of the features of your computer.  You can read and write to any memory 
  40562. -- location, and you can create and execute machine code subroutines.
  40563.  
  40564. -- If you are manipulating 32-bit addresses or values, remember to use
  40565. -- variables declared as atom. The integer type only goes up to 31 bits.
  40566.  
  40567. -- Writing characters to screen memory with poke() is much faster than  
  40568. -- using puts(). Address of start of text screen memory:
  40569. --       mono: #B0000
  40570. --      color: #B8000
  40571.  
  40572. -- If you choose to call machine_proc() or machine_func() directly (to save
  40573. -- a bit of overhead) you *must* pass valid arguments or Euphoria could crash.
  40574.  
  40575. -- Some example programs to look at:
  40576. --   demo\dos32\callmach.ex - calling a machine language routine
  40577. --   demo\dos32\hardint.ex  - setting up a hardware interrupt handler
  40578. --   demo\dos32\dosint.ex   - calling a DOS software interrupt
  40579.  
  40580. -- See also safe.e in this directory. It's a safe, debugging version of this
  40581. -- file.
  40582.  
  40583. constant M_ALLOC = 16,
  40584.      M_FREE = 17,
  40585.      M_ALLOC_LOW = 32,
  40586.      M_FREE_LOW = 33,
  40587.      M_INTERRUPT = 34,
  40588.      M_SET_RAND = 35,
  40589.      M_USE_VESA = 36,
  40590.      M_CRASH_MESSAGE = 37,
  40591.      M_TICK_RATE = 38,
  40592.      M_GET_VECTOR = 39,
  40593.      M_SET_VECTOR = 40,
  40594.      M_LOCK_MEMORY = 41,
  40595.      M_A_TO_F64 = 46,
  40596.      M_F64_TO_A = 47,
  40597.      M_A_TO_F32 = 48,
  40598.      M_F32_TO_A = 49,
  40599.      M_CRASH_FILE = 57
  40600.  
  40601. -- biggest address on a 32-bit machine
  40602. constant MAX_ADDR = power(2, 32)-1
  40603.  
  40604. -- biggest address accessible to 16-bit real mode
  40605. constant LOW_ADDR = power(2, 20)-1
  40606.  
  40607. type positive_int(integer x)
  40608.     return x >= 1
  40609. end type
  40610.  
  40611. type natural(integer x)
  40612.     return x >= 0
  40613. end type
  40614.  
  40615. type machine_addr(atom a)
  40616. -- a 32-bit non-null machine address 
  40617.     return a > 0 and a <= MAX_ADDR and floor(a) = a
  40618. end type
  40619.  
  40620. type far_addr(sequence a)
  40621. -- protected mode far address {seg, offset}
  40622.     return length(a) = 2 and integer(a[1]) and machine_addr(a[2])
  40623. end type
  40624.  
  40625. type low_machine_addr(atom a)
  40626. -- a legal low machine address 
  40627.     return a > 0 and a <= LOW_ADDR and floor(a) = a
  40628. end type
  40629.  
  40630. type sequence_8(sequence s)
  40631. -- an 8-element sequence
  40632.     return length(s) = 8
  40633. end type
  40634.  
  40635. type sequence_4(sequence s)
  40636. -- a 4-element sequence
  40637.     return length(s) = 4
  40638. end type
  40639.  
  40640. global constant REG_LIST_SIZE = 10
  40641. global constant REG_DI = 1,      
  40642.         REG_SI = 2,
  40643.         REG_BP = 3,
  40644.         REG_BX = 4,
  40645.         REG_DX = 5,
  40646.         REG_CX = 6,
  40647.         REG_AX = 7,
  40648.         REG_FLAGS = 8, -- on input: ignored 
  40649.                    -- on output: low bit has carry flag for 
  40650.                    -- success/fail
  40651.         REG_ES = 9,
  40652.         REG_DS = 10
  40653.  
  40654. type register_list(sequence r)
  40655. -- a list of register values
  40656.     return length(r) = REG_LIST_SIZE
  40657. end type
  40658.  
  40659. global function allocate(positive_int n)
  40660. -- Allocate n bytes of memory and return the address.
  40661. -- Free the memory using free() below.
  40662.     return machine_func(M_ALLOC, n)
  40663. end function
  40664.  
  40665. global procedure free(machine_addr a)
  40666. -- free the memory at address a
  40667.     machine_proc(M_FREE, a)
  40668. end procedure
  40669.  
  40670. global function allocate_low(positive_int n)
  40671. -- Allocate n bytes of low memory (address less than 1Mb) 
  40672. -- and return the address. Free this memory using free_low() below.
  40673. -- Addresses in this range can be passed to DOS during software interrupts.
  40674.     return machine_func(M_ALLOC_LOW, n)
  40675. end function
  40676.  
  40677. global procedure free_low(low_machine_addr a)
  40678. -- free the low memory at address a
  40679.     machine_proc(M_FREE_LOW, a)
  40680. end procedure
  40681.  
  40682. global function dos_interrupt(integer int_num, register_list input_regs)
  40683. -- call the DOS operating system via software interrupt int_num, using the
  40684. -- register values in input_regs. A similar register_list is returned.
  40685. -- It contains the register values after the interrupt.
  40686.     return machine_func(M_INTERRUPT, {int_num, input_regs})
  40687. end function
  40688.  
  40689. global function int_to_bytes(atom x)
  40690. -- returns value of x as a sequence of 4 bytes 
  40691. -- that you can poke into memory 
  40692. --      {bits 0-7,  (least significant)
  40693. --       bits 8-15,
  40694. --       bits 16-23,
  40695. --       bits 24-31} (most significant)
  40696. -- This is the order of bytes in memory on 386+ machines.
  40697.     integer a,b,c,d
  40698.     
  40699.     a = remainder(x, #100)
  40700.     x = floor(x / #100)
  40701.     b = remainder(x, #100)
  40702.     x = floor(x / #100)
  40703.     c = remainder(x, #100)
  40704.     x = floor(x / #100)
  40705.     d = remainder(x, #100)
  40706.     return {a,b,c,d}
  40707. end function
  40708.  
  40709. global function bytes_to_int(sequence s)
  40710. -- converts 4-byte peek() sequence into an integer value
  40711.     return s[1] + 
  40712.        s[2] * #100 + 
  40713.        s[3] * #10000 + 
  40714.        s[4] * #1000000
  40715. end function
  40716.  
  40717. global function int_to_bits(atom x, integer nbits)
  40718. -- Returns the low-order nbits bits of x as a sequence of 1's and 0's. 
  40719. -- Note that the least significant bits come first. You can use Euphoria's
  40720. -- and/or/not operators on sequences of bits. You can also subscript, 
  40721. -- slice, concatenate etc. to manipulate bits.
  40722.     sequence bits
  40723.     integer mask
  40724.     
  40725.     bits = repeat(0, nbits)
  40726.     if integer(x) and nbits < 30 then
  40727.     -- faster method
  40728.     mask = 1
  40729.     for i = 1 to nbits do
  40730.         bits[i] = and_bits(x, mask) and 1
  40731.         mask *= 2
  40732.     end for
  40733.     else
  40734.     -- slower, but works for large x and large nbits
  40735.     if x < 0 then
  40736.         x += power(2, nbits) -- for 2's complement bit pattern
  40737.     end if
  40738.     for i = 1 to nbits do
  40739.         bits[i] = remainder(x, 2) 
  40740.         x = floor(x / 2)
  40741.     end for
  40742.     end if
  40743.     return bits
  40744. end function
  40745.  
  40746. global function bits_to_int(sequence bits)
  40747. -- get the (positive) value of a sequence of "bits"
  40748.     atom value, p
  40749.     
  40750.     value = 0
  40751.     p = 1
  40752.     for i = 1 to length(bits) do
  40753.     if bits[i] then
  40754.         value += p
  40755.     end if
  40756.     p += p
  40757.     end for
  40758.     return value
  40759. end function
  40760.  
  40761. global procedure set_rand(integer seed)
  40762. -- Reset the random number generator.
  40763. -- A given value of seed will cause the same series of
  40764. -- random numbers to be generated from the rand() function
  40765.     machine_proc(M_SET_RAND, seed)
  40766. end procedure
  40767.  
  40768. global procedure use_vesa(integer code)
  40769. -- If code is 1 then force Euphoria to use the VESA graphics standard.
  40770. -- This may let Euphoria work better in SVGA modes with certain graphics cards.
  40771. -- If code is 0 then Euphoria's normal use of the graphics card is restored.
  40772. -- Values of code other than 0 or 1 should not be used.
  40773.     machine_proc(M_USE_VESA, code)
  40774. end procedure
  40775.  
  40776. global procedure crash_message(sequence msg)
  40777. -- Specify a final message to display for your user, in the event 
  40778. -- that Euphoria has to shut down your program due to an error.
  40779.     machine_proc(M_CRASH_MESSAGE, msg)
  40780. end procedure
  40781.  
  40782. global procedure crash_file(sequence file_path)
  40783. -- Specify a file path name in place of "ex.err" where you want
  40784. -- any diagnostic information to be written.
  40785.     machine_proc(M_CRASH_FILE, file_path)
  40786. end procedure
  40787.  
  40788. global procedure tick_rate(atom rate)
  40789. -- Specify the number of clock-tick interrupts per second.
  40790. -- This determines the precision of the time() library routine, 
  40791. -- and also the sampling rate for time profiling.
  40792.     machine_proc(M_TICK_RATE, rate)
  40793. end procedure
  40794.  
  40795. global function get_vector(integer int_num)
  40796. -- returns the current (far) address of the interrupt handler
  40797. -- for interrupt vector number int_num as a 2-element sequence: 
  40798. -- {16-bit segment, 32-bit offset}
  40799.     return machine_func(M_GET_VECTOR, int_num)
  40800. end function
  40801.  
  40802. global procedure set_vector(integer int_num, far_addr a)
  40803. -- sets a new interrupt handler address for vector int_num  
  40804.     machine_proc(M_SET_VECTOR, {int_num, a})
  40805. end procedure
  40806.  
  40807. global procedure lock_memory(machine_addr a, positive_int n)
  40808. -- Prevent a chunk of code or data from ever being swapped out to disk.
  40809. -- You should lock any code or data used by an interrupt handler.
  40810.     machine_proc(M_LOCK_MEMORY, {a, n})
  40811. end procedure
  40812.  
  40813. global function atom_to_float64(atom a)
  40814. -- Convert an atom to a sequence of 8 bytes in IEEE 64-bit format
  40815.     return machine_func(M_A_TO_F64, a)
  40816. end function
  40817.  
  40818. global function atom_to_float32(atom a)
  40819. -- Convert an atom to a sequence of 4 bytes in IEEE 32-bit format
  40820.     return machine_func(M_A_TO_F32, a)
  40821. end function
  40822.  
  40823. global function float64_to_atom(sequence_8 ieee64)
  40824. -- Convert a sequence of 8 bytes in IEEE 64-bit format to an atom
  40825.     return machine_func(M_F64_TO_A, ieee64)
  40826. end function
  40827.  
  40828. global function float32_to_atom(sequence_4 ieee32)
  40829. -- Convert a sequence of 4 bytes in IEEE 32-bit format to an atom
  40830.     return machine_func(M_F32_TO_A, ieee32)
  40831. end function
  40832.  
  40833. global function allocate_string(sequence s)
  40834. -- create a C-style null-terminated string in memory
  40835.     atom mem
  40836.     
  40837.     mem = allocate(length(s) + 1)
  40838.     if mem then
  40839.     poke(mem, s & 0)
  40840.     end if
  40841.     return mem
  40842. end function
  40843.  
  40844. -- variables and routines used in safe.e
  40845. without warning
  40846. integer check_calls
  40847. check_calls = 1
  40848.  
  40849. global procedure register_block(atom block_addr, atom block_len)
  40850. end procedure
  40851.  
  40852. global procedure unregister_block(atom block_addr)
  40853. end procedure
  40854.  
  40855. global procedure check_all_blocks()
  40856. end procedure
  40857. with warning
  40858.  
  40859. -- This file (unless modified) counts as 0 statements.
  40860. with 953103301 -- delete this statement if it causes an error
  40861.  
  40862. MISC.E
  40863. 2143
  40864. -- Miscellaneous routines and constants
  40865.  
  40866. global constant DOS32 = 1, -- ex.exe
  40867.         WIN32 = 2, -- exw.exe
  40868.         LINUX = 3  -- exu
  40869.  
  40870. constant M_INSTANCE = 55, M_SLEEP = 64
  40871.  
  40872. global function instance()
  40873. -- WIN32: returns hInstance - handle to this instance of the program
  40874. -- DOS32: returns 0
  40875.     return machine_func(M_INSTANCE, 0)
  40876. end function
  40877.  
  40878. global procedure sleep(integer t)
  40879. -- go to sleep for t seconds
  40880. -- allowing (on WIN32 and Linux) other processes to run
  40881.     if t > 0 then
  40882.     machine_proc(M_SLEEP, t)
  40883.     end if
  40884. end procedure
  40885.  
  40886. global function reverse(sequence s)
  40887. -- reverse the top-level elements of a sequence.
  40888. -- Thanks to Hawke' for helping to make this run faster.
  40889.     integer lower, n
  40890.     sequence t
  40891.     
  40892.     n = length(s)
  40893.     t = repeat(0, n)
  40894.     lower = 1
  40895.     for upper = n to floor(n/2)+1 by -1 do
  40896.     t[upper] = s[lower]
  40897.     t[lower] = s[upper]
  40898.     lower += 1
  40899.     end for
  40900.     return t
  40901. end function
  40902.  
  40903. global function sprint(object x)
  40904. -- Return the string representation of any Euphoria data object. 
  40905. -- This is the same as the output from print(1, x) or '?', but it's
  40906. -- returned as a string sequence rather than printed.
  40907.     sequence s
  40908.                  
  40909.     if atom(x) then
  40910.     return sprintf("%.10g", x)
  40911.     else
  40912.     s = "{"
  40913.     for i = 1 to length(x) do
  40914.         s &= sprint(x[i])  
  40915.         if i < length(x) then
  40916.         s &= ','
  40917.         end if
  40918.     end for
  40919.     s &= "}"
  40920.     return s
  40921.     end if
  40922. end function
  40923.  
  40924. -- trig formulas provided by Larry Gregg
  40925.  
  40926. global constant PI = 3.141592653589793238
  40927.  
  40928. constant PI_HALF =  PI / 2.0  -- this is pi/2
  40929.  
  40930. type trig_range(object x)
  40931. --  values passed to arccos and arcsin must be [-1,+1]
  40932.     if atom(x) then
  40933.     return x >= -1 and x <= 1
  40934.     else
  40935.     for i = 1 to length(x) do
  40936.         if not trig_range(x[i]) then
  40937.         return 0
  40938.         end if
  40939.     end for
  40940.     return 1
  40941.     end if
  40942. end type
  40943.  
  40944. global function arccos(trig_range x)
  40945. --  returns angle in radians
  40946.     return PI_HALF - 2 * arctan(x / (1.0 + sqrt(1.0 - x * x)))
  40947. end function
  40948.  
  40949. global function arcsin(trig_range x)
  40950. --  returns angle in radians
  40951.     return 2 * arctan(x / (1.0 + sqrt(1.0 - x * x)))
  40952. end function
  40953.  
  40954. -- This file (unless modified) counts as 0 statements.
  40955. with 63010154 -- delete this statement if it causes an error
  40956.  
  40957. MOUSE.E
  40958. 1438
  40959.         --------------------
  40960.         -- Mouse Routines --
  40961.         --------------------
  40962. -- DOS32 - you need a mouse driver
  40963. -- Linux - you need GPM server to be running
  40964. -- WIN32 - not implemented yet for the text console
  40965.  
  40966. include misc.e
  40967.  
  40968. -- Mouse Events:
  40969. global integer MOVE, LEFT_DOWN, LEFT_UP, RIGHT_DOWN, RIGHT_UP,
  40970.            MIDDLE_DOWN, MIDDLE_UP, ANY_UP
  40971.  
  40972. if platform() = LINUX then
  40973.     MOVE = 0
  40974.     LEFT_DOWN = 4
  40975.     LEFT_UP = 4
  40976.     RIGHT_DOWN = 1
  40977.     RIGHT_UP = 1
  40978.     MIDDLE_DOWN = 2
  40979.     MIDDLE_UP = 2
  40980.     ANY_UP = 35  -- LEFT, RIGHT or MIDDLE up (best you can do under xterm)
  40981. else
  40982.     MOVE = 1
  40983.     LEFT_DOWN = 2
  40984.     LEFT_UP = 4
  40985.     RIGHT_DOWN = 8
  40986.     RIGHT_UP = 16
  40987.     MIDDLE_DOWN = 32
  40988.     MIDDLE_UP = 64
  40989. end if
  40990.  
  40991. constant M_GET_MOUSE = 14,
  40992.      M_MOUSE_EVENTS = 15,
  40993.      M_MOUSE_POINTER = 24
  40994.  
  40995. global function get_mouse()
  40996. -- report mouse events,
  40997. -- returns -1 if no mouse event,
  40998. -- otherwise returns {event#, x-coord, y-coord}
  40999.     return machine_func(M_GET_MOUSE, 0)
  41000. end function
  41001.  
  41002. global procedure mouse_events(integer events)
  41003. -- select the mouse events to be reported by get_mouse()
  41004. -- e.g. mouse_events(LEFT_UP + LEFT_DOWN + RIGHT_DOWN)
  41005.     machine_proc(M_MOUSE_EVENTS, events)
  41006. end procedure
  41007.  
  41008. global procedure mouse_pointer(integer show_it)
  41009. -- show (1) or hide (0) the mouse pointer
  41010.     machine_proc(M_MOUSE_POINTER, show_it)
  41011. end procedure
  41012.  
  41013. -- This file (unless modified) counts as 0 statements.
  41014. with 92143742 -- delete this statement if it causes an error
  41015.  
  41016. MSGBOX.E
  41017. 3508
  41018. -- message_box() function
  41019.  
  41020. include dll.e
  41021. include machine.e
  41022. include misc.e
  41023.  
  41024. without warning
  41025.  
  41026. -- Possible style values for message_box() style sequence
  41027. global constant 
  41028.     MB_ABORTRETRYIGNORE = #02, --  Abort, Retry, Ignore
  41029.     MB_APPLMODAL = #00,       -- User must respond before doing something else
  41030.     MB_DEFAULT_DESKTOP_ONLY = #20000,    
  41031.     MB_DEFBUTTON1 = #00,      -- First button is default button
  41032.     MB_DEFBUTTON2 = #100,      -- Second button is default button
  41033.     MB_DEFBUTTON3 = #200,      -- Third button is default button
  41034.     MB_DEFBUTTON4 = #300,   -- Fourth button is default button
  41035.     MB_HELP = #4000,            -- Windows 95: Help button generates help event
  41036.     MB_ICONASTERISK = #40,
  41037.     MB_ICONERROR = #10, 
  41038.     MB_ICONEXCLAMATION = #30, -- Exclamation-point appears in the box
  41039.     MB_ICONHAND = MB_ICONERROR,        -- A hand appears
  41040.     MB_ICONINFORMATION = MB_ICONASTERISK,-- Lowercase letter i in a circle appears
  41041.     MB_ICONQUESTION = #20,    -- A question-mark icon appears
  41042.     MB_ICONSTOP = MB_ICONHAND,
  41043.     MB_ICONWARNING = MB_ICONEXCLAMATION,
  41044.     MB_OK = #00,              -- Message box contains one push button: OK
  41045.     MB_OKCANCEL = #01,        -- Message box contains OK and Cancel
  41046.     MB_RETRYCANCEL = #05,     -- Message box contains Retry and Cancel
  41047.     MB_RIGHT = #80000,        -- Windows 95: The text is right-justified
  41048.     MB_RTLREADING = #100000,   -- Windows 95: For Hebrew and Arabic systems
  41049.     MB_SERVICE_NOTIFICATION = #40000, -- Windows NT: The caller is a service 
  41050.     MB_SETFOREGROUND = #10000,   -- Message box becomes the foreground window 
  41051.     MB_SYSTEMMODAL  = #1000,    -- All applications suspended until user responds
  41052.     MB_TASKMODAL = #2000,       -- Similar to MB_APPLMODAL 
  41053.     MB_YESNO = #04,           -- Message box contains Yes and No
  41054.     MB_YESNOCANCEL = #03      -- Message box contains Yes, No, and Cancel
  41055.  
  41056. -- possible values returned by MessageBox() 
  41057. -- 0 means failure
  41058. global constant IDABORT = 3,  -- Abort button was selected.
  41059.         IDCANCEL = 2, -- Cancel button was selected.
  41060.         IDIGNORE = 5, -- Ignore button was selected.
  41061.         IDNO = 7,     -- No button was selected.
  41062.         IDOK = 1,     -- OK button was selected.
  41063.         IDRETRY = 4,  -- Retry button was selected.
  41064.         IDYES = 6    -- Yes button was selected.
  41065.  
  41066. atom lib
  41067. integer msgbox_id, get_active_id
  41068.  
  41069. if platform() = WIN32 then
  41070.     lib = open_dll("user32.dll")
  41071.     msgbox_id = define_c_func(lib, "MessageBoxA", {C_POINTER, C_POINTER, 
  41072.                            C_POINTER, C_INT}, C_INT)
  41073.     if msgbox_id = -1 then
  41074.     puts(2, "couldn't find MessageBoxA\n")
  41075.     abort(1)
  41076.     end if
  41077.  
  41078.     get_active_id = define_c_func(lib, "GetActiveWindow", {}, C_LONG)
  41079.     if get_active_id = -1 then
  41080.     puts(2, "couldn't find GetActiveWindow\n")
  41081.     abort(1)
  41082.     end if
  41083. end if
  41084.  
  41085. global function message_box(sequence text, sequence title, object style)
  41086.     integer or_style
  41087.     atom text_ptr, title_ptr, ret
  41088.     
  41089.     text_ptr = allocate_string(text)
  41090.     if not text_ptr then
  41091.     return 0
  41092.     end if
  41093.     title_ptr = allocate_string(title)
  41094.     if not title_ptr then
  41095.     free(text_ptr)
  41096.     return 0
  41097.     end if
  41098.     if atom(style) then
  41099.     or_style = style
  41100.     else
  41101.     or_style = 0
  41102.     for i = 1 to length(style) do
  41103.         or_style = or_bits(or_style, style[i])
  41104.     end for
  41105.     end if
  41106.     ret = c_func(msgbox_id, {c_func(get_active_id, {}), 
  41107.                  text_ptr, title_ptr, or_style})
  41108.     free(text_ptr)
  41109.     free(title_ptr)
  41110.     return ret
  41111. end function
  41112.  
  41113. -- This file (unless modified) counts as 0 statements.
  41114. with 80075173 -- delete this statement if it causes an error
  41115.  
  41116. SAFE.E
  41117. 21382
  41118.         ----------------------------------------
  41119.         -- Machine Level Programming for 386+ --
  41120.         -- * DEBUGGING VERSION of machine.e * --
  41121.         ----------------------------------------
  41122.  
  41123. -- How To Use This File:
  41124.  
  41125. -- 1. Copy safe.e into the same directory as your main .ex[w] file and 
  41126. --    rename safe.e as machine.e in that directory. (Do NOT simply 
  41127. --    include safe.e, or you may have naming conflicts.)
  41128.  
  41129. -- 2. If your program doesn't already include machine.e add:  
  41130. --           include machine.e  
  41131. --    to your main .ex[w] file at the top.
  41132.  
  41133. -- 3. If necessary, call register_block(address, length) to add additional
  41134. --    "external" blocks of memory to the safe_address_list. These are blocks 
  41135. --    of memory that are safe to read/write but which you did not acquire 
  41136. --    through Euphoria's allocate() or allocate_low(). Call 
  41137. --    unregister_block(address) when you want to prevent further access to 
  41138. --    an external block.
  41139.  
  41140. -- 4. Run your program. It might be 10x slower than normal but it's
  41141. --    worth it to catch a nasty bug.
  41142.  
  41143. -- 5. If a bug is caught, you will hear some "beep" sounds.
  41144. --    Press Enter to clear the screen and see the error message. 
  41145. --    There will be a "divide by zero" traceback in ex.err 
  41146. --    (if you are eligible for diagnostic dumps) so you can find the
  41147. --    statement that is making the illegal memory access.
  41148.  
  41149. -- 6. When you are finished debugging and want to run at full speed,
  41150. --    remove or rename the local copy of machine.e (really safe.e) 
  41151. --    in your directory.
  41152.  
  41153. -- This file is equivalent to machine.e, but it overrides the built-in 
  41154. -- routines: 
  41155. --     poke, peek, poke4, peek4s, peek4u, call, mem_copy, and mem_set
  41156. -- and it provides alternate versions of:
  41157. --     allocate, allocate_low, free, free_low
  41158.  
  41159. global integer check_calls
  41160. check_calls = 1   -- check all blocks for boundary corruption after each 
  41161.           -- call(), dos_interrupt(), c_proc(), or c_func(). 
  41162.           -- To save time, your program can turn off this checking by 
  41163.           -- setting check_calls to 0. 
  41164.  
  41165. -- from misc.e and graphics.e:
  41166. constant M_SOUND = 1
  41167.  
  41168. -- Your program will only be allowed to read/write areas of memory
  41169. -- that it allocated (and hasn't freed), as well as areas in low memory 
  41170. -- that you list below, or add dynamically via register_block().
  41171.  
  41172. sequence safe_address_list
  41173. -- Include the starting address and length of any 
  41174. -- acceptable areas of memory for peek/poke here. 
  41175. -- Set allocation number to 0.
  41176. if platform() = 1 then -- DOS32
  41177.     safe_address_list = {
  41178. --      {start , length , allocation_number}        
  41179.     {#A0000, 200*320, 0},   -- mode 19 pixel memory, start & length 
  41180.       --{#B0000, 4000   , 0},   -- monochrome text memory, first page
  41181.     {#B8000, 8000   , 0},   -- color text memory, first page, 50-line mode 
  41182.     {1024  , 100    , 0}    -- keyboard buffer area (roughly)
  41183.     -- add more here
  41184. }
  41185. else
  41186.     safe_address_list = {}
  41187. end if
  41188.  
  41189. with type_check
  41190.  
  41191. puts(1, "\n\t\tUsing Debug Version of machine.e\n")
  41192. atom t
  41193. t = time()
  41194. while time() < t + 3 do
  41195. end while
  41196.  
  41197. constant OK = 1, BAD = 0
  41198. constant M_ALLOC = 16,
  41199.      M_FREE = 17,
  41200.      M_ALLOC_LOW = 32,
  41201.      M_FREE_LOW = 33,
  41202.      M_INTERRUPT = 34,
  41203.      M_SET_RAND = 35,
  41204.      M_USE_VESA = 36,
  41205.      M_CRASH_MESSAGE = 37,
  41206.      M_TICK_RATE = 38,
  41207.      M_GET_VECTOR = 39,
  41208.      M_SET_VECTOR = 40,
  41209.      M_LOCK_MEMORY = 41,
  41210.      M_A_TO_F64 = 46,
  41211.      M_F64_TO_A = 47,
  41212.      M_A_TO_F32 = 48,
  41213.      M_F32_TO_A = 49,
  41214.      M_CRASH_FILE = 57
  41215.  
  41216. -- biggest address on a 32-bit machine
  41217. constant MAX_ADDR = power(2, 32)-1
  41218.  
  41219. -- biggest address accessible to 16-bit real mode
  41220. constant LOW_ADDR = power(2, 20)-1
  41221.  
  41222. type positive_int(integer x)
  41223.     return x >= 1
  41224. end type
  41225.  
  41226. type natural(integer x)
  41227.     return x >= 0
  41228. end type
  41229.  
  41230. type machine_addr(atom a)
  41231. -- a 32-bit non-null machine address 
  41232.     return a > 0 and a <= MAX_ADDR and floor(a) = a
  41233. end type
  41234.  
  41235. type far_addr(sequence a)
  41236. -- protected mode far address {seg, offset}
  41237.     return length(a) = 2 and integer(a[1]) and machine_addr(a[2])
  41238. end type
  41239.  
  41240. type low_machine_addr(atom a)
  41241. -- a legal low machine address 
  41242.     return a > 0 and a <= LOW_ADDR and floor(a) = a
  41243. end type
  41244.  
  41245. function safe_address(atom start, integer len)
  41246. -- is it ok to read/write all addresses from start to start+len-1?
  41247.     atom block_start, block_upper, upper
  41248.     sequence block
  41249.     
  41250.     upper = start + len
  41251.     -- search the list of safe memory blocks:
  41252.     for i = 1 to length(safe_address_list) do
  41253.     block = safe_address_list[i]
  41254.     block_start = block[1]
  41255.     if start >= block_start then 
  41256.         block_upper = block_start + block[2]
  41257.         if upper <= block_upper then
  41258.         if i > 1 then
  41259.             -- move block i to the top and move 1..i-1 down
  41260.             if i = 2 then
  41261.             -- common case, subscript is faster than slice:
  41262.             safe_address_list[2] = safe_address_list[1]
  41263.             else
  41264.             safe_address_list[2..i] = safe_address_list[1..i-1]
  41265.             end if
  41266.             safe_address_list[1] = block
  41267.         end if
  41268.         return OK
  41269.         end if
  41270.     end if
  41271.     end for
  41272.     return BAD -- not found in any safe block
  41273. end function
  41274.  
  41275. procedure die(sequence msg)
  41276. -- Terminate with a message.
  41277. -- makes warning beeps first so you can see what's happening on the screen
  41278.     atom t
  41279.     
  41280.     for i = 1 to 7 do
  41281.     machine_proc(M_SOUND, 1000)
  41282.     t = time()
  41283.     while time() < t + .1 do
  41284.     end while
  41285.     machine_proc(M_SOUND, 0)
  41286.     t = time()
  41287.     while time() < t + .1 do
  41288.     end while
  41289.     end for
  41290.     puts(1, "\n *** Press Enter *** ")
  41291.     if getc(0) then
  41292.     end if
  41293.     if machine_func(5, -1) then -- graphics_mode
  41294.     end if
  41295.     puts(1, "\n\n" & msg & "\n\n")
  41296.     if getc(0) then
  41297.     end if
  41298.     ? 1/0 -- force traceback
  41299. end procedure
  41300.  
  41301. function bad_address(atom a)
  41302. -- show address in decimal and hex  
  41303.     return sprintf(" ADDRESS!!!! %d (#%08x)", {a, a})
  41304. end function
  41305.  
  41306. function original_peek(object x)
  41307.     return peek(x) -- Euphoria's normal peek
  41308. end function
  41309.  
  41310. without warning
  41311. -- override "peek" with debug peek
  41312. global function peek(object x)
  41313. -- safe version of peek 
  41314.     integer len
  41315.     atom a
  41316.     
  41317.     if atom(x) then
  41318.     len = 1
  41319.     a = x
  41320.     else
  41321.     len = x[2]
  41322.     a = x[1]
  41323.     end if
  41324.     if safe_address(a, len) then
  41325.     return original_peek(x)
  41326.     else
  41327.     die("BAD PEEK" & bad_address(a))
  41328.     end if
  41329. end function
  41330.  
  41331. function original_peek4s(object x)
  41332.     return peek4s(x) -- Euphoria's normal peek
  41333. end function
  41334.  
  41335. -- override "peek4s" with debug peek4s
  41336. global function peek4s(object x)
  41337. -- safe version of peek4s 
  41338.     integer len
  41339.     atom a
  41340.     
  41341.     if atom(x) then
  41342.     len = 4
  41343.     a = x
  41344.     else
  41345.     len = x[2]*4
  41346.     a = x[1]
  41347.     end if
  41348.     if safe_address(a, len) then
  41349.     return original_peek4s(x)
  41350.     else
  41351.     die("BAD PEEK4S" & bad_address(a))
  41352.     end if
  41353. end function
  41354.  
  41355. function original_peek4u(object x)
  41356.     return peek4u(x) -- Euphoria's normal peek
  41357. end function
  41358.  
  41359. -- override "peek4u" with debug peek4u
  41360. global function peek4u(object x)
  41361. -- safe version of peek4u 
  41362.     integer len
  41363.     atom a
  41364.     
  41365.     if atom(x) then
  41366.     len = 4
  41367.     a = x
  41368.     else
  41369.     len = x[2]*4
  41370.     a = x[1]
  41371.     end if
  41372.     if safe_address(a, len) then
  41373.     return original_peek4u(x)
  41374.     else
  41375.     die("BAD PEEK4U" & bad_address(a))
  41376.     end if
  41377. end function
  41378.  
  41379. procedure original_poke(atom a, object v)
  41380.     poke(a, v)
  41381. end procedure
  41382.  
  41383. global procedure poke(atom a, object v)
  41384. -- safe version of poke 
  41385.     integer len
  41386.     
  41387.     if atom(v) then
  41388.     len = 1
  41389.     else
  41390.     len = length(v)
  41391.     end if
  41392.     if safe_address(a, len) then
  41393.     original_poke(a, v)
  41394.     else
  41395.     die("BAD POKE" & bad_address(a))
  41396.     end if
  41397. end procedure
  41398.  
  41399. procedure original_poke4(atom a, object v)
  41400.     poke4(a, v)
  41401. end procedure
  41402.  
  41403. global procedure poke4(atom a, object v)
  41404. -- safe version of poke4 
  41405.     integer len
  41406.     
  41407.     if atom(v) then
  41408.     len = 4
  41409.     else
  41410.     len = length(v)*4
  41411.     end if
  41412.     if safe_address(a, len) then
  41413.     original_poke4(a, v)
  41414.     else
  41415.     die("BAD POKE4" & bad_address(a))
  41416.     end if
  41417. end procedure
  41418.  
  41419. procedure original_mem_copy(atom target, atom source, atom len)
  41420.     mem_copy(target, source, len)
  41421. end procedure
  41422.  
  41423. global procedure mem_copy(machine_addr target, machine_addr source, natural len)
  41424. -- safe mem_copy
  41425.     if not safe_address(target, len) then 
  41426.     die("BAD MEM_COPY TARGET" & bad_address(target))
  41427.     elsif not safe_address(source, len) then
  41428.     die("BAD MEM_COPY SOURCE" & bad_address(source))
  41429.     else
  41430.     original_mem_copy(target, source, len)
  41431.     end if
  41432. end procedure
  41433.  
  41434. procedure original_mem_set(atom target, atom value, integer len)
  41435.     mem_set(target, value, len)
  41436. end procedure
  41437.  
  41438. global procedure mem_set(machine_addr target, atom value, natural len)
  41439. -- safe mem_set
  41440.     if safe_address(target, len) then
  41441.     original_mem_set(target, value, len)
  41442.     else
  41443.     die("BAD MEM_SET" & bad_address(target))
  41444.     end if
  41445. end procedure
  41446.  
  41447. atom allocation_num
  41448. allocation_num = 0
  41449. constant BORDER_SPACE = 40
  41450. constant leader = repeat('@', BORDER_SPACE)
  41451. constant trailer = repeat('%', BORDER_SPACE)
  41452.  
  41453. procedure show_byte(atom m)
  41454. -- display byte at memory location m
  41455.     integer c
  41456.     
  41457.     c = original_peek(m)
  41458.     if c <= 9 then
  41459.     printf(1, "%d", c)
  41460.     elsif c < 32 or c > 127 then
  41461.     printf(1, "%d #%02x", {c, c})
  41462.     else
  41463.     if c = leader[1] or c = trailer[1] then
  41464.         printf(1, "%s", c)
  41465.     else
  41466.         printf(1, "%d #%02x '%s'", {c, c, c})
  41467.     end if
  41468.     end if
  41469.     puts(1, ",  ")
  41470. end procedure
  41471.  
  41472. procedure show_block(sequence block_info)
  41473. -- display a corrupted block and die
  41474.     integer len, id, bad, p
  41475.     atom start
  41476.     
  41477.     start = block_info[1]
  41478.     len = block_info[2]
  41479.     id = block_info[3]
  41480.     printf(1, "BLOCK# %d, START: #%x, SIZE %d\n", {id, start, len})
  41481.     -- check pre-block
  41482.     bad = 0
  41483.     for i = start-BORDER_SPACE to start-1 do
  41484.     p = original_peek(i)
  41485.     if p != leader[1] or bad then
  41486.         bad += 1
  41487.         if bad = 1 then
  41488.         puts(1, "DATA WAS STORED ILLEGALLY, JUST BEFORE THIS BLOCK:\n")
  41489.         puts(1, "(" & leader[1] & " characters are OK)\n")
  41490.         printf(1, "#%x: ", i)
  41491.         end if
  41492.         show_byte(i)
  41493.     end if
  41494.     end for
  41495.     puts(1, "\nDATA WITHIN THE BLOCK:\n")
  41496.     printf(1, "#%x: ", start)
  41497.     if len <= 30 then
  41498.     -- show whole block
  41499.     for i = start to start+len-1 do
  41500.         show_byte(i)
  41501.     end for 
  41502.     else
  41503.     -- first part of block
  41504.     for i = start to start+14 do
  41505.         show_byte(i)
  41506.     end for 
  41507.     -- last part of block
  41508.     puts(1, "\n ...\n")
  41509.     printf(1, "#%x: ", start+len-15)
  41510.     for i = start+len-15 to start+len-1 do
  41511.         show_byte(i)
  41512.     end for 
  41513.     end if
  41514.     bad = 0
  41515.     -- check post-block
  41516.     for i = start+len to start+len+BORDER_SPACE-1 do
  41517.     p = original_peek(i)
  41518.     if p != trailer[1] or bad then
  41519.         bad += 1
  41520.         if bad = 1 then
  41521.         puts(1, "\nDATA WAS STORED ILLEGALLY, JUST AFTER THIS BLOCK:\n")
  41522.         puts(1, "(" & trailer[1] & " characters are OK)\n")
  41523.         printf(1, "#%x: ", i)
  41524.         end if
  41525.         show_byte(i)
  41526.     end if
  41527.     end for 
  41528.     die("")
  41529. end procedure
  41530.  
  41531. global procedure check_all_blocks()
  41532. -- Check all allocated blocks for corruption of the leader and trailer areas. 
  41533.     integer n
  41534.     atom a
  41535.     sequence block
  41536.     
  41537.     for i = 1 to length(safe_address_list) do
  41538.     block = safe_address_list[i]
  41539.     if block[3] >= 1 then
  41540.         -- a block that we allocated
  41541.         a = block[1]
  41542.         n = block[2]
  41543.         if not equal(leader, 
  41544.              original_peek({a-BORDER_SPACE, BORDER_SPACE})) then
  41545.         show_block(block)
  41546.         elsif not equal(trailer, 
  41547.              original_peek({a+n, BORDER_SPACE})) then
  41548.         show_block(block)
  41549.         end if          
  41550.     end if
  41551.     end for
  41552. end procedure
  41553.  
  41554. procedure original_call(atom addr)
  41555.     call(addr)
  41556. end procedure
  41557.  
  41558. global procedure call(atom addr)
  41559. -- safe call - machine code must start in block that we own
  41560.     if safe_address(addr, 1) then
  41561.     original_call(addr)
  41562.     if check_calls then
  41563.         check_all_blocks() -- check for any corruption
  41564.     end if
  41565.     else
  41566.     die(sprintf("BAD CALL ADDRESS!!!! %d\n\n", addr))
  41567.     end if
  41568. end procedure
  41569.  
  41570. procedure original_c_proc(integer i, sequence s)
  41571.     c_proc(i, s)
  41572. end procedure
  41573.  
  41574. global procedure c_proc(integer i, sequence s)
  41575.     original_c_proc(i, s)
  41576.     if check_calls then
  41577.     check_all_blocks()
  41578.     end if
  41579. end procedure
  41580.  
  41581. function original_c_func(integer i, sequence s)
  41582.     return c_func(i, s)
  41583. end function
  41584.  
  41585. global function c_func(integer i, sequence s)
  41586.     object r
  41587.     
  41588.     r = original_c_func(i, s)
  41589.     if check_calls then
  41590.     check_all_blocks()
  41591.     end if 
  41592.     return r
  41593. end function
  41594.  
  41595.  
  41596. global procedure register_block(machine_addr block_addr, positive_int block_len)
  41597. -- register an externally-acquired block of memory as being safe to use
  41598.     allocation_num += 1
  41599.     safe_address_list = prepend(safe_address_list, {block_addr, block_len,
  41600.        -allocation_num})
  41601. end procedure
  41602.  
  41603. global procedure unregister_block(machine_addr block_addr)
  41604. -- remove an external block of memory from the safe address list
  41605.     for i = 1 to length(safe_address_list) do
  41606.     if safe_address_list[i][1] = block_addr then
  41607.         if safe_address_list[i][3] >= 0 then
  41608.         die("ATTEMPT TO UNREGISTER A NON-EXTERNAL BLOCK")
  41609.         end if
  41610.         safe_address_list = safe_address_list[1..i-1] &
  41611.                    safe_address_list[i+1..length(safe_address_list)]
  41612.         return
  41613.     end if  
  41614.     end for
  41615.     die("ATTEMPT TO UNREGISTER A BLOCK THAT WAS NOT REGISTERED!")
  41616. end procedure
  41617.  
  41618. function prepare_block(atom a, integer n)
  41619. -- set up an allocated block so we can check it for corruption
  41620.     if a = 0 then
  41621.     die("OUT OF MEMORY!")
  41622.     end if
  41623.     original_poke(a, leader)
  41624.     a += BORDER_SPACE
  41625.     original_poke(a+n, trailer)
  41626.     allocation_num += 1
  41627. --  if allocation_num = ??? then 
  41628. --      trace(1) -- find out who allocated this block number
  41629. --  end if  
  41630.     safe_address_list = prepend(safe_address_list, {a, n, allocation_num})
  41631.     return a
  41632. end function
  41633.  
  41634. global function allocate(positive_int n)
  41635. -- allocate memory block and add it to safe list
  41636.     atom a
  41637.     integer half
  41638.  
  41639.     a = machine_func(M_ALLOC, n+BORDER_SPACE*2)
  41640.     return prepare_block(a, n)
  41641. end function
  41642.  
  41643. global function allocate_low(positive_int n)
  41644. -- allocate memory block and add it to safe list
  41645.     atom a
  41646.     
  41647.     a = machine_func(M_ALLOC_LOW, n+BORDER_SPACE*2)
  41648.     return prepare_block(a, n)
  41649. end function
  41650.  
  41651. global procedure free(machine_addr a)
  41652. -- free address a - make sure it was allocated
  41653.     integer n
  41654.     
  41655.     for i = 1 to length(safe_address_list) do
  41656.     if safe_address_list[i][1] = a then
  41657.         -- check pre and post block areas
  41658.         if safe_address_list[i][3] <= 0 then
  41659.         die("ATTEMPT TO FREE A BLOCK THAT WAS NOT ALLOCATED!")
  41660.         end if
  41661.         n = safe_address_list[i][2]
  41662.         if not equal(leader, original_peek({a-BORDER_SPACE, BORDER_SPACE})) then
  41663.         show_block(safe_address_list[i])
  41664.         elsif not equal(trailer, original_peek({a+n, BORDER_SPACE})) then
  41665.         show_block(safe_address_list[i])
  41666.         end if          
  41667.         machine_proc(M_FREE, a)
  41668.         -- remove it from list
  41669.         safe_address_list = 
  41670.             safe_address_list[1..i-1] &
  41671.             safe_address_list[i+1..length(safe_address_list)]
  41672.         return
  41673.     end if
  41674.     end for
  41675.     die("ATTEMPT TO FREE USING AN ILLEGAL ADDRESS!")
  41676. end procedure
  41677.  
  41678. global procedure free_low(low_machine_addr a)
  41679. -- free low address a - make sure it was allocated
  41680.     integer n
  41681.     
  41682.     if a > 1024*1024 then
  41683.     die("TRYING TO FREE A HIGH ADDRESS USING free_low!")
  41684.     end if
  41685.     for i = 1 to length(safe_address_list) do
  41686.     if safe_address_list[i][1] = a then
  41687.         -- check pre and post block areas
  41688.         if safe_address_list[i][3] <= 0 then
  41689.         die("ATTEMPT TO FREE A BLOCK THAT WAS NOT ALLOCATED!")
  41690.         end if
  41691.         n = safe_address_list[i][2]
  41692.         if not equal(leader, original_peek({a-BORDER_SPACE, BORDER_SPACE})) then
  41693.         show_block(safe_address_list[i])
  41694.         elsif not equal(trailer, original_peek({a+n, BORDER_SPACE})) then
  41695.         show_block(safe_address_list[i])
  41696.         end if          
  41697.         machine_proc(M_FREE_LOW, a)
  41698.         -- remove it from list
  41699.         safe_address_list = 
  41700.             safe_address_list[1..i-1] &
  41701.             safe_address_list[i+1..length(safe_address_list)]
  41702.         return
  41703.     end if
  41704.     end for
  41705.     die("ATTEMPT TO FREE USING AN ILLEGAL ADDRESS!")
  41706. end procedure
  41707.  
  41708. global constant REG_LIST_SIZE = 10
  41709.  
  41710. type register_list(sequence r)
  41711. -- a list of register values
  41712.     return length(r) = REG_LIST_SIZE
  41713. end type
  41714.  
  41715. global function dos_interrupt(integer int_num, register_list input_regs)
  41716. -- call the DOS operating system via software interrupt int_num, using the
  41717. -- register values in input_regs. A similar register_list is returned.
  41718. -- It contains the register values after the interrupt.
  41719.     object r
  41720.     r = machine_func(M_INTERRUPT, {int_num, input_regs})
  41721.     if check_calls then
  41722.     check_all_blocks()
  41723.     end if
  41724.     return r
  41725. end function
  41726.  
  41727.  
  41728. ----------- the rest is identical to machine.e ------------------------------
  41729.  
  41730. type sequence_8(sequence s)
  41731. -- an 8-element sequence
  41732.     return length(s) = 8
  41733. end type
  41734.  
  41735. type sequence_4(sequence s)
  41736. -- a 4-element sequence
  41737.     return length(s) = 4
  41738. end type
  41739.  
  41740. global constant REG_DI = 1,      
  41741.         REG_SI = 2,
  41742.         REG_BP = 3,
  41743.         REG_BX = 4,
  41744.         REG_DX = 5,
  41745.         REG_CX = 6,
  41746.         REG_AX = 7,
  41747.         REG_FLAGS = 8, -- on input: ignored 
  41748.                    -- on output: low bit has carry flag for 
  41749.                    -- success/fail
  41750.         REG_ES = 9,
  41751.         REG_DS = 10
  41752.  
  41753. global function int_to_bytes(atom x)
  41754. -- returns value of x as a sequence of 4 bytes 
  41755. -- that you can poke into memory 
  41756. --      {bits 0-7,  (least significant)
  41757. --       bits 8-15,
  41758. --       bits 16-23,
  41759. --       bits 24-31} (most significant)
  41760. -- This is the order of bytes in memory on 386+ machines.
  41761.     integer a,b,c,d
  41762.     
  41763.     a = remainder(x, #100)
  41764.     x = floor(x / #100)
  41765.     b = remainder(x, #100)
  41766.     x = floor(x / #100)
  41767.     c = remainder(x, #100)
  41768.     x = floor(x / #100)
  41769.     d = remainder(x, #100)
  41770.     return {a,b,c,d}
  41771. end function
  41772.  
  41773. global function bytes_to_int(sequence s)
  41774. -- converts 4-byte peek() sequence into an integer value
  41775.     return s[1] + 
  41776.        s[2] * #100 + 
  41777.        s[3] * #10000 + 
  41778.        s[4] * #1000000
  41779. end function
  41780.  
  41781. global function int_to_bits(atom x, integer nbits)
  41782. -- Returns the low-order nbits bits of x as a sequence of 1's and 0's. 
  41783. -- Note that the least significant bits come first. You can use Euphoria's
  41784. -- and/or/not operators on sequences of bits. You can also subscript, 
  41785. -- slice, concatenate etc. to manipulate bits.
  41786.     sequence bits
  41787.     integer mask
  41788.     
  41789.     bits = repeat(0, nbits)
  41790.     if integer(x) and nbits < 30 then
  41791.     -- faster method
  41792.     mask = 1
  41793.     for i = 1 to nbits do
  41794.         bits[i] = and_bits(x, mask) and 1
  41795.         mask *= 2
  41796.     end for
  41797.     else
  41798.     -- slower, but works for large x and large nbits
  41799.     if x < 0 then
  41800.         x += power(2, nbits) -- for 2's complement bit pattern
  41801.     end if
  41802.     for i = 1 to nbits do
  41803.         bits[i] = remainder(x, 2) 
  41804.         x = floor(x / 2)
  41805.     end for
  41806.     end if
  41807.     return bits
  41808. end function
  41809.  
  41810. global function bits_to_int(sequence bits)
  41811. -- get the (positive) value of a sequence of "bits"
  41812.     atom value, p
  41813.     
  41814.     value = 0
  41815.     p = 1
  41816.     for i = 1 to length(bits) do
  41817.     if bits[i] then
  41818.         value += p
  41819.     end if
  41820.     p += p
  41821.     end for
  41822.     return value
  41823. end function
  41824.  
  41825. global procedure set_rand(integer seed)
  41826. -- Reset the random number generator.
  41827. -- A given value of seed will cause the same series of
  41828. -- random numbers to be generated from the rand() function
  41829.     machine_proc(M_SET_RAND, seed)
  41830. end procedure
  41831.  
  41832. global procedure use_vesa(integer code)
  41833. -- If code is 1 then force Euphoria to use the VESA graphics standard.
  41834. -- This may let Euphoria work better in SVGA modes with certain graphics cards.
  41835. -- If code is 0 then Euphoria's normal use of the graphics card is restored.
  41836. -- Values of code other than 0 or 1 should not be used.
  41837.     machine_proc(M_USE_VESA, code)
  41838. end procedure
  41839.  
  41840. global procedure crash_message(sequence msg)
  41841. -- Specify a final message to display for your user, in the event 
  41842. -- that Euphoria has to shut down your program due to an error.
  41843.     machine_proc(M_CRASH_MESSAGE, msg)
  41844. end procedure
  41845.  
  41846. global procedure crash_file(sequence file_path)
  41847. -- Specify a file name in place of "ex.err" where you want
  41848. -- diagnostic information to be written.
  41849.     machine_proc(M_CRASH_FILE, file_path)
  41850. end procedure
  41851.  
  41852. global procedure tick_rate(atom rate)
  41853. -- Specify the number of clock-tick interrupts per second.
  41854. -- This determines the precision of the time() library routine, 
  41855. -- and also the sampling rate for time profiling.
  41856.     machine_proc(M_TICK_RATE, rate)
  41857. end procedure
  41858.  
  41859. global function get_vector(integer int_num)
  41860. -- returns the current (far) address of the interrupt handler
  41861. -- for interrupt vector number int_num as a 2-element sequence: 
  41862. -- {16-bit segment, 32-bit offset}
  41863.     return machine_func(M_GET_VECTOR, int_num)
  41864. end function
  41865.  
  41866. global procedure set_vector(integer int_num, far_addr a)
  41867. -- sets a new interrupt handler address for vector int_num  
  41868.     machine_proc(M_SET_VECTOR, {int_num, a})
  41869. end procedure
  41870.  
  41871. global procedure lock_memory(machine_addr a, positive_int n)
  41872. -- Prevent a chunk of code or data from ever being swapped out to disk.
  41873. -- You should lock any code or data used by an interrupt handler.
  41874.     machine_proc(M_LOCK_MEMORY, {a, n})
  41875. end procedure
  41876.  
  41877. global function atom_to_float64(atom a)
  41878. -- Convert an atom to a sequence of 8 bytes in IEEE 64-bit format
  41879.     return machine_func(M_A_TO_F64, a)
  41880. end function
  41881.  
  41882. global function atom_to_float32(atom a)
  41883. -- Convert an atom to a sequence of 4 bytes in IEEE 32-bit format
  41884.     return machine_func(M_A_TO_F32, a)
  41885. end function
  41886.  
  41887. global function float64_to_atom(sequence_8 ieee64)
  41888. -- Convert a sequence of 8 bytes in IEEE 64-bit format to an atom
  41889.     return machine_func(M_F64_TO_A, ieee64)
  41890. end function
  41891.  
  41892. global function float32_to_atom(sequence_4 ieee32)
  41893. -- Convert a sequence of 4 bytes in IEEE 32-bit format to an atom
  41894.     return machine_func(M_F32_TO_A, ieee32)
  41895. end function
  41896.  
  41897. global function allocate_string(sequence s)
  41898. -- create a C-style null-terminated string in memory
  41899.     atom mem
  41900.     
  41901.     mem = allocate(length(s) + 1)
  41902.     poke(mem, s & 0)
  41903.     return mem
  41904. end function
  41905.  
  41906. -- This file (unless modified) counts as 0 statements.
  41907. with 447683372 -- delete this statement if it causes an error
  41908.  
  41909. SORT.E
  41910. 1631
  41911.         -------------
  41912.         -- Sorting --
  41913.         -------------
  41914.  
  41915. -- Sort the elements of a sequence into ascending order, using "Shell" sort.
  41916.  
  41917. global function sort(sequence x)
  41918. -- Sort a sequence into ascending order. The elements can be atoms or 
  41919. -- sequences. The standard compare() routine is used to compare elements.
  41920.     integer gap, j, first, last
  41921.     object tempi, tempj
  41922.  
  41923.     last = length(x)
  41924.     gap = floor(last / 3) + 1
  41925.     while 1 do
  41926.     first = gap + 1
  41927.     for i = first to last do
  41928.         tempi = x[i]
  41929.         j = i - gap
  41930.         while 1 do
  41931.         tempj = x[j]
  41932.         if compare(tempi, tempj) >= 0 then
  41933.             j += gap
  41934.             exit
  41935.         end if
  41936.         x[j+gap] = tempj
  41937.         if j <= gap then
  41938.             exit
  41939.         end if
  41940.         j -= gap
  41941.         end while
  41942.         x[j] = tempi
  41943.     end for
  41944.     if gap = 1 then
  41945.         return x
  41946.     else
  41947.         gap = floor(gap / 3) + 1
  41948.     end if
  41949.     end while
  41950. end function
  41951.  
  41952. global function custom_sort(integer custom_compare, sequence x)
  41953. -- Sort a sequence. A user-supplied comparison function is used 
  41954. -- to compare elements.
  41955.     integer gap, j, first, last
  41956.     object tempi, tempj
  41957.  
  41958.     last = length(x)
  41959.     gap = floor(last / 3) + 1
  41960.     while 1 do
  41961.     first = gap + 1
  41962.     for i = first to last do
  41963.         tempi = x[i]
  41964.         j = i - gap
  41965.         while 1 do
  41966.         tempj = x[j]
  41967.         if call_func(custom_compare, {tempi, tempj}) >= 0 then
  41968.             j += gap
  41969.             exit
  41970.         end if
  41971.         x[j+gap] = tempj
  41972.         if j <= gap then
  41973.             exit
  41974.         end if
  41975.         j -= gap
  41976.         end while
  41977.         x[j] = tempi
  41978.     end for
  41979.     if gap = 1 then
  41980.         return x
  41981.     else
  41982.         gap = floor(gap / 3) + 1
  41983.     end if
  41984.     end while
  41985. end function
  41986.  
  41987. -- This file (unless modified) counts as 0 statements.
  41988. with 19276224 -- delete this statement if it causes an error
  41989.  
  41990. WILDCARD.E
  41991. 2654
  41992. -- wildcard.e - wild card matching for strings and DOS file names
  41993.  
  41994. constant TO_LOWER = 'a' - 'A' 
  41995.  
  41996. global function lower(object x)
  41997. -- convert atom or sequence to lower case
  41998.     return x + (x >= 'A' and x <= 'Z') * TO_LOWER
  41999. end function
  42000.  
  42001. global function upper(object x)
  42002. -- convert atom or sequence to upper case
  42003.     return x - (x >= 'a' and x <= 'z') * TO_LOWER
  42004. end function
  42005.  
  42006. function qmatch(sequence p, sequence s)
  42007. -- find pattern p in string s
  42008. -- p may have '?' wild cards (but not '*')
  42009.     integer k
  42010.     
  42011.     if not find('?', p) then
  42012.     return match(p, s) -- fast
  42013.     end if
  42014.     -- must allow for '?' wildcard
  42015.     for i = 1 to length(s) - length(p) + 1 do
  42016.     k = i
  42017.     for j = 1 to length(p) do
  42018.         if p[j] != s[k] and p[j] != '?' then
  42019.         k = 0
  42020.         exit
  42021.         end if
  42022.         k += 1
  42023.     end for
  42024.     if k != 0 then
  42025.         return i
  42026.     end if
  42027.     end for
  42028.     return 0
  42029. end function
  42030.  
  42031. constant END_MARKER = -1
  42032.  
  42033. global function wildcard_match(sequence pattern, sequence string)
  42034. -- returns TRUE if string matches pattern
  42035. -- pattern can include '*' and '?' "wildcard" characters
  42036.     integer p, f, t 
  42037.     sequence match_string
  42038.     
  42039.     pattern = pattern & END_MARKER
  42040.     string = string & END_MARKER
  42041.     p = 1
  42042.     f = 1
  42043.     while f <= length(string) do
  42044.     if not find(pattern[p], {string[f], '?'}) then
  42045.         if pattern[p] = '*' then
  42046.         while pattern[p] = '*' do
  42047.             p += 1
  42048.         end while
  42049.         if pattern[p] = END_MARKER then
  42050.             return 1
  42051.         end if
  42052.         match_string = ""
  42053.         while pattern[p] != '*' do
  42054.             match_string = match_string & pattern[p]
  42055.             if pattern[p] = END_MARKER then
  42056.             exit
  42057.             end if
  42058.             p += 1
  42059.         end while
  42060.         if pattern[p] = '*' then
  42061.             p -= 1
  42062.         end if
  42063.         t = qmatch(match_string, string[f..length(string)])
  42064.         if t = 0 then
  42065.             return 0
  42066.         else
  42067.             f += t + length(match_string) - 2
  42068.         end if
  42069.         else
  42070.         return 0
  42071.         end if
  42072.     end if
  42073.     p += 1
  42074.     f += 1
  42075.     if p > length(pattern) then
  42076.         return f > length(string) 
  42077.     end if
  42078.     end while
  42079.     return 0
  42080. end function
  42081.  
  42082. global function wildcard_file(sequence pattern, sequence filename)
  42083. -- Return 1 (TRUE) if filename matches the wild card pattern.
  42084. -- Similar to DOS wild card matching but better. For example, 
  42085. -- "*ABC.*" in DOS will match *all* files, where this function will 
  42086. -- only match when the file name part has "ABC" at the end.
  42087.     
  42088.     pattern = upper(pattern)
  42089.     filename = upper(filename)
  42090.     if not find('.', pattern) then
  42091.     pattern = pattern & '.'
  42092.     end if
  42093.     if not find('.', filename) then
  42094.     filename = filename & '.'
  42095.     end if
  42096.     return wildcard_match(pattern, filename)
  42097. end function
  42098.  
  42099. -- This file (unless modified) counts as 0 statements.
  42100. with 55041175 -- delete this statement if it causes an error
  42101.  
  42102. HOW2REG.EX
  42103. 23925
  42104. -- Guide to Purchasing the Complete Edition of Euphoria
  42105. -- written by Junko C. Miura of Rapid Deployment Software
  42106. -- If you have trouble running this program, send e-mail 
  42107. -- to: jcmiura@attcanada.net
  42108.  
  42109. include misc.e
  42110. include get.e
  42111. include graphics.e
  42112. include image.e
  42113.  
  42114. -- packages
  42115. constant WIN = "WIN32 + DOS32",
  42116.      DOS = "DOS32",
  42117.      LNX = "Linux",
  42118.      PLNX = " + Linux"
  42119.  
  42120. -- prices
  42121. constant COMPLETE_WIN = 39,
  42122.      COMPLETE_LNX = 25,
  42123.      COMPLETE_ALL = 59,
  42124.      SH = 5,
  42125.      DISCOUNT = 15
  42126.  
  42127. function string(integer amount)
  42128.     return sprintf("%d", amount)
  42129. end function
  42130.  
  42131. constant COMPLETE_WIN_ = string(COMPLETE_WIN),
  42132.      COMPLETE_LNX_ = string(COMPLETE_LNX),
  42133.      COMPLETE_ALL_ = string(COMPLETE_ALL),
  42134.      UPGRADE_WIN_ = string(COMPLETE_WIN - DISCOUNT),
  42135.      UPGRADE_ALL_ = string(COMPLETE_ALL - DISCOUNT),
  42136.      SH_ = string(SH),
  42137.      DISCOUNT_ = string(DISCOUNT)
  42138.  
  42139. constant strEsc = 
  42140.  "Fill in or change the above information. &EPress 'Esc' key when " &
  42141.  "finished&7"
  42142.  
  42143. constant strGreeting0 =
  42144.  "\n\nYou will be asked several questions in the following menu screens. " &
  42145.  "Whether you are registering for the first time, or upgrading, " & 
  42146.  "this tool will select the most " &
  42147.  "convenient way for you to order the Complete Edition " &
  42148.  "of Euphoria. " &
  42149.  "\n\n&4If you want to change any of your choices, you can always " &
  42150.  "run this program again.&7"
  42151.  
  42152. constant strGreeting =
  42153.  "\n\nEuphoria runs on Windows, DOS and Linux platforms." &
  42154.  "\n\nYou can choose from the following selections:" &
  42155.  "\n\t- &9" & WIN & "&7 package ($" & COMPLETE_WIN_ & ")" &
  42156.  "\n\t- &2" & LNX & "&7 package ($" & COMPLETE_LNX_ & ")" &
  42157.  "\n\t- &9" & WIN & "&2" & PLNX & "&7 package ($" & COMPLETE_ALL_ & ")" &
  42158.  "\n\nShipping and handling is $" & SH_ & "." &
  42159.  "\n\nIf you have access to the World Wide Web and you don't require " &
  42160.  "a disk or receipt, you can " &
  42161.  "&4save the shipping and handling cost&7. " &
  42162.  "\n\n&3All prices are in U.S. dollars.&7"
  42163.  
  42164. constant strGreeting1 = 
  42165.  "\n\nWe offer a special discounted price for registered users who wish " &
  42166.  "to upgrade:" &
  42167.  "\n\n\t- Upgrade price of &9" & WIN & "&7 package ($" & UPGRADE_WIN_ &
  42168.  ")\n\t- Upgrade price of &9" & WIN & "&2" & PLNX & "&7 package ($" &
  42169.  UPGRADE_ALL_ & ")\n\n\nTo be eligible for the &9" & WIN & "&7 upgrade " &
  42170.  "price, you must have previously registered for the &9" & WIN &
  42171.  "&7 or &9" & DOS & "&7 package." &
  42172.  "\n\nRegistering for &2" & LNX & "&7-only does &Fnot&7 entitle you to a " &
  42173.  "discount on the &9" & WIN & "&7 package, but does allow you a discount " &
  42174.  "on the &9" & WIN & "&2" & PLNX & "&7 package."
  42175.  
  42176. constant strCC1 = 
  42177.  "\t\t&DOrdering through DigiBuy\n" &
  42178.  "\t\t------------------------&7\n\n" &
  42179.  "You can order Euphoria from DigiBuy using your " & 
  42180.  "&4MasterCard&7,&4 Visa&7,&4 American Express &7or&4 Discover Card&7." &
  42181.  "\n\n\nGo to our Web site:\n\n\t" &
  42182.  "&3http://www.RapidEuphoria.com/ &7\n\n" &
  42183.  "and click \"Register Now On-Line!\""
  42184.  
  42185. constant strCC3 = 
  42186.  "\t\t&DOrdering through DigiBuy (continued)\n" &
  42187.  "\t\t------------------------------------&7\n\n" &
  42188.  "On the DigiBuy ordering page, select "
  42189.    
  42190. constant strCC4 =  
  42191.  "\nFor technical assistance, volume discounts, or any other enquiries " &
  42192.  "please contact Rapid Deployment Software directly.\n\n"
  42193.  
  42194. constant strRDS0 =
  42195.  "\t&DOrdering directly from Rapid Deployment Software (continued)\n" &
  42196.  "\t------------------------------------------------------------&7" 
  42197.  
  42198. constant strRDSGreet =
  42199.  "\t&DOrdering directly from Rapid Deployment Software\n" &
  42200.  "\t------------------------------------------------&7" &
  42201.  "\n\n&4You can order by postal mail directly from " & 
  42202.  "Rapid Deployment Software.&7" &
  42203.  "\n\nYou need to send an order form to RDS by postal mail. \n\nNext, you " &
  42204.  "will be asked some questions, so we can create an order form " &
  42205.  "for you. Send this order form to RDS when you decide to register." &
  42206.  "\n\nFor your convenience, you can print the file &EMYORDER.FRM&7 " &
  42207.  "and send it along with your check or money order. If you don't " &
  42208.  "have a printer, just copy the essential information to a sheet of paper."
  42209.  
  42210. constant strRDSUpgrade =
  42211.  strRDS0 & 
  42212.  "\n\nYou can upgrade to v2.2 and get a discount of $" &
  42213.  DISCOUNT_ & ".00 U.S. \n\nYou must mail us the order form " &
  42214.  "&EMYORDER.FRM&7 that you generate from this tool " &
  42215.  "along with your check."
  42216.  
  42217. constant strRDSFormNotice0 =
  42218.  "&3Please make sure that the following data is correct.&7\n\n"
  42219.  
  42220. constant strRDSOrder = 
  42221.  "\n         Euphoria Complete Edition Order Form v2.2 (or later)" &
  42222.  "\n         ----------------------------------------------------" &
  42223.  "\n\n Enclose a check or money order payable to:\n" &
  42224.  "      Rapid Deployment Software\n" &
  42225.  "      130 Holm Crescent\n" &
  42226.  "      Thornhill, Ontario\n" &
  42227.  "      L3T 5J3\n" &
  42228.  "      CANADA\n\n\n" &
  42229.  " Ship Euphoria to:\n\n"
  42230.  
  42231. constant strRDSFormNotice =
  42232.  strRDS0 & 
  42233.  "\n\n&EMYORDER.FRM&7 has been created in the current directory. " &
  42234.  "&4You can print it and send it with a check or money order to RDS " &
  42235.  "when you are ready.&7 If you don't have a printer, just copy the " &
  42236.  "essential information to a sheet of paper." &
  42237.  "\n\n&3The total cost is U.S. $"
  42238.  
  42239. constant strRDSFormNotice1 =
  42240.  "\n\n&3We can accept a personal check or money order " &
  42241.  "\n\t\tin your country's currency, or " &
  42242.  "\n\t\tin Canadian dollars, or " &
  42243.  "\n\t\tin U.S. dollars." &
  42244.  "\n\nPlease do a fair conversion from the U.S. dollar price.&7 "
  42245.  
  42246. constant strRDSFormNotice2 =
  42247.  "\n\n&3You can make a check or money order at your bank or " &
  42248.  "post office. Please make it in either U.S. dollars, or preferably " &
  42249.  "in Canadian dollars.&7"
  42250.  
  42251. constant strRDSCheck =  
  42252.  strRDS0 & 
  42253.  "\n\nMake your check or money order payable to: " &
  42254.  "\n\n\t    &4Rapid Deployment Software&7 " &
  42255.  "\n\n\t    130 Holm Crescent " &
  42256.  "\n\t    Thornhill, Ontario " &
  42257.  "\n\t    L3T 5J3 " &
  42258.  "\n\t    CANADA " &
  42259.  "\n\n\t    Phone (905) 764-8636 " &
  42260.  "\n\t    Fax   (905) 764-7615\n\n" &
  42261.  "\nand include a print-out of &EMYORDER.FRM&7\n\n"
  42262.  
  42263. --****************************************************************************
  42264. constant TRUE = 1, FALSE = 0, SCREEN = 1 
  42265. constant CR = 13, TAB = 9, ARROW_LEFT = 331, ARROW_RIGHT = 333, 
  42266.      ARROW_UP = 328, ARROW_DOWN = 336, ESC = 27, DELETE = 339,
  42267.      FORM_FEED = 12
  42268. constant USA = 'U', CANADA = 'C', OTHER = 'O'
  42269. constant YES = 'Y', NO = 'N'
  42270. constant WIN_DOS = 'W', LNX_ONLY = 'L'
  42271. integer BS
  42272. if platform() = LINUX then
  42273.     BS = 263
  42274. else
  42275.     BS = 8
  42276. end if
  42277.  
  42278. -- field types and indices of the various fields for the menu screen
  42279. constant STRING = 1, NUMERIC = 2
  42280. constant PROMPT = 1,
  42281.      DATA_TYPE = 2,
  42282.      LINE = 3,
  42283.      COLUMN = 4,
  42284.      DATA_COLUMN = 5,
  42285.      LENGTH = 6,
  42286.      MAX_COLUMN_NO = 7, -- cursor can come, but no entry in THIS column
  42287.      DEFAULT_VALUE = 8,
  42288.      UNIT_PRICE = 9
  42289.     
  42290. constant FINISH = 0, UP = 1, DOWN = 2
  42291.  
  42292.  
  42293. sequence fields -- fields info for the menu screen, definition comes later
  42294. sequence input_values   -- user response to fields
  42295.  
  42296. integer COUNTRY_INDEX, EMAIL_INDEX, UPGRADE_INDEX,
  42297.     SHIPPING_INDEX, PLATFORM_INDEX
  42298.     -- field specific variables and constants finish here
  42299.  
  42300. integer screenWidth, maxNumLines, numColumns, monoMonitor
  42301. integer country, whichPkg, isUpgrade
  42302. integer haveCC
  42303. integer countryOk, downloadOnly, totalPrice, printNow
  42304.  
  42305.  
  42306. function indexLastNonBlankChar(sequence str)
  42307.     integer allBlanks, i
  42308.     
  42309.     i = length(str)
  42310.     allBlanks = TRUE
  42311.     while allBlanks and i >= 1 do
  42312.     if str[i] = ' ' then
  42313.         i -= 1
  42314.     else
  42315.         allBlanks = FALSE
  42316.     end if
  42317.     end while
  42318.     return i
  42319. end function
  42320.  
  42321.  
  42322. procedure set_color(integer color)
  42323.     if monoMonitor then
  42324.     return
  42325.     else
  42326.     text_color(color)
  42327.     end if
  42328. end procedure
  42329.  
  42330.  
  42331. procedure waitResponse(sequence str)
  42332. -- wait for the key response indicated by a parameter   
  42333.     integer char
  42334.     
  42335.     position(maxNumLines, screenWidth - length(str))
  42336.     puts(SCREEN,str) 
  42337.     while TRUE do
  42338.     char = wait_key()
  42339.     if char = CR or '\n' then
  42340.         clear_screen()
  42341.         exit
  42342.     end if
  42343.     end while
  42344. end procedure
  42345.  
  42346.  
  42347. function upper_key()
  42348.     integer char
  42349.     object line
  42350.     
  42351.     line = gets(0)
  42352.     if sequence(line) then
  42353.     char = line[1]
  42354.     else
  42355.     char = CR
  42356.     end if
  42357.     if char >= 'a' and char <= 'z' then
  42358.     char += 'A' - 'a'
  42359.     end if
  42360.     return char
  42361. end function
  42362.  
  42363.  
  42364. procedure color_puts(integer color, object x)
  42365.     set_color(color)
  42366.     puts(SCREEN, x)
  42367.     set_color(WHITE)
  42368. end procedure
  42369.  
  42370.  
  42371. procedure display(sequence paragraph)
  42372. -- neatly display some multi-colored text
  42373.     integer column, i
  42374.  
  42375.     column = 1
  42376.     i = 1
  42377.     while i <= length(paragraph) do
  42378.     if paragraph[i] = '\n' then
  42379.         puts(SCREEN, paragraph[i])
  42380.         column = 1
  42381.     elsif paragraph[i] = '&' then
  42382.         set_color(find(paragraph[i+1], "0123456789ABCDEF")-1)
  42383.         i += 1
  42384.     else    
  42385.         puts(SCREEN, paragraph[i])
  42386.         column += 1
  42387.         if column > numColumns and 
  42388.         (paragraph[i] = ' ' or paragraph[i] = '-') then
  42389.         puts(SCREEN, '\n')
  42390.         column = 1
  42391.         end if
  42392.     end if
  42393.     i += 1
  42394.     end while
  42395. end procedure
  42396.  
  42397.  
  42398. procedure putGreeting(sequence s)
  42399.     color_puts(BRIGHT_MAGENTA, "\n\tHow to Register for the Complete " &
  42400.         "Edition of Euphoria\n\t-----------------------------" &
  42401.         "-----------------------\n\n")
  42402.     display(s)
  42403.     waitResponse("press 'Enter' for NEXT")
  42404. end procedure
  42405.  
  42406.  
  42407. procedure greetings()
  42408.     sequence vc
  42409.     
  42410.     vc = video_config()
  42411.     monoMonitor = not vc[VC_COLOR]
  42412.     screenWidth = vc[VC_COLUMNS]
  42413.     numColumns = screenWidth - 15
  42414.     maxNumLines = vc[VC_LINES]
  42415.     clear_screen()
  42416.     putGreeting(strGreeting0)
  42417.     putGreeting(strGreeting)
  42418.     putGreeting(strGreeting1)
  42419. end procedure
  42420.  
  42421.  
  42422. function ask(sequence str)
  42423.     integer i
  42424.     sequence choices, pos 
  42425.     
  42426.     choices = {}
  42427.     i = 1
  42428.     while i <= length(str) do
  42429.     if str[i] = '&' then
  42430.         i += 1           -- note i is incremented here by one already
  42431.         color_puts(YELLOW, str[i])
  42432.         if str[i] != '_' then
  42433.         choices &= str[i] 
  42434.         end if
  42435.     else
  42436.         puts(SCREEN, str[i])
  42437.     end if
  42438.     i += 1               -- increment i
  42439.     end while
  42440.     
  42441.     if length(choices) > 0 then
  42442.     pos = get_position()
  42443.     position(pos[1], pos[2] - 1)
  42444.     while TRUE do
  42445.         i = find(upper_key(), choices) 
  42446.         if i != 0 then
  42447.         return choices[i]
  42448.         else 
  42449.         puts(SCREEN, "\nPlease enter ")
  42450.         for j = 1 to length(choices) - 2 do
  42451.             color_puts(YELLOW, choices[j])
  42452.             puts(SCREEN, ", ")
  42453.         end for
  42454.         color_puts(YELLOW, choices[length(choices) - 1])
  42455.         puts(SCREEN, " or ")
  42456.         color_puts(YELLOW, choices[length(choices)])
  42457.         puts(SCREEN, ':')
  42458.         end if
  42459.     end while
  42460.     end if
  42461. end function
  42462.  
  42463.  
  42464. procedure CCard()
  42465.     integer cost
  42466.     sequence str
  42467.     
  42468.     clear_screen()
  42469.     display(strCC1)
  42470.     waitResponse("press 'Enter' for NEXT")
  42471.     
  42472.     str = "&4Euphoria "
  42473.     if whichPkg = WIN_DOS then
  42474.     cost = COMPLETE_WIN
  42475.     str = str & "&9" & WIN & " "
  42476.     elsif whichPkg = LNX_ONLY then
  42477.     cost = COMPLETE_LNX
  42478.     str = str & "&2" & LNX & " "
  42479.     else
  42480.     cost = COMPLETE_ALL
  42481.     str = str & "&9" & WIN & "&2" & PLNX & " "
  42482.     end if
  42483.     
  42484.     if isUpgrade = YES then
  42485.     cost = cost - DISCOUNT
  42486.     str &= "&4upgrade, "
  42487.     end if
  42488.     if downloadOnly = NO then
  42489.     cost += SH
  42490.     str &= "&4with shipping and handling"
  42491.     else
  42492.     str &= "&4with download-only option"
  42493.     end if
  42494.     
  42495.     display(strCC3 & str & "&7. The charge will be $" & 
  42496.         string(cost) & ".00 U.S.\n\n" & strCC4)
  42497. end procedure
  42498.  
  42499.  
  42500. procedure displayFields()
  42501.     sequence fieldInsert
  42502.  
  42503.     -- define the description of the various fields for the menu screen
  42504.     COUNTRY_INDEX = 7       -- these are indices into fields, better NOT
  42505.     EMAIL_INDEX = 8         --   to be constants
  42506.     PLATFORM_INDEX = 9
  42507.     UPGRADE_INDEX = 10      -- note that UPGRADE_INDEX and SHIPPING_INDEX are
  42508.     SHIPPING_INDEX = 10     --   the same value
  42509.     
  42510.     fields = 
  42511.     {
  42512.       {"Your Name",       STRING,  5, 7, 27, 35, screenWidth, "", ""},
  42513.       {"Your Address",    STRING,  7, 7, 27, 35, screenWidth, "", ""},
  42514.       {"",                STRING,  8, 7, 27, 35, screenWidth, "", ""},
  42515.       {"",                STRING,  9, 7, 27, 35, screenWidth, "", ""},
  42516.       {"",                STRING, 10, 7, 27, 35, screenWidth, "", ""},
  42517.       {"",                STRING, 11, 7, 27, 35, screenWidth, "", ""},
  42518.       {"Country",         STRING, 12, 7, 27, 30, screenWidth, "", ""},
  42519.       {"E-mail address",  STRING, 14, 7, 27, 35, screenWidth, "", ""}
  42520.     }
  42521.       
  42522.     if whichPkg = WIN_DOS then
  42523.     fields &= 
  42524.     {  
  42525.       {"Complete Edition WIN32 + DOS32          @  $" &
  42526.                   sprintf("%2d.00", COMPLETE_WIN),  
  42527.                   NUMERIC, 18, 7, 62, 2, 64, "1", COMPLETE_WIN}
  42528.     }
  42529.     elsif whichPkg = LNX_ONLY then
  42530.     fields &= 
  42531.     {  
  42532.       {"Complete Edition Linux                  @  $" &
  42533.                   sprintf("%2d.00", COMPLETE_LNX),  
  42534.                   NUMERIC, 18, 7, 62, 2, 64, "1", COMPLETE_LNX}
  42535.     }
  42536.     else
  42537.     fields &= 
  42538.     {  
  42539.       {"Complete Edition WIN32 + DOS32 + Linux  @  $" &
  42540.                   sprintf("%2d.00", COMPLETE_ALL),  
  42541.                   NUMERIC, 18, 7, 62, 2, 64, "1", COMPLETE_ALL}
  42542.     }
  42543.     end if
  42544.     fields &=
  42545.     {  
  42546.       {"shipping/handling                       @  $",
  42547.                   NUMERIC, 19, 7, 62, 2, 64, "1", SH}
  42548.     }
  42549.  
  42550.     fieldInsert =
  42551.       {"upgrade discount                        @ -$" &
  42552.                   sprintf("%2d.00", DISCOUNT),
  42553.                   NUMERIC, 19, 7, 62, 2, 64, "1", -DISCOUNT}
  42554.     
  42555.     if country = USA then
  42556.     fields[COUNTRY_INDEX][DEFAULT_VALUE] = "U.S.A."
  42557.     fields[SHIPPING_INDEX][PROMPT] &= sprintf("%2d.00", SH)
  42558.     elsif country = CANADA then
  42559.     fields[COUNTRY_INDEX][DEFAULT_VALUE] = "CANADA"
  42560.     fields[SHIPPING_INDEX][PROMPT] &= sprintf("%2d.00", SH)
  42561.     else
  42562.     fields[SHIPPING_INDEX][PROMPT] &= sprintf("%2d.00", SH)
  42563.     end if
  42564.     
  42565.     if isUpgrade = YES then
  42566.     fields = append(append(fields[1..PLATFORM_INDEX], fieldInsert),
  42567.             fields[SHIPPING_INDEX])
  42568.     SHIPPING_INDEX += 1
  42569.     fields[SHIPPING_INDEX][LINE] += 1
  42570.     end if
  42571.     
  42572.     if downloadOnly = YES then
  42573.     fields[SHIPPING_INDEX][DEFAULT_VALUE] = "0"
  42574.     end if
  42575.     
  42576.     clear_screen()
  42577.     display(strRDS0)
  42578.  
  42579.     -- display all the prompts
  42580.     for i = 1 to length(fields) do
  42581.     position(fields[i][LINE], fields[i][COLUMN])
  42582.     puts(SCREEN, fields[i][PROMPT])
  42583.     position(fields[i][LINE], fields[i][DATA_COLUMN])
  42584.     puts(SCREEN, repeat('_', fields[i][LENGTH]))
  42585.     position(fields[i][LINE], fields[i][DATA_COLUMN])
  42586.     puts(SCREEN, fields[i][DEFAULT_VALUE])
  42587.     end for
  42588.     position(17, 7)
  42589.     color_puts(RED, "description                                 price" &
  42590.            "   quantity\n")
  42591. end procedure
  42592.  
  42593.  
  42594. function key_gets(integer fieldNo)
  42595.    integer line, init_column, column, indicator, char, maxColNo, num, num1
  42596.    sequence cursor, temp, temp1
  42597.    
  42598.    cursor = get_position()
  42599.    line = cursor[1]
  42600.    init_column = cursor[2]
  42601.    maxColNo = fields[fieldNo][MAX_COLUMN_NO]
  42602.    column = init_column
  42603.    while TRUE do
  42604.     char = wait_key()
  42605.     
  42606.     if char = CR or char = '\n' or char = TAB or char = ARROW_DOWN then
  42607.         indicator = DOWN
  42608.         exit
  42609.     
  42610.     elsif char = ARROW_UP then
  42611.         indicator = UP
  42612.         exit
  42613.  
  42614.     elsif char = ESC then
  42615.         indicator = FINISH
  42616.         exit
  42617.     
  42618.     elsif char = DELETE then
  42619.         if column >= init_column and column < maxColNo then
  42620.         temp = save_text_image({line, column + 1},
  42621.                        {line, maxColNo - 1}) 
  42622.         temp = temp[1]          -- temp now is a single sequence
  42623.         temp1 = ""
  42624.         for j = 1 to length(temp) - 1 by 2 do
  42625.             temp1 = append(temp1, temp[j])
  42626.         end for
  42627.         temp1 = temp1[1..indexLastNonBlankChar(temp1)]
  42628.         puts(SCREEN, temp1)
  42629.         num = fields[fieldNo][DATA_COLUMN] + fields[fieldNo][LENGTH]
  42630.         num1 = column + length(temp1)
  42631.         if num1 < num then      -- num1 is a cursor column position
  42632.             puts(SCREEN, repeat('_', num - num1))
  42633.         else
  42634.             puts(SCREEN, repeat(' ', maxColNo - num1))
  42635.         end if
  42636.         position(line, column)
  42637.         end if
  42638.     
  42639.     elsif char = ARROW_RIGHT then
  42640.         if column < maxColNo then
  42641.         column += 1
  42642.         position(line, column)
  42643.         end if
  42644.         
  42645.     elsif char = BS then
  42646.         if column > init_column then
  42647.         if column < maxColNo then
  42648.             temp = save_text_image({line, column}, 
  42649.                        {line, maxColNo - 1}) 
  42650.             temp = temp[1]          -- temp now is a single sequence
  42651.             temp1 = ""
  42652.             for j = 1 to length(temp) - 1 by 2 do
  42653.             temp1 = append(temp1, temp[j])
  42654.             end for
  42655.             temp1 = temp1[1..indexLastNonBlankChar(temp1)]
  42656.             column -= 1
  42657.             position(line, column)
  42658.             puts(SCREEN, temp1)
  42659.             num = fields[fieldNo][DATA_COLUMN] + 
  42660.               fields[fieldNo][LENGTH]
  42661.             num1 = column + length(temp1)
  42662.             if num1 < num then      -- num1 is a cursor column position
  42663.             puts(SCREEN, repeat('_', num - num1))
  42664.             else
  42665.             puts(SCREEN, repeat(' ', maxColNo - num1))
  42666.             end if
  42667.             position(line, column)
  42668.         elsif column = maxColNo then
  42669.             column -= 1
  42670.             position(line, column)
  42671.         end if
  42672.         end if
  42673.         
  42674.     elsif char = ARROW_LEFT then
  42675.         if column > init_column then
  42676.         column -= 1
  42677.         position(line, column)
  42678.         end if
  42679.         
  42680.     elsif char >= 32  and char <= 255 then
  42681.         if column < maxColNo then
  42682.         puts(SCREEN, char)
  42683.         column += 1
  42684.         end if
  42685.     
  42686.     end if
  42687.     end while
  42688.     return indicator
  42689. end function
  42690.  
  42691.  
  42692. procedure get_data()
  42693. -- get field values from user and return them as a sequence
  42694.     integer fieldNo, keyResults
  42695.     sequence temp, temp1
  42696.  
  42697.     displayFields()
  42698.     position(maxNumLines, screenWidth - length(strEsc))
  42699.     display(strEsc) 
  42700.     
  42701.     -- let the user enter all data
  42702.     fieldNo = 1
  42703.     while TRUE do
  42704.     position(fields[fieldNo][LINE], fields[fieldNo][DATA_COLUMN])
  42705.     keyResults = key_gets(fieldNo)
  42706.     if keyResults = DOWN then
  42707.         if fieldNo < length(fields) then
  42708.         fieldNo += 1
  42709.         else
  42710.         fieldNo = 1
  42711.         end if
  42712.     
  42713.     elsif keyResults = UP then
  42714.         if fieldNo > 1 then
  42715.         fieldNo -= 1
  42716.         end if
  42717.     
  42718.     elsif keyResults = FINISH then
  42719.         exit
  42720.  
  42721.     end if
  42722.     end while
  42723.     
  42724.     -- collect all the input
  42725.     input_values = repeat("", length(fields))
  42726.     totalPrice = 0
  42727.     for i = 1 to length(fields) do
  42728.     temp = save_text_image({fields[i][LINE], fields[i][DATA_COLUMN]},
  42729.              {fields[i][LINE], fields[i][MAX_COLUMN_NO] - 1})
  42730.     temp = temp[1]
  42731.     for j = 1 to length(temp) - 1 by 2 do
  42732.         if temp[j] = '_' then
  42733.         temp[j] = ' '
  42734.         end if
  42735.         input_values[i] = append(input_values[i], temp[j])
  42736.     end for
  42737.     
  42738.     if fields[i][DATA_TYPE] = NUMERIC then
  42739.         temp = value(input_values[i])
  42740.         if temp[1] = GET_SUCCESS then
  42741.         input_values[i] = temp[2]
  42742.         elsif temp[1] = GET_EOF then    -- nothing in the field
  42743.         input_values[i] = 0
  42744.         else        -- non-numeric data in the field. Assign a default.
  42745.         temp1 = value(fields[i][DEFAULT_VALUE])
  42746.         input_values[i] = temp1[2]
  42747.         end if
  42748.         totalPrice += input_values[i] * fields[i][UNIT_PRICE]
  42749.     end if
  42750.     end for
  42751. end procedure
  42752.  
  42753. procedure displayCost()
  42754.     integer fn, k, totalCadPrice
  42755.     
  42756.     clear_screen()
  42757.     display(strRDSFormNotice0)
  42758.     -- display data for user's check on the screen here, then create a file
  42759.     fn = open("myorder.frm", "w")
  42760.     if fn = -1 then
  42761.     display("Can't create MYORDER.FRM ! We will abort execution.")
  42762.     abort(1)
  42763.     end if
  42764.     for j = 1 to 2 do
  42765.     if j = 1 then
  42766.         k = SCREEN
  42767.     else
  42768.         k = fn
  42769.         puts(k, strRDSOrder)
  42770.     end if
  42771.     for i = 1 to length(input_values) do
  42772.         if fields[i][DATA_TYPE] = NUMERIC then
  42773.         printf(k, " %-60s%d\n", {fields[i][PROMPT], input_values[i]})
  42774.         elsif i = EMAIL_INDEX then
  42775.         printf(k, "\n %-20s%s\n\n\n", 
  42776.                {fields[i][PROMPT], input_values[i]})
  42777.         puts(k, " description                                 price" &
  42778.             "       quantity\n")
  42779.         puts(k, " --------------------------------------      -----" &
  42780.             "       --------\n")
  42781.         else 
  42782.         printf(k, " %-20s%s\n", {fields[i][PROMPT], input_values[i]})
  42783.         end if
  42784.     end for
  42785.     printf(k, "%72s\n\n", {"----------------------------"})
  42786.     printf(k, "%51s%5d.00 %s\n", {"Total:", totalPrice, "U.S. dollars"})
  42787.     
  42788.     if country != USA then
  42789.         totalCadPrice = floor(totalPrice * 1.52)
  42790.         printf(k, "%51s%d.00 %s\n", {"(We will also accept ",
  42791.                       totalCadPrice, "Canadian dollars)"})
  42792.     end if
  42793.     puts(k, "\n")
  42794.     end for
  42795.     
  42796.     if input_values[SHIPPING_INDEX] = 0 then
  42797.     puts(fn, "\n\n You will download the Complete Edition software " &
  42798.         "from the \n World Wide Web. Send e-mail to rds@attcanada.net" &
  42799.         " and we will\n give you the necessary " &
  42800.         "instructions. Nothing will be\n shipped to you by postal" &
  42801.         " mail.\n\n")
  42802.     end if
  42803.     puts(fn, 12) -- add a form feed
  42804.     close(fn)
  42805.     
  42806.     waitResponse("press 'Enter' for NEXT")
  42807.     display(strRDSFormNotice)
  42808.     printf(SCREEN, "%d.00", totalPrice)     -- printed in some bright color
  42809.     if country != USA then
  42810.     printf(SCREEN, " (or %d.00 Canadian dollars)", totalCadPrice) 
  42811.     end if
  42812.     set_color(WHITE)                        -- change back the foreground color
  42813.     if country = OTHER then
  42814.     if countryOk = YES then
  42815.         display(strRDSFormNotice1)
  42816.     else
  42817.         display(strRDSFormNotice2)
  42818.     end if
  42819.     end if
  42820.     waitResponse("press 'Enter' for NEXT")
  42821. end procedure
  42822.  
  42823.  
  42824. procedure printRDSOrder()
  42825.     integer p, of, tryAgain
  42826.     object line
  42827.     
  42828.     puts(SCREEN, "\n\nPress any key when your printer is ready.")
  42829.     if wait_key() then
  42830.     end if
  42831.     if platform() = LINUX then
  42832.     system("cat myorder.frm | lpr", 2)
  42833.     else    
  42834.     p = open("PRN", "w")
  42835.     if p = -1 then
  42836.         color_puts(RED, "\n\ncould not open printer. Make sure it " &
  42837.                 "is on and connected.")
  42838.         tryAgain = ask("\n\nWould you like to try again? &Yes or &No &_")
  42839.         if tryAgain = YES then
  42840.         p = open("PRN", "w")
  42841.         if p = -1 then
  42842.             color_puts(RED, "\n\nStill can't open printer. You can " &
  42843.                     "print MYORDER.FRM file at a later time.")
  42844.             waitResponse("press 'Enter' for NEXT")
  42845.             return
  42846.         end if
  42847.         else
  42848.         return
  42849.         end if
  42850.     end if
  42851.     of = open("myorder.frm", "r")
  42852.     if of = -1 then
  42853.         display("\n\nCan't open MYORDER.FRM !")
  42854.         waitResponse("press 'Enter' for NEXT")
  42855.         return
  42856.     end if
  42857.     
  42858.     while TRUE do
  42859.         line = gets(of)
  42860.         if atom(line) then
  42861.         exit
  42862.         end if
  42863.         puts(p, line)
  42864.     end while
  42865.     puts(p, FORM_FEED)
  42866.     close(p)
  42867.     close(of)
  42868.     end if
  42869. end procedure
  42870.  
  42871.  
  42872. procedure RDSOrder()
  42873.     integer create
  42874.     
  42875.     clear_screen()
  42876.     display(strRDSGreet)
  42877.     create = ask("\n\nWould you like to create an order form now? " &
  42878.          "&Yes or &No &_")
  42879.     clear_screen()
  42880.     if create = NO then
  42881.     return
  42882.     end if
  42883.  
  42884.     display(strRDS0)
  42885.     country = ask("\n\nWhich country do you live in, &U.S.A., &Canada " &
  42886.           "or &Other? &_")
  42887.     countryOk = YES         -- USA or Canada currency is accepted
  42888.     if country = OTHER then
  42889.     countryOk = ask("\n\nDo you live in one of the following " &
  42890.         "countries?\n\n\t" &
  42891.         "\n\tAustralia,    Austria,      Barbados,      Belgium, " &
  42892.         "\n\tBritain,      Canada,       Denmark,       Finland, " &
  42893.         "\n\tFrance,       Greece,       Germany,       Hong Kong, " &
  42894.         "\n\tIreland,      Japan,        Mexico,        Netherlands, " &
  42895.         "\n\tNew Zealand,  Norway,       Portugal,      Spain, " &
  42896.         "\n\tSweden,       Switzerland,  United States" &
  42897.         "\n\n\t\t&Yes or &No &_")
  42898.     end if
  42899.     clear_screen()
  42900.  
  42901.     if isUpgrade = YES then
  42902.     display(strRDSUpgrade)
  42903.     waitResponse("press 'Enter' for NEXT")
  42904.     end if
  42905.     get_data()
  42906.     displayCost()
  42907.     display(strRDS0)
  42908.     printNow = ask("\n\nWould you like to print your order form right " &
  42909.            "now? &Yes or &No &_")
  42910.     if printNow = YES then
  42911.     printRDSOrder()     
  42912.     end if
  42913.     clear_screen()
  42914.     display(strRDSCheck)
  42915. end procedure
  42916.  
  42917.  
  42918. -- *** start the main execution part
  42919.     greetings()
  42920.     whichPkg = ask("\nWhich package do you want to purchase?" &
  42921.            "\n&WIN32+DOS32, &Linux or &All three &_")
  42922.     
  42923.     isUpgrade = NO
  42924.     if whichPkg != LNX_ONLY then
  42925.     isUpgrade = ask("\n\nAre you currently a registered user of " &
  42926.             "Euphoria on WIN32 or DOS32? " &
  42927.             "&Yes or &No &_")
  42928.     if isUpgrade = NO and whichPkg != WIN_DOS then
  42929.         isUpgrade = ask("\n\nAre you currently a registered user of " &
  42930.                 "Euphoria on Linux? " &
  42931.                 "&Yes or &No &_")
  42932.     end if
  42933.     end if
  42934.     
  42935.     downloadOnly = ask("\n\nWould you like to take advantage of the " &
  42936.                "\"Download-only\" option? &Yes or &No &_") 
  42937.     
  42938.     -- keep up-to-date which CCards are accepted by DigiBuy all the time !  
  42939.     haveCC = ask("\n\nDo you have a credit card, such as\n\t\t" &
  42940.          "MasterCard, \n\t\tVisa, \n\t\tAmerican Express " &
  42941.          "or \n\t\tDiscover Card, \n\tand do you want to " & 
  42942.          "use it? \n\t\t\t&Yes or &No &_")
  42943.     
  42944.     if haveCC = YES then
  42945.     CCard()
  42946.     else
  42947.     RDSOrder()
  42948.     end if          
  42949.  
  42950. REGISTER.DOC
  42951. 5096
  42952.  
  42953.  
  42954.                 Ordering the Complete Edition of Euphoria 
  42955.  
  42956.  
  42957.  1. What You Get
  42958.  ===============
  42959.  
  42960.  Euphoria runs on Windows, DOS and Linux platforms. You can choose from the
  42961.  following packages:
  42962.  
  42963.      New Registrations:
  42964.         WIN32 + DOS32 ........... $39
  42965.         Linux  .................. $25
  42966.         WIN32 + DOS32 + Linux  .. $59
  42967.      
  42968.      Upgrades:   
  42969.         WIN32 + DOS32 ........... $24
  42970.         WIN32 + DOS32 + Linux ... $44
  42971.  
  42972.  
  42973.  Low cost upgrade prices are available to all registered users of Euphoria
  42974.  (from v1.0 onward). To get the upgrade price on a package, you must have
  42975.  previously registered Euphoria on one of the platforms contained in that
  42976.  package. For example, to be eligible for the WIN32 + DOS32 upgrade price, you
  42977.  must have previously registered Euphoria for WIN32 + DOS32, or just DOS32. To
  42978.  be eligible for the WIN32 + DOS32 + Linux upgrade price, you must simply be a
  42979.  registered user of Euphoria on any platform.
  42980.  
  42981.  All prices are in U.S. dollars. Shipping of a 3.5" floppy disk to any country,
  42982.  if required, costs $5. If you don't require a disk or a receipt, you can
  42983.  download the Complete Edition software from our Web site and avoid the
  42984.  shipping charge.
  42985.  
  42986.  When you register or upgrade, you get:
  42987.  
  42988.       * versions of ex.exe (DOS32) and exw.exe (WIN32), and/or exu (Linux) with
  42989.         full, greater than 300 statements, diagnostic support
  42990.  
  42991.       * the ability to bind and shroud Euphoria programs for easy use and
  42992.         distribution
  42993.  
  42994.       * execution-count profiling, to analyze your program's logic, and improve
  42995.         performance
  42996.  
  42997.       * time profiling, to discover performance bottlenecks (DOS32 only)
  42998.  
  42999.       * a discount on all future releases of Euphoria for the platforms that
  43000.         you have registered
  43001.  
  43002.       * 6 months of free technical support from Rapid Deployment Software
  43003.  
  43004.       * 6 months of free software upgrades to the package you registered or
  43005.         upgraded
  43006.  
  43007.       * the ability to vote in the Euphoria Micro-Economy and encourage others
  43008.         to develop software that you find useful. (See web.doc or the RDS Web
  43009.         site for details on the Micro-Economy.)
  43010.  
  43011.  Free upgrades consist of downloading improved official-release software from
  43012.  the Web. You must have registered or upgraded within 6 months of a new
  43013.  *official* release (alpha-test and beta-test releases aren't considered).
  43014.  
  43015.  If you have earned money in the Euphoria Micro-Economy, please contact RDS
  43016.  (rds@attcanada.net) for details on how to reduce the price.
  43017.  
  43018.  
  43019.  2. Methods of Registering
  43020.  =========================
  43021.  
  43022.  2.1 Credit Card Orders
  43023.  ----------------------
  43024.  
  43025.  You can register or upgrade Euphoria through DigiBuy using your MasterCard,
  43026.  Visa, American Express or Discover Card. Go to our Web site:
  43027.  
  43028.         http://www.RapidEuphoria.com
  43029.  
  43030.  and click "Register Now On-Line!" DigiBuy has a secure server that lets your
  43031.  Web browser encrypt your credit card information before sending it across the
  43032.  Internet.
  43033.  
  43034.  If you choose to download the Complete Edition, we will send the instructions
  43035.  to the e-mail address that you provide to DigiBuy. This usually happens the
  43036.  same day, or early the next day. If you choose to receive a disk (and receipt)
  43037.  we will assume that you don't need the instructions. E-mail us if you do - we
  43038.  will give you the instructions, while still shipping your disk and receipt.
  43039.  
  43040.  With DigiBuy, there are no extra sales taxes to pay, unless you are a resident
  43041.  of Connecticut, Minnesota or Washington States.
  43042.  
  43043.  
  43044.  2.2 Paying with a Check or Money Order
  43045.  --------------------------------------
  43046.  
  43047.  There is a program, how2reg.ex, in the euphoria\register directory that will
  43048.  ask you questions and advise you on how to order.
  43049.  
  43050.  Just type:
  43051.  
  43052.         ex how2reg
  43053.    
  43054.  or on Linux:
  43055.         
  43056.         exu how2reg.ex
  43057.  
  43058.  Run how2reg any time, and rerun it as many times as you like. You are not
  43059.  committed to registering just by running it. Run how2reg for upgrade orders as
  43060.  well.
  43061.  
  43062.  After running how2reg, print MYORDER.FRM or simply copy the information to a
  43063.  sheet of paper, before mailing it to RDS with your check or money order.
  43064.  
  43065.  We prefer U.S. or Canadian currency. However, we can accept personal checks
  43066.  from any of the following countries:
  43067.  
  43068.      Australia, Austria, Barbados, Belgium, Britain, Canada, Denmark, Finland,
  43069.      France, Greece, Germany, Hong Kong, Ireland, Japan, Mexico, Netherlands,
  43070.      New Zealand, Norway, Portugal, Spain, Sweden, Switzerland, United States
  43071.  
  43072.      Please do a fair conversion from our U.S. dollar prices to your local
  43073.      currency.
  43074.  
  43075.  Make your check or money order payable to:
  43076.  
  43077.          Rapid Deployment Software
  43078.  
  43079.          130 Holm Crescent
  43080.          Thornhill, Ontario
  43081.          L3T 5J3
  43082.          CANADA
  43083.  
  43084.  
  43085.  There are no extra sales taxes to pay.
  43086.  
  43087.  
  43088.  3. Return Policy
  43089.  ================
  43090.  
  43091.  Since you have ample opportunity to "try before you buy" we do not accept
  43092.  returns. However, if the disk is damaged or lost in transit we will send you a
  43093.  new one free of charge.
  43094.  
  43095.  
  43096.  
  43097. APPEND.EX
  43098. 1349
  43099. with trace
  43100. trace(1)
  43101.  
  43102. -- Action Tutorial #5 - Append and Prepend to a Sequence
  43103.  
  43104. -- To run this tutorial, 
  43105. --        Press Enter to execute the highlighted Euphoria statement.
  43106. --        Press F1 to flip to the main output screen.
  43107. --        Press F2 to flip back to this trace screen.
  43108. --        Read the comments as you go.
  43109.  
  43110. -- We will:
  43111. --        1. make a sequence of 15 random numbers
  43112. --        2. append() all the even numbers into a variable called "even"
  43113. --        3. prepend() all the odd numbers into a variable called "odd"
  43114.  
  43115. sequence even, odd, random
  43116. even = {} -- it's a sequence, but it contains 0 elements
  43117.  
  43118. odd = {}  -- the same
  43119.  
  43120. random = repeat(30, 15) -- 30 repeated 15 times
  43121.  
  43122. random = rand(random)    -- 15 random numbers between 1 and 30
  43123.  
  43124. integer num -- convenient place to put the next number
  43125.  
  43126. -- Now we'll put the even numbers into even using append()
  43127. for i = 1 to length(random) do
  43128.     num = random[i]  -- the next random number
  43129.     -- if the remainder after dividing by 2 is 0, the number is even
  43130.     if remainder(num, 2) = 0 then
  43131.     even = append(even, num) -- add number at the end
  43132.     else
  43133.     odd = prepend(odd, num) -- add number on at the beginning
  43134.     end if
  43135. end for
  43136.  
  43137. -- display the even numbers
  43138. puts(1, "The even numbers are:\n")
  43139. ? even  -- check it with F1/F2
  43140.  
  43141. -- display the odd numbers
  43142. puts(1, "The odd numbers are:\n")
  43143. ? odd
  43144.  
  43145. CALC.EX
  43146. 687
  43147. with trace
  43148. trace(1)
  43149.  
  43150. -- Action tutorial #2 - evaluate simple expressions
  43151.  
  43152. -- To run this tutorial, keep pressing the Enter key 
  43153. -- to execute the next statement, and the F1 and F2
  43154. -- keys to flip between the main screen and this trace screen.
  43155.  
  43156. -- Step 1 - We can use the question mark (?) to print
  43157. -- the value of any expression on the screen. Let's
  43158. -- calculate 2+2
  43159. ? 2 + 2
  43160. -- Press F1 then F2 to see the result printed on the screen.
  43161.  
  43162. -- Let's try something a bit harder:
  43163. ? 3 * 3 * sqrt(16)
  43164. -- Press F1 then F2 to see the result (and the previous result)
  43165. -- printed on the screen.
  43166.  
  43167. -- Notice that multiply has higher precedence than addition:
  43168. ? 2 * 3 + 4 * 5
  43169.  
  43170.  
  43171. CELCIUS.EX
  43172. 1310
  43173. include get.e -- so we can use the prompt_number() function
  43174.  
  43175. with trace
  43176. trace(1)
  43177. -- Action Tutorial #4 - Convert Fahrenheit to Celcius
  43178.  
  43179. -- To run this tutorial, 
  43180. --        Press Enter to execute the highlighted Euphoria statement.
  43181. --        Press F1 to flip to the main output screen.
  43182. --        Press F2 to flip back to this trace screen.
  43183. --        Read the comments as you go.
  43184.  
  43185. -- In this tutorial we will:
  43186. --          1. Ask the user to enter a Fahrenheit temperature
  43187. --          2. Read a number from the user
  43188. --          3. Convert the number to Celcius
  43189. --          4. Print the result on the screen
  43190.  
  43191. -- Some variables:
  43192. atom ftemp     -- holds Fahrenheit temperature
  43193. atom ctemp     -- holds Celcius temperature
  43194.  
  43195. -- Prompt the user to enter a number:
  43196. -- We included the file "get.e", so we can use prompt_number().
  43197. ftemp = prompt_number("Enter a Fahrenheit temperature: ", {})
  43198. -- {} means the user can enter any number. 
  43199. -- If we said {10,20} he would have to enter a number from 10 to 20.
  43200.  
  43201. -- Now, using the magic formula, convert it to Celcius:
  43202. ctemp = 5/9 * (ftemp - 32)
  43203.  
  43204. -- Now print the Celcius temperature:
  43205. ? ctemp
  43206.  
  43207. -- To be neat, we can print exactly 2 decimal places
  43208. -- by calling printf() - formatted print
  43209. printf(1, "with two decimal places: %.2f\n", ctemp)
  43210.  
  43211. EXAMPLE.EX
  43212. 1155
  43213.         -------------------------------------
  43214.         -- Example Program from the Manual --
  43215.         -------------------------------------
  43216.  
  43217. function merge_sort(sequence x)
  43218. -- put x into ascending order using a recursive merge sort
  43219.     integer n, mid
  43220.     sequence merged, a, b
  43221.  
  43222.     n = length(x)
  43223.     if n = 0 or n = 1 then
  43224.     return x  -- trivial case
  43225.     end if
  43226.  
  43227.     mid = floor(n/2)
  43228.     a = merge_sort(x[1..mid])       -- sort first half of x 
  43229.     b = merge_sort(x[mid+1..n])     -- sort second half of x
  43230.  
  43231.     -- merge the two sorted halves into one
  43232.     merged = {}
  43233.     while length(a) > 0 and length(b) > 0 do
  43234.     if compare(a[1], b[1]) < 0 then
  43235.         merged = append(merged, a[1])
  43236.         a = a[2..length(a)]
  43237.     else
  43238.         merged = append(merged, b[1])
  43239.         b = b[2..length(b)]
  43240.     end if
  43241.     end while
  43242.     return merged & a & b  -- merged data plus leftovers
  43243. end function
  43244.  
  43245. procedure print_sorted_list()
  43246. -- generate sorted_list from list 
  43247.     ? merge_sort( {9, 10, 3, 1, 4, 5, 8, 7, 6, 2} )
  43248.     ? merge_sort( {1.5, -9, 1e6, 100} )
  43249.     printf(1, "%s, %s, %s\n", merge_sort({"oranges", "apples", "bananas"}))  
  43250. end procedure
  43251.  
  43252. print_sorted_list()     -- this command starts the program 
  43253.  
  43254. GETC.EX
  43255. 1614
  43256. with trace
  43257. trace(1)
  43258.  
  43259. -- Action Tutorial #6 - Read a File: One character at a time
  43260. -- To run this tutorial, 
  43261. --        Press Enter to execute the highlighted Euphoria statement.
  43262. --        Press F1 / F2 to flip to the main output screen.
  43263. --        Press down-arrow to execute quickly to the end of a loop
  43264.  
  43265. -- We will:
  43266. --        1. open the "tutorial.doc" file in this directory
  43267. --        2. count the number of new-line, '\n', characters
  43268. --        3. print the number of new-lines
  43269. --        4. close the file
  43270.  
  43271. integer fn    -- the file number
  43272. integer lines -- the number of lines ('\n' characters)
  43273. integer c     -- the next character from the file
  43274.  
  43275. -- First, we try to open the file called "tutorial.doc"
  43276. fn = open("tutorial.doc", "r")
  43277. if fn = -1 then
  43278.     puts(1, "Can't open tutorial.doc\n")
  43279.     abort(1)
  43280. end if
  43281. -- By successfully opening the file we have established that 
  43282. -- the file exists, and open() gives us a file number (or "handle") 
  43283. -- that we can use to perform operations on the file.
  43284.  
  43285. lines = 0
  43286. while 1 do   -- this is always true - apparently an "infinite" loop
  43287.     c = getc(fn)
  43288.     if c = -1 then
  43289.     exit -- no more characters, end of file, 
  43290.          -- this is how we quit the loop
  43291.     end if
  43292.     if c = '\n' then
  43293.     lines = lines + 1  -- assume one \n per line in the file
  43294.     end if
  43295.     -- When you get bored, 
  43296.     -- Press down-arrow until you are out of the loop
  43297. end while
  43298.  
  43299. -- print the total number of lines
  43300. ? lines
  43301.  
  43302. -- close the tutorial.doc file 
  43303. -- This is not really necessary, but you can only have 
  43304. -- 25 files open at any one time.
  43305. close(fn)
  43306.  
  43307. GETS.EX
  43308. 1804
  43309. with trace
  43310. trace(1)
  43311.  
  43312. -- Action Tutorial #7 - Read a File: One line at a time
  43313. -- To run this tutorial, 
  43314. --        Press Enter to execute the highlighted Euphoria statement.
  43315. --        Press F1 / F2 to flip to the main output screen.
  43316. --        Press down-arrow to execute quickly to the end of a loop
  43317.  
  43318. -- We will:
  43319. --        1. open the "tutorial.doc" file in this directory
  43320. --        2. See how many lines contain the word "Euphoria"
  43321. --        3. print the lines containing "Euphoria"
  43322. --        4. close the file
  43323.  
  43324. integer fn    -- the file number
  43325. integer e     -- the number of lines that contain "Euphoria"
  43326. object line   -- the next line from the file
  43327.  
  43328. -- First, we try to open the file called "tutorial.doc"
  43329. fn = open("tutorial.doc", "r")
  43330. if fn = -1 then
  43331.     puts(1, "Can't open tutorial.doc\n")
  43332.     abort(1)
  43333. end if
  43334. -- By successfully opening the file we have established that 
  43335. -- the file exists, and open() gives us a file number (or "handle") 
  43336. -- that we can use to perform operations on the file.
  43337.  
  43338. e = 0
  43339. while 1 do   -- this is always true - apparently an "infinite" loop
  43340.     line = gets(fn)
  43341.     if atom(line) then
  43342.     exit -- no more lines, end of file, 
  43343.          -- this is how we quit the loop
  43344.     end if
  43345.     if match("Euphoria", line) then
  43346.     e = e + 1 
  43347.     end if
  43348.     -- When you get bored, 
  43349.     -- Press down-arrow until you are out of the loop
  43350. end while
  43351.  
  43352. -- Print the total number of lines containing "Euphoria".
  43353. -- We need \" to get a double-quote within a string.
  43354. -- %d formats for an integer value in base 10 (decimal)
  43355. -- 1 prints to the screen (standard output)
  43356. printf(1, "%d lines contain \"Euphoria\"\n", e)
  43357.  
  43358. -- close the tutorial.doc file 
  43359. -- This is not really necessary, but you can only have 
  43360. -- 25 files open at any one time.
  43361. close(fn)
  43362.  
  43363. HELLO.EX
  43364. 798
  43365. with trace
  43366. trace(1)
  43367.  
  43368. -- Action Tutorial #1 - Print Hello World on the Screen
  43369.  
  43370. -- To run this tutorial, 
  43371. --        Press Enter to execute the highlighted Euphoria statement.
  43372. --        Press F1 to flip to the main output screen.
  43373. --        Press F2 to flip back to this trace screen.
  43374. --        Read the comments as you go.
  43375.  
  43376. -- Step 1: Just to be neat - we'll clear the screen.
  43377. -- First, press F1 then F2.
  43378. -- Then press Enter:
  43379. clear_screen() 
  43380. -- Check again with F1/F2 - was the screen cleared?
  43381.  
  43382. -- Step 2: Let's position the cursor at line 10, column 30
  43383. position(10, 30)  
  43384. -- Is the cursor now at 10,30? Press F1/F2
  43385.  
  43386. -- Step 3: Display the text:
  43387. puts(1, "Hello World")  
  43388. -- Is the text there? Press F1/F2
  43389.  
  43390. -- Step 4 Output 2 blank lines and we're done
  43391. puts(1, "\n\n")
  43392.  
  43393.  
  43394.  
  43395. LEARN.EX
  43396. 2774
  43397.     -----------------------------------------------
  43398.     -- A Quiz to Test Your Knowledge of Euphoria --
  43399.     -----------------------------------------------
  43400. include get.e
  43401. include graphics.e
  43402.  
  43403. constant NTRYS = 3
  43404. constant KEYBOARD = 0, SCREEN = 1
  43405.  
  43406. procedure get_answer(object correct)
  43407.     sequence answer
  43408.     atom t
  43409.     integer c
  43410.     
  43411.     for i = 1 to NTRYS do
  43412.     answer = get(KEYBOARD)
  43413.     puts(SCREEN, '\n')
  43414.     if answer[1] = GET_SUCCESS then
  43415.         if equal(answer[2], correct) then
  43416.         puts(SCREEN, "Correct!\n\n")
  43417.         sound(2000)
  43418.         t = time()
  43419.         while time() < t+0.1 do
  43420.         end while
  43421.         sound(0)
  43422.         return
  43423.         elsif i < NTRYS then
  43424.         puts(SCREEN, "Try again\n")
  43425.         sound(200)
  43426.         t = time()
  43427.         while time() < t+0.4 do
  43428.         end while
  43429.         sound(0)
  43430.         end if
  43431.     else
  43432.         puts(SCREEN, "syntax error - a Euphoria object is expected\n")
  43433.         -- clear rest of line:
  43434.         for j = 1 to 100 do
  43435.         c = getc(KEYBOARD)
  43436.         if c = -1 then
  43437.             abort(0)
  43438.         elsif c = '\n' then
  43439.             exit
  43440.         end if
  43441.         end for 
  43442.     end if    
  43443.     end for
  43444.     puts(SCREEN, "The correct answer was: ")
  43445.     print(SCREEN, correct)
  43446.     puts(SCREEN, '\n')
  43447. end procedure
  43448.  
  43449. procedure part1()
  43450. -- evaluating simple expressions
  43451.     object x, y
  43452.  
  43453.     puts(SCREEN, "Please evaluate the following Euphoria expressions\n")
  43454.     puts(SCREEN, "You have 3 guesses.\n\n")
  43455.  
  43456.     x = rand(10)
  43457.     y = rand(10)
  43458.     printf(SCREEN, "%d + %d\n", {x, y})
  43459.     get_answer(x + y)
  43460.  
  43461.     x = rand(repeat(10, 3))
  43462.     y = rand(10)
  43463.     print(SCREEN, x)
  43464.     puts(SCREEN, " * ")
  43465.     print(SCREEN, y)
  43466.     puts(SCREEN, '\n')
  43467.     get_answer(x * y)
  43468.  
  43469.     x = rand(repeat(10, 4)) - 5
  43470.     y = rand(repeat(10, 4)) - 5
  43471.     print(SCREEN, x)
  43472.     puts(SCREEN, " > ")
  43473.     print(SCREEN, y)
  43474.     puts(SCREEN, '\n')
  43475.     get_answer(x > y)    
  43476.  
  43477.     x = rand(20)
  43478.     y = rand(5)
  43479.     puts(SCREEN, "repeat(")
  43480.     print(1, x)
  43481.     puts(SCREEN, ", ")
  43482.     print(1, y)
  43483.     puts(SCREEN, ")\n")
  43484.     get_answer(repeat(x, y))
  43485.     
  43486.     x = rand(repeat(25, 3)) + 'a'
  43487.     y = rand(repeat(25, 2)) + 'a'
  43488.     printf(SCREEN, "\"%s\" & \"%s\"\n", {x, y})
  43489.     get_answer(x & y)
  43490.  
  43491.     x = rand(repeat(99,3))
  43492.     y = rand(repeat(99,2))
  43493.     puts(SCREEN, "append(")
  43494.     print(SCREEN, x)
  43495.     puts(SCREEN, ", ")
  43496.     print(SCREEN, y)
  43497.     puts(SCREEN, ")\n")
  43498.     get_answer(append(x, y))
  43499.     
  43500.     puts(SCREEN, "what will the value of x be\n")
  43501.     puts(SCREEN, "after executing the following statements?\n")
  43502.     puts(SCREEN, "x = ")
  43503.     x = rand({10, 10, {10, 10, 10, 10}, 20})
  43504.     print(SCREEN, x)
  43505.     y = rand({20, 20, 20, 20, 20})
  43506.     puts(SCREEN, "\ny = ")
  43507.     print(SCREEN, y)
  43508.     puts(SCREEN, "\nx[3][2..3] = y[4..5]\n")    
  43509.     x[3][2..3] = y[4..5]
  43510.     get_answer(x)
  43511. end procedure
  43512.  
  43513. part1()   -- quick questions
  43514.  
  43515. SEQCALC.EX
  43516. 1078
  43517. with trace
  43518. trace(1)
  43519.  
  43520. -- Action Tutorial #3 - Sequences
  43521.  
  43522. -- To run this tutorial, keep pressing the Enter key 
  43523. -- to execute the next statement, and the F1 and F2
  43524. -- keys to flip between the main screen and this trace screen.
  43525.  
  43526. -- The most important feature of Euphoria is the "sequence".
  43527. -- Once you learn how sequences work, everything else is easy.
  43528.  
  43529. -- A sequence is just a collection of numbers, sort of like the
  43530. -- "array" in other programming languages, but much more flexible.
  43531. -- Here's an example of a simple sequence:
  43532. --               {5, 1, 9}
  43533. -- It's a collection of 3 numbers. The order is important.
  43534. -- {5,1,9} is certainly *not* equivalent to {1,9,5}.
  43535.  
  43536. -- Let's try some calculations:
  43537. ? {5, 1, 9}
  43538. ? {5, 1, 9} * 2
  43539. ? {5, 1, 9} + {5, 1, 9}
  43540. -- Euphoria lets you perform arithmetic calculations on sequences.
  43541. -- The rules are fairly intuitive. You can also store a sequence
  43542. -- into a variable. First you have to declare a variable that
  43543. -- is allowed to hold a sequence:
  43544. sequence fred
  43545.  
  43546. fred = {5,1,9}
  43547. ? fred
  43548. ? fred * 2
  43549. ? fred + fred
  43550.  
  43551.  
  43552.  
  43553. SIMPLE.EX
  43554. 593
  43555.     --------------------------------
  43556.     -- A very simple sort program --
  43557.     --------------------------------
  43558. with trace -- make everything traceable
  43559. trace(1)   -- turn on tracing
  43560.  
  43561. function simple_sort(sequence x)
  43562. object temp 
  43563.     for i = 1 to length(x) - 1 do
  43564.     for j = i + 1 to length(x) do
  43565.         if compare(x[j],x[i]) < 0 then
  43566.         -- swap x[j], x[i]
  43567.         temp = x[j]    
  43568.         x[j] = x[i]
  43569.         x[i] = temp
  43570.         end if
  43571.     end for
  43572.     end for
  43573.     return x
  43574. end function
  43575.  
  43576. -- Hold down the Enter key and 
  43577. -- watch x get sorted before your eyes! 
  43578. ? simple_sort( {9, 10, 3, 1, 4, 5, 8, 7, 6, 2} )
  43579. TUTORIAL.DOC
  43580. 1573
  43581.     
  43582.             Euphoria Tutorial Programs
  43583.             --------------------------
  43584.  
  43585.  To make learning Euphoria easier, and more fun, we have created some
  43586.  simple programs that you can run in trace mode. They show you step-by-step 
  43587.  how to do common operations like reading in numbers, printing numbers, 
  43588.  opening files etc. There are comments on most of the statements so someone 
  43589.  who is new to Euphoria, or new to programming, can understand exactly how 
  43590.  each program works. Most of the programs do not do anything useful, but they
  43591.  cover topics that sometimes are confusing to beginners.
  43592.  
  43593.  Hopefully these "Action Tutorials" will be more stimulating for you than 
  43594.  simply reading a lot of dull text. You can actually watch each program
  43595.  executing, from the inside out, and see the values of variables etc.
  43596.  
  43597.  Once you understand these programs, you might want to download David Gay's
  43598.  "Beginner's Guide to Euphoria", or other tutorials available on the Web.
  43599.  
  43600.  Action Tutorials
  43601.  ----------------
  43602.  
  43603.  Suggested Order:
  43604.  
  43605.     1. hello.ex - Hello World
  43606.     
  43607.     2. celcius.ex - Fahrenheit to Celsius converter
  43608.     
  43609.     3. calc.ex - Simple Calculations
  43610.     
  43611.     4. seqcalc.ex - Calculations on Sequences
  43612.     
  43613.     5. append.ex - append() and prepend()
  43614.     
  43615.     6. getc.ex - reading a file - one character at a time
  43616.     
  43617.     7. gets.ex - reading a file - one line at a time
  43618.     
  43619.     8. simple.ex - watch a simple sorting algorithm at work
  43620.     
  43621.     9. example.ex - the merge sort example from REFMAN.DOC
  43622.     
  43623.     10. learn.ex - test your knowledge!
  43624.     
  43625.