Terminals are text oriented and introducing pictures or windows isn't attempted by most Linix utilities. Usually it is too much work for little benifit. But, there are a few ways we can cheat. One way is to use the drawing characters to make boxes. Another way to to set the scroll region and split the screen into windows. An example of screen splitting is the splitvt program. The "mc" file manager is well known program that uses draw characters.
The box characters are not normally enabled, and
first we need to turn them on: The following code
accomplishes this:
draw_on:
mov ecx,base_msg
call crt_str
ret
base_msg: db 1bh,')0',0eh,0 ;line draw set
The crt_str function is a library call to send a string to
the display. Any write to the display could be used. (Note:
This write string function can be found in AsmLib)
After the string is output, the following characters are
present:
old char. draw state old char. draw state
------------------------------ ----------------------------
_ Blank o Horiz Line - scan 1
' Diamond p Horiz Line - scan 3
a Checkerboard q Horiz Line - scan 5
b Digraph: HT r Horiz Line - scan 7
c Digraph: FF s Horiz Line - scan 9
d Digraph: CR t Left "T" (|-)
e Digraph: LF u Right "T" (-|)
f Degree Symbol v Bottom "T" (|#_)
g +/- Symbol w Top "T" (T)
h Digraph: NL x Vertical Bar (|)
i Digraph: VT y Less/Equal (<#_)
j Lower-right corner z Grtr/Egual (>#_)
k Upper-right corner { Pi symbol
l Upper-left corner | Not equal (=#/)
m Lower-left corner } UK pound symbol
n Crossing lines (+) ~ Centered dot
We can disable draw characters by sending the following code to
display:
draw_off:
mov ecx,g0_select
call crt_str
ret
g0_select: db 0fh,0
Drawing a box is now easy. We just write to the display
after moving the cursor to the box bounds. There are many ways
to write a box routine, and the following example uses a table
processor. The table process takes commands from a table to move
the cursor and repeat characters. For a single window
the table processor may be over kill, but if several boxes are
wanted or other graphics added, a table becomes very efficient.
extern draw_table
;-----------------------------------------------------
;>1 draw
; draw_box - use line drawing characters to draw a box
; inputs:
; esi = ptr to block of data as follows:
; dd <color>
; db row
; db column
; db vertical size
; db horizontal size
; outputs:
; none
; operation:
; draw_box stores data in control_table to describe
; a box. The control table is then passed to
; draw_table.
;
;<
;-----------------------------------------------------------
global draw_box
draw_box:
lodsd ;get color
mov [color],eax
lodsb ;get row
mov bl,al ;save row
mov [ul_row],al ;top left corner
mov [ur_row],al ;top right corner
mov [rh_rowt],al ;top line
inc al
mov [rv_rowl],al ;left bar, repeat down
mov [rv_rowr],al ;right bar, repeat down
lodsb ;get upper left column
mov bh,al ;save column
mov [ul_col],al ;set upper left column
mov [rv_coll],al ;set repeat down, left edge column
mov [ll_col],al
inc al
mov [rh_colt],al ;set upper bar, starting column
mov [rh_colb],al ;set lower bar, starting column
lodsb ;get vertical size
sub al,2
mov [rv_cntr],al
mov [rv_cntl],al
add bl,al ;compute botton row
inc bl
mov [ll_row],bl ;set lower left row for corner
mov [rh_rowb],bl ;set lower bar row
mov [lr_row],bl ;set lower right row for corner
lodsb ;get horiontal size
sub al,2
mov [rh_cntt],al
mov [rh_cntb],al
add bh,al ;compute right column
inc bh
mov [ur_col],bh ;upper right corner col
mov [lr_col],bh ;lower right corner col
mov [rv_colr],bh ;right edge bar column
mov esi,control_table
call draw_table
ret
;--------------
[section .data]
control_table:
db 5 ;draw on
db 1 ;set color
color dd 0 ;color
db 2 ;upper left corner char
ul_row db 0 ;upper left row
ul_col db 0 ;upper left col
db 'l' ;corner char
db 2 ;upper right corner char
ur_row db 0 ;upper right row
ur_col db 0 ;upper right col
db 'k' ;corner char
db 2 ;lower left corner char
ll_row db 0 ;lower left row
ll_col db 0 ;lower left col
db 'm' ;corner char
db 2 ;lower right corner char
lr_row db 0 ;lower right row
lr_col db 0 ;lower right col
db 'j' ;corner char
db 3 ;repeat horizontal -top line
rh_rowt db 0 ;repeat h row
rh_colt db 0 ;repeat h column
rh_cntt db 0 ;repeat count
db 'q' ;repeat h char
db 3 ;repeat horizontal -bottom line
rh_rowb db 0 ;repeat h row
rh_colb db 0 ;repeat h column
rh_cntb db 0 ;repeat count
db 'q' ;repeat h char
db 4 ;repeat vertical (down) - left edge
rv_rowl db 0 ;repeat row
rv_coll db 0 ;repeat col
rv_cntl db 0 ;repeat count
db 'x' ;repeat char
db 4 ;repeat vertical (down) - right edge
rv_rowr db 0 ;repeat row
rv_colr db 0 ;repeat col
rv_cntr db 0 ;repeat count
db 'x' ;repeat char
db 6 ;draw off
db 0 ;end of table
[section .text]
extern crt_str
extern crt_char_at
extern move_cursor
extern crt_set_color
extern crt_horizontal
extern crt_vertical
extern draw_on
extern draw_off
;-----------------------------------------------------
;>1 draw
; draw_table - draw using table of actions
; Actions are embedded characters with value of 0-6.
; inputs:
; esi = ptr to draw table
; draw table codes db 0 = end of table
; db 1 + dd cccc = color change
; db 2,row,col,char = single char display
; db 3,row,col,rep,char = repeat char. horiz
; db 4,row,col,rep,char = repeat char, down
; db 5 = draw on
; db 6 = draw off
;
; outputs:
; none
; notes:
; all externals are in AsmLIb
;
;<
;-----------------------------------------------------------
global draw_table
draw_table:
xor eax,eax
lodsb ;get next code
or eax,eax
jz dt_exit ;exit if done
dec eax
jz dt_color
dec eax
jz dt_single_char
dec eax
jz dt_repeat_hor
dec eax
jz dt_repeat_down
dec eax
jz draw_enable
dec eax
jz draw_disable
dt_exit:
ret
;---------
dt_color:
lodsd ;get color
mov [active_color],eax ;save color
jmp draw_table
;---------
dt_single_char:
lodsw ;get cursor position
xchg al,ah ;;
mov bx,ax ;move cursor to bl=col bh=row
lodsb ;get char
mov cl,al ;char -> al
mov eax,[active_color]
call crt_char_at
jmp draw_table
;---------
dt_repeat_hor:
lodsw ;get cursor position
xchg al,ah ;;;
call move_cursor
lodsb ;get repeat count
xor ecx,ecx
mov cl,al ;repeat count -> ecx
lodsb ;get char
mov bl,al ;char -> bl
mov eax,[active_color]
call crt_horizontal
jmp draw_table
;---------
dt_repeat_down:
mov eax,[active_color]
call crt_set_color
lodsw ;get cursor position al=col ah=row
xchg al,ah
push eax
lodsb ;get repeat count
mov bh,al ;repeat count -> bh
lodsb
mov bl,al ;character to repeat -> bl
pop eax ;restore cursor position
call crt_vertical
jmp draw_table
;---------
draw_enable:
call draw_on
jmp draw_table
;---------
draw_disable:
call draw_off
jmp draw_table
;---------------
[section .data]
active_color dd 0
[section .text]
This code is taken from the Open Source project AsmIDE.
AsmIDE includes the AsmLib source needed by the draw code.
http://members.save-net.com/jko%40save-net.com/asm/
To compile this example use:
nasm -f elf -g draw.asm
the file type is specified with "-f elf" and the
-g says to include debug information. Next, it is
linked with:
ld draw.o -o draw /usr/lib/asmlib.a
The only requirement to link is the library file
at /usr/lib. The library and a debugger are also
available at:
http://sourceforge.net/projects/asmbug
http://sourceforge.net/projects/asmlib
|