Text mode

From EuWiki

Jump to: navigation, search


With the change from eu 2.5 to eu 3.0, euphoria lost the static binding to the ncurses library. While this may have pleased some people, other people may not be so pleased to know that fundamental, but not insurmountable changes were made to displaying characters, and to inputting characters.

Displaying of characters has changed internally, but not to the end user, ie printing in colours and positioning the cursor has not changed when controlled from euphoria, and as such will not be dealt with any further here.

However, retrieving characters using wait_key() and get_key has changed drastically.

With eu2.5 or less, using wait_key() or get_key() returned only one integer. with eu3.0, using either of these functions fills the keyboard buffer with several integers, which indicate which key was pressed. The length of the stream is not constant.

Since I use a console mode program as a frontend for a large database, I had to find a quick way of interpreting what those functions returned, and returning what they would have returned in eu2.5

First the defines

global constant EU_VERSION = 3,	--change this as reuired
                PLAT = platform()        
        
 
constant COLORS = 1,  FGND = 1, BKGND = 2,   -- box structure
         COORDS = 2,  ROW = 1, COL = 2,
         SIZE   = 3,  HEIGHT = 1, WIDTH = 2, MINH = 4, MINW = 8,    
         STYLE  = 4,      
         SHADOW = 5,
         HINT   = 6,
         HINTCOLORS = 7,
         BUFFER = 8
 
global integer  SGL, DBL, DHL, DVL, NONE,
                up, dn, left, right, ENTER, ESC, SP,
                pgup, pgdn, home, endd, insert, bksp, del, tab,
                F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12        
         
global sequence Lines, Divider, Shadow
global integer TL, HL, TR, VL, BL, BR
global sequence ENV
                ENV = "Windows"
 
ESC = 27
global constant KEY_UP = {ESC, 91, 65},
                KEY_DOWN = {ESC, 91, 66} 
 
 
tab = '\t'
TL = 1  HL = 2  TR = 3  VL = 4  BL = 5  BR = 6
 
if platform() = LINUX then               
        SGL = 1 DBL = 2  DHL = 3  DVL = 4  NONE = 5  -- border styles
        --key defines
        up = 259  dn = 258  left = 260  right = 261  ENTER = 10  ESC = 27  SP = 32  
        pgup = 339  pgdn = 338  home = 262  endd = 360  insert = 331  bksp = 263 del = 330
        F1 = 265 F2 = 266 F3 = 267 F4 = 268 F5 = 269 F6 = 270 F7 = 271 F8 = 272 F9 = 273 F10 = 274 F11 = 275 F12 = 276
        
        
        --these have been changed from the 'graphic' character set
        Lines = {{'+','-','+','|','+','+'}, -- single line borders
                        {'+','-','+','|','+','+'}, -- double line borders
                        {'+','-','+','|','+','+'}, -- double horizontal
                        {'+','-','+','|','+','+'}, -- double vertical
                        {' ',' ',' ',' ',' ',' '} } -- none
                        
        Divider = {{'+','-','+'}, -- single style divider line
                        {'+','-','+'},
                        {'+','-','+'}, -- double horizontal
                        {'+','-','+'},
                        {' ',' ',' '}}
        
        Shadow = {' ',' ',' '}  -- 3 different shadow backgrounds
        
        ENV = getenv("TERM")
        if match(upper(ENV), "XTERM") = -10 then --set to -10 to ignore it for now
                --xterms seem to work differently - try Windows set
                Lines = {{218,196,191,179,192,217}, -- single line borders
                                {201,205,187,186,200,188}, -- double line borders
                                {213,205,184,179,212,190}, -- double horizontal
                                {214,196,183,186,211,189}, -- double vertical
                                {' ',' ',' ',' ',' ',' '}} -- none
                                
                Divider = {{195,196,180}, -- single style divider line
                                {204,205,185},
                                {198,205,181}, -- double horizontal
                                {199,196,182},
                                {' ',' ',' '}}
                
                Shadow = {176,177,178}  -- 3 different shadow backgrounds
        end if
                        
        
else
        SGL = 1 DBL = 2  DHL = 3  DVL = 4  NONE = 5  -- border styles
        --key defines wim32 / dos
        up = 328  dn = 336  left = 331  right = 333  ENTER = 13  ESC = 27  SP = 32 
        pgup = 329  pgdn = 337  home = 327  endd = 335  insert = 338  bksp = 8 del = 339
        F1 = 315 F12 = 316 F3 = 317 F4 = 318 F5 = 319 F6 = 320 F7 = 321 F8 = 322 F9 = 323 F10 = 324 F11 = 325 F12 = 326
 
        --have to work out codes for lines      
--    Lines = {{'?,'?,'¿','³','?,'?}, -- single line borders
--                {'?,'?,'»','º','?,'¼'}, -- double line borders
--                {'?,'?,'¸','³','?,'¾'}, -- double horizontal
--                {'?,'?,'·','º','?,'½'}, -- double vertical
--                {' ',' ',' ',' ',' ',' '}} -- none
--                
--    Divider = {{'?,'?,'´'}, -- single style divider line
--                  {'?,'?,'¹'},
--                  {'?,'?,'µ'}, -- double horizontal
--                  {'?,'?,'¶'},
--                  {' ',' ',' '}}
--
--    Shadow = {'°','±','²'}  -- 3 different shadow backgrounds
    Lines = {{218,196,191,179,192,217}, -- single line borders
                  {201,205,187,186,200,188}, -- double line borders
                  {213,205,184,179,212,190}, -- double horizontal
                  {214,196,183,186,211,189}, -- double vertical
                  {' ',' ',' ',' ',' ',' '}} -- none
                  
    Divider = {{195,196,180}, -- single style divider line
                    {204,205,185},
                    {198,205,181}, -- double horizontal
                    {199,196,182},
                    {' ',' ',' '}}
 
    Shadow = {176,177,178}  -- 3 different shadow backgrounds
 
        
end if

This was adapted fron D. Cuny's / Irv Mullins et al text mode dialogs.

Note this works equally well on a windows console (in fact looks a little nicer, as the lines come out as lines, and not ascii characters)

Next, the translators

---------------------------------------------------------------------------------------------------------------------
global function resolve_queue(sequence kq)
---------------------------------------------------------------------------------------------------------------------
 
for i = 1 to length(kq) do
        if kq[1] =  ESC then
                if kq[2] = -1 then
                        return ESC
                elsif kq[2] = 79 then
                        if kq[3] = 0 then return home
                        elsif kq[3] = 101 then return endd
                        elsif kq[3] = 80 then return F1
                        elsif kq[3] = 81 then return F1 + 1
                        elsif kq[3] = 82 then return F1 + 2
                        elsif kq[3] = 83 then return F1 + 3
                        end if
                elsif kq[2] = 91 then
                        if kq[3] >= 65 and kq[3] <= 68 then
                                if kq[3] = 65 then return up
                                elsif kq[3] = 66 then return dn
                                elsif kq[3] = 67 then return right
                                else return left
                                end if
                        elsif kq[3] = 49 then
                                if kq[4] = 126 then return home end if
                        elsif kq[3] = 50 then
                                if kq[4] = 126 then return insert end if
                        elsif kq[3] = 51 then return del
                        elsif kq[3] = 52 then return endd
                        elsif kq[3] = 53 then return pgup
                        elsif kq[3] = 54 then return pgdn
                        else 
                                return F1 + kq[3] - 49
                        end if
                end if
        end if
end for
 
 
return -1
end function
 
---------------------------------------------------------------------------------------------------------------------
global function wait_key_nn()
--new non ncurses wait_key replacement for eu 3
--returns a single character, like versions previous to eu25t3
--will also return a single character with versions prior to eu25t3
--note lot of scrounging from ed.ex, RDS
 
---------------------------------------------------------------------------------------------------------------------
atom key
sequence kq
object characters
 
kq = {} 
 
--wait for the first key - less computing time!
key = wait_key()
 
--pre eu 3.0 compatability
if EU_VERSION < 3 or PLAT = WIN32 then return key end if
 
kq = {key}
 
--now get the rest of the keys
while 1 do
        key = get_key()
        if key = -1 then
                exit
        end if
        kq &= key
end while
 
--thats filled the sequence, now process it
 
if length(kq) = 1 then
        if kq[1] =  127 then kq[1] = bksp end if 
        return kq[1]
end if 
 
--puts(1, "Key pressed")
--for i = 1 to length(kq) do
--        printf(1, "%d,", {kq[i]})
--end for
 
key = resolve_queue(kq)
 
return key
end function
---------------------------------------------------------------------------------------------------------------------
global function get_key_nn(object c)
--replaces original get_key function for n0 ncurses eu version
--this won't work if there are too many key presses too quickly, better to use a match
---------------------------------------------------------------------------------------------------------------------
atom key
sequence kq
 
if EU_VERSION < 3 or PLAT = WIN32 then return c end if
 
kq = {c}        --the first element
 
--now get the rest of the keys
while 1 do
        key = get_key()
        if key = -1 then
                exit
        end if
        kq &= key
end while
 
--thats filled the sequence, now process it
 
if length(kq) = 1 then
        if kq[1] =  127 then kq[1] = bksp end if 
        return kq[1]
end if 
 
--puts(1, "Key pressed")
--for i = 1 to length(kq) do
--        printf(1, "%d,", {kq[i]})
--end for
 
key = resolve_queue(kq)
 
return key
end function
 
---------------------------------------------------------------------------------------------------------------------
global function get_key_w(object c)
--uses match, to check for up and downs only, from waiting room
---------------------------------------------------------------------------------------------------------------------
atom key
sequence kq
 
if EU_VERSION < 3 or PLAT = WIN32 then return c end if
 
kq = {c}        --the first element
 
--now get the rest of the keys
--this will get multiple presses, and promptly ignore them in the compare
while 1 do
        key = get_key()
        if key = -1 then
                exit
        end if
        kq &= key
end while
 
--thats filled the sequence, now process it
 
if length(kq) = 1 then
        if kq[1] =  127 then kq[1] = bksp end if 
        return kq[1]
end if 
 
if match(KEY_UP, kq) > 0 then           --KEY_UP sequence
        return up
end if
if match(KEY_DOWN, kq) > 0 then         --KEY_DOWN sequence
        return dn
end if
 
return key
end function

And then replace all instances of wait_key in your program, with wait_key_nn, and get_key with either get_key_nn, or get_key_w (the latter was a special case I needed for a dynamic list for speed, but is included here for completeness.

Thet get_key_nn and get_key_w reuire a parameter - this is the first paramet of get_key - ie a normal get_key is used to get the first character, and this is fed to the new functions. In real use

integer c
 
c = get_key()
if c != -1 then
     c = get_key_nn(c)
end if


These form part of the Fdialogs library, an extended version of the Dialogs library for text mode interface provided by Irv Mullins, D. Cuny etc.

Most of the codes and code from resolve_strings() was pulled from ed, supplied with eu3.0, modified to read from a sequence, rather than the key buffer.

Chris Burch

Personal tools