home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hall of Fame
/
HallofFameCDROM.cdr
/
prpascal
/
colors.lzh
/
COLORS.PAS
Wrap
Pascal/Delphi Source File
|
1987-01-04
|
18KB
|
610 lines
(*
*******************************************************************************
TURBO PASCAL by Mike Robison
OKC
SECTION 1 - Screen Text and Color Manipulation
(actual progam with functions)
SECTION 2 - Use of constants to write inline statements
*******************************************************************************
*************************
** SECTION 1 **
*******************************************************************************
Screen Text and Color Manipulation
This program displays a menu of forground and background colors that you can
select to see what text would look like. There are many good screen functions
and procedures used (including direct to screen writing, and flicker free
control for IBM PC color monitors).
The program automatically finds out what type of system is being used and
adjusts to the system -
Flickers? Screen Buffer
IBM JR No $b800
IBM PC Color Yes $b800
IBM PC Mono No $b000
*)
(*{$R+,U+}*)
type
screenptrtype= ^screentype;
screentype=array[0..2047] of integer; {4k = 4096 / 2 = 0..2047}
boxtype=array[0..5] of byte;
registertype = record
ax,bx,cx,dx,bp,si,di,ds,es,flags:integer;
end;
str15 = string[15];
const
linebox:boxtype=(201,205,187,186,200,188);
colornames:array[0..15] of string[8] =
(' BlacK ',' BluE ',' GreeN ',' CyaN ',
' ReD ','MagentA ',' BrowN ',' LGray ',
' GraY ',' LBlue ',' LGreen ',' LCyan ',
' LRed ','LMagenta',' YelloW ',' WhitE ');
frontpos = 286;
backpos = 304;
columns = 120;
endcol = 119;
var
boxwith:boxtype;
register : registertype;
display,screen,page1,page2:screenptrtype;
showstart,showstop:integer;
oktoshow,junior,delay : boolean;
monitor:char;
showlen:integer;
revinputattr,inputattr,limitattr,redonwhite,blueonwhite:integer;
fillercolor,fillerascii:integer;
oldcolors,lastcolors:integer;
inlinelen,inlineattr:integer;
destseg,sourceseg,sourceofs,destofs:integer;
editentry : string[20];
{FUNCTIONS}
procedure colorit(newcolors:integer);forward;
{ Flicker control - waits for retrace signal}
procedure displaywait;
begin
if delay then
begin
while port[$3DA] and 8=8 do begin end;
while port[$3DA] and 8=0 do begin end;
end;
end;
{ Flicker control - keeps track of scratch pad video buffer use "}
procedure startandstop(start,stop:integer);
begin
if delay then
begin
if start<showstart then if start>=0 then showstart:=start else showstart:=0;
if stop>showstop then if stop<=1999 then showstop:=stop else showstop:=1999;
end;
end;
{ Changes the hi bytes(ie attribute) of an array of integers }
procedure reversescreen(var target; len,attribute:integer);
begin
if len<=0 then exit;
destseg:=seg(target);
destofs:=ofs(target)+1;
inlinelen:=len;
inlineattr:=attribute;
inline(
$8E/$06/destseg/
$8B/$1E/destofs/
$A1/inlineattr/
$8B/$0E/inlinelen/
$26/$88/$27/
$43/$43/
$E2/$F9);
end;
{ Converts a character string into integers (attribute + char)}
procedure showstr(var source,target; len,attribute:integer);
begin
if len<=0 then exit;
sourceseg:=seg(source);
sourceofs:=ofs(source);
destseg:=seg(target);
destofs:=ofs(target);
inlinelen:=len;
inlineattr:=attribute;
inline(
$1e/
$8b/$36/sourceofs/
$8b/$3e/destofs/
$8b/$16/inlineattr/
$8b/$0e/inlinelen/
$a1/sourceseg/$8e/$c0/
$a1/destseg/$8e/$d8/
$89/$d0/ {mov}
$26/$02/$04/ {es: add}
$89/$05/ {mov}
$46/$47/$47/ {inc si}
$e2/$f4/ {loop}
$1f);
end;
{Flicker control - Waits for retrace and copies integers}
procedure screenwrite(var source,dest; wc:integer); {wc = count of integers}
begin
if (not delay) or (wc<=0) then exit;
sourceseg:=seg(source);sourceofs:=ofs(source);
destseg:=seg(dest);destofs:=ofs(dest);
inlinelen:=wc;
inline(
$1E/ {push ds}
$8B/$0E/inlinelen/
$8E/$06/destseg/
$8B/$36/sourceofs/
$8B/$3E/destofs/
$8E/$1E/sourceseg/
$FC/ {cld}
$BA/$DA/$03/ {in al,3da}
$EC/$24/$08/ {and al,8}
$75/$FB/ {jnz}
$BA/$DA/$03/ {in al,3da}
$EC/$24/$08/ {in al,3da}
$74/$FB/ {and al}
$F3/$A5/ {rep movsw}
$1F); {pop ds}
end;
{Sets colors(most are for color monitors), determines if flicker control used}
procedure setcolor;
var
stdfront:integer;
start,total,count2,count3:integer;
boxback,boxborder,boxtext:integer;
begin
boxback:=$0700; boxborder:=$0400; boxtext:=$0100;
limitattr:=$0400;
stdfront:=$0f00;
inputattr:=stdfront;
revinputattr:=(inputattr shl 4)and $7fff;
blueonwhite:=boxtext + boxback shl 4;
redonwhite:=limitattr + boxback shl 4;
fillercolor:=blueonwhite;
fillerascii:=fillercolor+197;
if monitor in ['M','B'] then textmode(bw80) else textmode(c80);
delay := not((monitor='M') or junior);
if delay then { determines how much can be written in retrace }
begin
fillchar(screen^,4000,0); total:=0;start:=1;
for count3:=1 to 5 do
begin
count2:=60; displaywait;
while (port[$3DA]and 8=8) and (count2<=2000) do
begin
count2:=count2+10;
screenwrite(screen^[start],display^[start],count2);
end;
total:=total+count2-10;
end;
showlen:=total div 5;
if showlen<75 then showlen:=75 else if showlen>2000 then showlen:=2000;
fillchar(display^,4000,$ff);
end;
end;
{Determines video buffers}
procedure setup;
var displaystart,count:integer;
begin
delay:=false; showlen:=75;showstart:=1999;showstop:=0;
{JUNIOR?}
with register do
begin intr($11,register);junior:=(ax and 256>1);end;
{MONITOR}
with register do
begin
ax:=$0f00;intr($10,register); ax:=ax and $ff;monitor:='B';
case ax of
1,3,8..15: monitor:='C';
7 : monitor:='M';
end;
end;
{SETUP SCREEN POINTERS}
if monitor='M' then displaystart:=$b000 else displaystart:=$b800;
screen:=ptr(displaystart,0000);
if monitor='M' then begin new(page1); display:=screen;end
else
begin
page1:=ptr(displaystart,4000);
if junior then display:=screen else new(display);
end;
setcolor;
end;
{Flicker control - Transfers video scratch pad to screen on video retraces}
procedure showscreen;
label EXITLOCATION;
var stop,start,count,linelen,transferlen:integer;
begin
if (not delay) or (not oktoshow) then exit;
if showstart=1999 then showstart:=0; if showstop=0 then showstop:=1999;
count:=showstart;
repeat
display^[showstop+1]:=0;
while display^[count]=$ffff do count:=count+1; start:=count;
if start=showstop then goto EXITLOCATION;
display^[showstop+1]:=$ffff;
while display^[count]<>$ffff do count:=count+1; stop:=count-1;
linelen:=stop-start+1;
while linelen>0 do
begin
transferlen:=linelen;if transferlen>showlen then transferlen:=showlen;
screenwrite(display^[start],screen^[start],transferlen);
fillchar(display^[start],transferlen shl 1,255);
start:=start+transferlen;linelen:=linelen-transferlen;
end;
until count>=showstop;
EXITLOCATION:
display^[showstop+1] := $ffff;
showstart:=1999;showstop:=0;
end;
{Fills area of screen with char (lo(color)) and attribute (hi(color))}
procedure fillarea(x,y,x1,y1,color:integer);
var count:integer; pattern:array[0..79] of integer;
begin
x:=x-1; y:=y-1; x1:=x1-1; y1:=y1-1;
if lo(color)=0 then color:=color+32;
for count:=x to x1 do pattern[count]:=color;
startandstop(y*80,y1*80+x1);
for count:=y to y1 do
move(pattern[x],display^[count*80+x],(x1-x+1)shl 1);
showscreen;
colorit(color and $ff00);
end;
{Reverses last colors used}
function revcolors:integer;
begin revcolors:=(lastcolors and $f000)shr 4 + (lastcolors and $0700)shl 4;end;
{Changes attribute only (on screen)}
procedure attributesb(x,y:integer; norm:boolean);
var start,sbattribute:integer;
begin
start:=(y-1)*80+x;
if norm then sbattribute:=lastcolors else sbattribute:=revcolors;
displaywait;reversescreen(screen^[start],17,sbattribute);
end;
{Figure out array position of cursor}
function getscrpos(col,row:integer):integer;
begin getscrpos:=(row-1)*80+col-1; end;
{Makes any size of a box with a heading (optional), box is filled in}
procedure makebox(lx,ly,rx,ry,boxnum:integer;description:str15);
var
tmpattr,middle,linelen,top,bottom,loffset,roffset,count,count2,
attribute,len:integer;
begin
linelen:=rx-lx;
top:=(ly-1)*80+lx-1; bottom:=(ry-1)*80+lx-1;
startandstop(top,bottom+linelen+81);
if boxnum<>5 then tmpattr:=blueonwhite else tmpattr:=inputattr;
fillarea(lx+1,ly+1,rx-1,ry-1,tmpattr);
attribute:=redonwhite;
display^[top]:=attribute+linebox[0];
display^[top+linelen]:=attribute+linebox[2];
display^[bottom]:=attribute+linebox[4];
display^[bottom+linelen]:=attribute+linebox[5];
tmpattr:=attribute + linebox[1];
for count:=1 to linelen-1 do
begin display^[top+count]:=tmpattr; display^[bottom+count]:=tmpattr; end;
loffset:=top+80;roffset:=loffset+linelen;
tmpattr:=attribute + linebox[3];
for count:=1 to ry-ly-1 do
begin
display^[loffset]:=tmpattr; display^[roffset]:=tmpattr;
loffset:=loffset+80; roffset:=roffset+80;
end;
len:=ord(description[0]);colorit(blueonwhite);
if len>0 then
begin
middle:=(lx+rx-len+1)div 2;
attribute:=blueonwhite;
showstr(description[1],display^[getscrpos(middle,ly)],len,attribute);
end;
showscreen;
end;
{Changes text colors for write procedures}
procedure colorit;
begin
oldcolors:=lastcolors;
if not (monitor in['B','M']) then
begin
textcolor((newcolors and $0f00) shr 8);
textbackground((newcolors and $7000) shr 12);
end
else if newcolors and $0800>0 then normvideo else lowvideo;
lastcolors:=newcolors;
end;
{Fills entire screen}
procedure fillscreen;
begin fillarea(1,1,80,25,fillerascii); end;
{get front color (i.e. normal video but in color)}
function getfront(color: integer):integer;
begin if color=0 then getfront:= $0f00 else getfront:= color shl 8;end;
{get color in reverse}
function getback(color: integer):integer;
begin if color in [0,8] then getback:= $7000 else getback:=(color and 7)shl 12;end;
{FUNCTION WHICH MAKES AND DISPLAYS COLOR MEMU }
function getnewcolor(currcolor:integer):integer; {color in lo(currcolor) }
var count,front,back,oldfront,oldback,origcolor:integer;
showsample,done,doingfront:boolean;
achar : char;
begin
origcolor:=currcolor;
oktoshow := false;
makebox(41,1,80,25,4,' COLOR HELP ');
makebox(46,3,59,20,5,' FRONT COLOR');
makebox(64,3,77,12,5,' BACK COLOR ');
fillarea(42,21,79,24,currcolor shl 8);
for count:=0 to 15 do
begin
editentry:=' '+colornames[count]+' ';
showstr(editentry[1],display^[frontpos+count*80],12,getfront(count));
if count<=7 then
showstr(editentry[1],display^[backpos+count*80],12,getfront(count));
end;
oktoshow := true;
showscreen;
colorit(currcolor shl 8);
gotoxy(44,21);write(#24' '#25' = change color');
gotoxy(44,22);write(#27' '#26' = change to editing front/back');
gotoxy(44,23);write(' '#17#217' = make selection & return');
gotoxy(44,24);write(' ESC = escape with orig colors');
gotoxy(1,25);
front := currcolor and $f; back := (currcolor and $f0) shr 4;
oldfront:=(front+1) and $f; oldback:=(back+1) and 7;
doingfront:=true; done:=false;
repeat
showsample:=false;
if oldback<>back then
begin
showsample:=true;
displaywait;
reversescreen(screen^[backpos+oldback*80],12,getfront(oldback));
reversescreen(screen^[backpos+back*80],12,getback(back));
oldback:=back;
end;
if oldfront<>front then
begin
showsample:=true;
displaywait;
reversescreen(screen^[frontpos+oldfront*80],12,getfront(oldfront));
reversescreen(screen^[frontpos+front*80],12,getback(front));
oldfront:=front;
end;
currcolor := front shl 8 + back shl 12;
if showsample then
begin
displaywait;
reversescreen(screen^[1641],38,currcolor);
reversescreen(screen^[1721],38,currcolor);
displaywait;
reversescreen(screen^[1801],38,currcolor);
reversescreen(screen^[1881],38,currcolor);
end;
read(kbd,achar);
if (achar=#27)and(keypressed) then
begin
read(kbd,achar);
case achar of
#72 : if doingfront then {UP}
if front=0 then front := 15 else front:=front-1
else if back=0 then back := 7 else back:=back-1;
#75 : doingfront:=true; {LEFT}
#77 : doingfront:=false; {RIGHT}
end;
end
else
begin
done:= (achar = #13) or (achar = #27);
if achar=#27 then currcolor:=origcolor shl 8;
achar:=#80;
end;
if (not done) and (achar=#80) then {DOWN}
if doingfront then front:=(front+1) and $0f else back:=(back+1) and $07;
until done;
getnewcolor := currcolor shr 8;
end;
var newcolor : integer;
begin
setup;
oldcolors := inputattr; lastcolors:= oldcolors;
oktoshow := true;
fillscreen;
newcolor := getnewcolor(blueonwhite shr 8);
end.
(* ********************
*** SECTION 2 ***
*******************************************************************************
USE OF CONSTANTS TO MIMIC ASSEMBLY LANGUAGE
Below are some of the one byte assembly language instructions which can be
used to write inline statements. See examples below.
*******************************************************************************
*)
const
push_es = $06; pop_es = $07;
or_al_i = $0c; or_ax_i = $0d; push_cs = $0e;
push_ss = $16; pop_ss = $17;
push_ds = $1e; pop_ds = $1f;
and_al_i = $24; and_ax_i = $25;
es_ = $26;
sub_al_i = $2c; sub_ax_i = $2d;
xor_al_i = $34; xor_ax_i = $35;
cmp_al_i = $3c; cmp_ax_i = $3d;
inc_ax =$40 ; dec_ax = $48; push_ax = $50; pop_ax = $58;
inc_cx =$41 ; dec_cx = $49; push_cx = $51; pop_cx = $59;
inc_dx =$42 ; dec_dx = $4a; push_dx = $52; pop_dx = $5a;
inc_bx =$43 ; dec_bx = $4b; push_bx = $53; pop_bx = $5b;
inc_sp =$44 ; dec_sp = $4c; push_sp = $54; pop_sp = $5c;
inc_bp =$45 ; dec_bp = $4d; push_bp = $55; pop_bp = $5d;
inc_si =$46 ; dec_si = $4e; push_si = $56; pop_si = $5e;
inc_di =$47 ; dec_di = $4f; push_di = $57; pop_di = $5f;
jo = $70; jno = $71; jb = $72; jnb = $73; je = $74; jne = $75;
jbe = $76; jnbe = $77; js = $78; jns = $79; jp = $7a; jnp = $7b;
jl = $7c; jnl = $7d; jle = $7e; jnle = $7f;
nop = $90;
xchg_ax_cx = $91; xchg_ax_dx = $92; xchg_ax_bx = $93; xchg_ax_sp = $94;
xchg_ax_bp = $95; xchg_ax_si = $96; xchg_ax_di = $97;
call_long = $9a;
mov_al_m = $a0; mov_ax_m = $a1; mov_m_al = $a2; mov_m_ax = $a3;
movsb = $a4; movsw = $a5;
cmpsb = $a6; cmpsw = $a7;
testb = $a8; testw = $a9;
stosb = $aa; stosw = $ab;
lodsb = $ac; lodsw = $ad;
scasb = $ae; scasw = $af;
mov_al_i = $b0; mov_cl_i = $b1; mov_dl_i = $b2; mov_bl_i = $b3;
mov_ah_i = $b4; mov_ch_i = $b5; mov_dh_i = $b6; mov_bh_i = $b7;
mov_ax_i = $b8; mov_cx_i = $b9; mov_dx_i = $ba; mov_bx_i = $bb;
mov_sp_i = $bc; mov_bp_i = $bd; mov_si_i = $be; mov_di_i = $bf;
ret_near = $c3;
ret_far = $cb;
loopnz = $e0; loopz = $e1; loop = $e2; jcxz = $e3;
inb = $e4; inw = $e5; outb = $e6; outw = $e7;
call_near = $e8; jmp_near = $e9;
jmp_short = $eb;
rep = $f2; repz = $f3;
cld = $fc; std = $fd;
*******************************************************************************
EXAMPLE 1 - Copy blocks of data (i.e. integers, records, etc. in an array)
Note: this is a procedure
*******************************************************************************
var move_size,dest_seg, dest_ofs, {must be in data segment, ie global}
source_seg, source_ofs : integer;
procedure repeatblock(var source_loc; size,copies:integer);
begin
dest_seg := seg(source_loc);
source_ofs := ofs(source_loc);
dest_ofs := source_ofs + size;
move_size := size * copies;
inline(
push_ds/
mov_ax_m/move_size/
xchg_ax_cx/
mov_ax_m/source_ofs/
xchg_ax_si/
mov_ax_m/dest_ofs/
xchg_ax_di/
mov_ax_m/dest_seg/
push_ax/
push_ax/
pop_ds/
pop_es/
cld/
rep/movsb/
pop_ds
);
end;
*******************************************************************************
EXAMPLE 2 - Nested loops
*******************************************************************************
var anumber : integer;
begin
anumber := 0;
inline
(
mov_ax_m/>anumber/
mov_cx_i/>$0003/ { for count := 1 to 3 do }
push_cx/
mov_cx_i/>$0004/ { for count2 := 1 to 4 do }
inc_ax/ { anumber := anumber + 1;}
loop/256-3/
pop_cx/
loop/256-10/
mov_m_ax/anumber
);
write(' anumber = ',anumber);
end.