home *** CD-ROM | disk | FTP | other *** search
- // ANSICLIP.PRG Copyright 1992 Robert Greenlee Released for unlimited use.
- //
- // SHOWANSI()
- // This function will display an ANSI encoded picture file. ANSI.SYS
- // does not need to be loaded as the display is handled using Clipper
- // screen functions only.
- //
- // This is a rewrite of the SHOWANSI() function which was released into
- // the public domain by Ken LaCapria on 11/10/91 in the file SHOWANSI.PRG.
- // Ken's 11/10/91 version didn't work well enough to display any of the ANSI
- // pictures I wanted to look at so I continued its development until I
- // came up with this version which properly displays most of the ANSI pictures
- // I've found on BBS's. I am using Clipper 5.01. Note that I've commented
- // out a line below which uses the posalpha() function in the Nantucket
- // Tools Library and put a FOR/NEXT loop in its place. If you have
- // the Nantucket Tools Library or a posalpha() equivalent you might want
- // to drop the FOR/NEXT. Also the ANSI SetMode functions can be enabled
- // by uncommenting the line with the FT_SETMODE() function on it but you'll
- // need the Nanforum ToolKit NANFOR.LIB when you link (or you could use
- // SCRSETMODE() in Nantucket Tools). This entire function could stand
- // alot more work but I'm tired of working on it for now.
- // Hopefully someone else will get interested. Currently if it detects any
- // unsupported ANSI sequences such as keyboard or music commands it will
- // display them on the screen along with an "Unsupported ANSI sequence" message.
- // I tried DO CASEing everything and taking out the LOOP's but it became slower.
- // I've added a timeron equate that can be set .t. to display how long it takes
- // to display each picture so you can see how your changes effect display speed.
- // I'm leaving my debug code in so that anyone interested can continue
- // development and I'm including a demo, ansidemo.prg, which uses this function
- // to display .ANS files in the current directory. I can be reached on the
- // Sabaline (619-692-1961) and Mushin (619-222-3097) BBS's in San Diego. I
- // don't know where Ken LaCapria can be reached, apparently he didn't leave
- // any info on that in SHOWANSI.PRG/.ZIP.
- //
- // HISTORY:
- // 1/28/92 - ANSICLIP.ZIP - First Release of SHOWANSI.PRG rewrite.
- // 1/29/92 - ANSICL52.ZIP - Second Release. Recoded Change-Color handler
- // to substantially increase display speed.
- //
- #include "inkey.ch"
- //
- // SHOWANSI returns a null string
- // Syntax: SHOWANSI(memvar)
- //
- FUNCTION showansi (ansitext)
- local textlen,onechar,charpos,tempstrng,sf,sb,ef,eb,uf,ub,temprow
- local tempcol,colnpos,tempchar,tempsubstr,X,savrow,savcol,oldcolor
- local valtempstr,nextcharpos,oldsf,mposalpha,showesc,debugansi,x1
- local mrow,mcol,gtimeons,gdateon,valtemp,timeron,templen
- local secson,minuteson,dayson,hourson,secsleft,arcolors
-
- timeron = .f. // If this is .t. then the time it takes to display the
- // picture will be displayed in the lower left corner.
- IF timeron
- gtimeons = SECONDS()
- gdateon = DATE()
- ENDI
- oldcolor = setcolor()
- showesc = .t. // Display an Escape code not part of ANSI as a left arrow
- debugansi = .f. // Crude debug mode that stops at every Escape sequence and
- // displays various info. You hold the Enter key down
- // until you get to the spot that's screwing up and then
- // you try to see which Escape sequence is causing the problem
- // and what's happening that's wrong and then you fix it.
- IF debugansi
- SET CURSOR ON // let's see where cursor is after each Escape sequence
- ENDI
-
- STOR 'W' TO sf,ef,uf
- STOR 'N' TO sb,eb,ub
- arcolors = {'N','R','G','GR','B','RB','BG','W'}
- STOR 0 TO temprow,tempcol,colnpos,savrow,savcol,charpos
- // Trim off any EOF markers like zeroes & Control-Z's
- DO WHIL SUBS(ansitext,LEN(ansitext),1) $ CHR(0)+CHR(26)
- ansitext = SUBS(ansitext,1,LEN(ansitext)-1)
- ENDD
- textlen=LEN(ansitext)
- DO WHIL charpos+1<=textlen
- IF debugansi
- MROW = ROW()
- MCOL = COL()
- @ maxrow(),60 SAY 'savrow='+LTRIM(STR(savrow,3))+' savcol='+LTRIM(STR(savcol,3))
- @ MROW,MCOL SAY ''
- ENDI
- charpos++
- STOR '' TO tempstrng,tempsubstr
-
- nextcharpos = charpos+AT(CHR(K_ESC),SUBS(ansitext,charpos))-1
- // If no more Esc's send rest of string and exit
- IF nextcharpos < charpos
- ?? SUBS(ansitext,charpos)
- EXIT
- ENDI
- // If not an Esc send out up to next Esc
- IF nextcharpos > charpos
- ?? SUBS(ansitext,charpos,nextcharpos-charpos) // send to next ESC
- ENDI
- charpos = nextcharpos + 1
- // Process Esc command. If valid next char is [
- onechar=SUBS(ansitext,charpos,1) // probably pointing to [
- IF onechar<>'['
- IF onechar = CHR(K_ESC) .AND. showesc
- ?? CHR(K_ESC)
- ENDI
- charpos-- // point back to Escape, charpos gets bumped above
- LOOP
- ENDIF
- charpos++ // skip past [
- // mposalpha = posalpha(ansitext,.F.,charpos-1) + charpos-1
- mposalpha = 0
- FOR x = charpos TO textlen
- x1 = SUBS(ansitext,x,1)
- IF !(x1==LOWER(x1) .AND. x1==UPPER(x1))
- mposalpha = x
- EXIT
- ENDI
- NEXT
- IF mposalpha = 0
- EXIT // Picture ends with incomplete Esc sequence - stop now
- ENDI
- tempstrng = SUBS(ansitext,charpos,mposalpha-charpos)
- charpos = mposalpha
- onechar=SUBS(ansitext,charpos,1)
-
- IF debugansi
- // here we display the ANSI command about to be processed and the
- // row & col before, the command parameters (tempstrng), and a 40
- // character chunk of the code string with the current command
- // in the middle of it (Escape codes are changed to ! and carriage
- // returns and line feeds are changed to ^.)
- MROW = ROW()
- MCOL = COL()
- @ maxrow()-5,10 SAY ''
- ?? 'row='+LTRIM(STR(MROW,3))+', '
- ?? 'col='+LTRIM(STR(MCOL,3))+', '
- ?? 'command='+onechar+' '
- @ maxrow()-4,10 SAY 'tempstrng= '+tempstrng+' '
- @ maxrow()-3,10 SAY 'ansitext-20= '+ STRTRAN(STRTRAN(STRTRAN(SUBS(ansitext,charpos-20,40),CHR(27),'!'),CHR(13),'^'),CHR(10),'^')
- @ MROW,MCOL SAY ''
- SET CONS OFF
- wait
- SET CONS ON
- ENDI
-
-
- IF ! onechar $ 'ABCDHJKfhlmsu'
- MROW=ROW()
- MCOL=COL()
- @ maxrow(),0 SAY 'Unsupported ANSI sequence '
- ?? STRTRAN(STRTRAN(STRTRAN(SUBS(ansitext,charpos,30),CHR(27),'!'),CHR(13),'^'),CHR(10),'^')
- @ MROW,MCOL SAY ''
- SET CONS OFF
- wait
- SET CONS ON
- LOOP
- ENDI
- IF !onechar == 'm' // This improves display time
- valtemp = VAL(tempstrng)
- IF onechar='K' // Clear to End of Line
- DO CASE
- CASE valtemp=0
- @ ROW(),COL()-1 CLEAR TO ROW(),maxcol()
- CASE valtemp=1
- @ ROW(),0 CLEAR TO ROW(),COL()-1
- CASE valtemp=2
- @ ROW(),0 CLEAR TO ROW(),maxcol()
- ENDC
- LOOP
- ENDIF
- IF onechar $ 'ABCD' // Cursor Up/Down/Right/Left
- DO CASE
- CASE onechar='A'
- temprow=ROW()-MAX(valtemp,1)
- tempcol = COL()
- CASE onechar='B'
- temprow=ROW()+MAX(valtemp,1)
- tempcol = COL()
- CASE onechar='C'
- tempcol=COL()+MAX(valtemp,1)
- temprow = ROW()
- CASE onechar='D'
- tempcol=COL()-MAX(valtemp,1)
- temprow = ROW()
- ENDC
- @ MIN(maxrow(),MAX(0,temprow)),MIN(maxcol(),MAX(0,tempcol)) SAY ''
- LOOP
- ENDIF
-
- IF onechar $ 'Hf' // Absolute Cursor Positioning (Both same)
- colnpos=AT(';',tempstrng)
- IF colnpos > 0
- temprow=VAL(SUBS(tempstrng,1,colnpos-1))-1
- ELSE
- temprow = valtemp-1
- ENDI
- IF colnpos > 0 .AND. LEN(SUBS(tempstrng,colnpos+1)) > 0
- tempcol=VAL(SUBS(tempstrng,colnpos+1))-1
- ELSE
- tempcol = 0
- ENDI
- @ MIN(maxrow(),MAX(0,temprow)),MIN(maxcol(),MAX(0,tempcol)) SAY ''
- LOOP
- ENDIF
-
- IF onechar='s' // Save Current Cursor Location
- savrow=ROW()
- savcol=COL()
- LOOP
- ENDIF
-
- IF onechar='u' // Return to last Saved Cursor Location
- @ savrow,savcol SAY ''
- LOOP
- ENDIF
-
- IF onechar='J' // Clear Screen - Cursor to upper left corner
- DO CASE
- CASE valtemp=0
- @ ROW(),MAX(COL()-1,0) CLEAR TO ROW(),maxcol()
- @ ROW()+1,0 CLEAR
- CASE valtemp=1
- @ ROW(),0 CLEAR
- CASE valtemp=2
- @ 0,0 CLEAR TO maxrow(),maxcol()
- ENDC
- LOOP
- ENDIF
- IF onechar$'lh' // Set screen width/height commands.
- // Esc[=#h sets screen mode
- // Esc[=#l resets screen mode
- // 0 = 40x25 black & white
- // 1 = 40x25 color
- // 2 = 80x25 black & white
- // 3 = 80x25 color
- // 4 = 320x200 color graphics
- // 5 = 320x200 black & white graphics
- // 6 = 640x200 black & white graphics
- // 7 = line-wrap on/off (Esc[=7h/Esc[=7l)
- // 84 = 132x43 Paradise VGA
- // 85 = 132x25 Paradise VGA
- //
- IF SUBS(tempstrng,1,1) == '=' // You need NanForum TookKit's
- IF SUBS(tempstrng,2,1) $ '012345689' // NANFOR.LIB for FT_SETMODE()
- // FT_SETMODE(VAL(SUBS(tempstrng,2))) // or you could use SETSCRMODE()
- ENDI // in Nantucket Tools.
- ENDI
- // Esc[?7l or Esc[=7l turns line-wrap off Not Supported yet
- // Esc[?7h or Esc[=7h turns line-wrap on Not Supported yet
- LOOP
- ENDIF
- ENDIF // .NOT. onechar == 'm'
- // at this point onechar is ASSUMED to be 'm' since all the IF's above LOOP
- X=0
- templen = LEN(tempstrng)
- DO WHILE .t. // EXITS at bottom of DO/WHIL when !(x <= templen)
- tempsubstr=''
- x++
- tempsubstr = SUBS(tempstrng,x,AT(';',SUBS(tempstrng,x)+';')-1)
- x=x+LEN(tempsubstr)
-
- IF debugansi
- // here we display each part of the screen color sequence before
- // it is processed.
- MROW = ROW()
- MCOL = COL()
- @ maxrow()-1,10 SAY 'tempsubstr= '+tempsubstr+' '
- @ MROW,MCOL SAY ''
- SET CONS OFF
- wait
- SET CONS ON
- ENDI
-
- oldsf = sf
- valtempstr = VAL(tempsubstr)
- DO CASE
- CASE valtempstr=0
- STOR 'W' TO sf,ef,uf
- STOR 'N' TO sb,eb,ub
- CASE valtempstr=1
- sf=STRTRAN(sf+'+','++','+')
- CASE valtempstr=2
- sf=STRTRAN(sf,'+')
- CASE valtempstr=4
- sf='U'
- CASE valtempstr=5 .AND. .NOT. '*' $ sf
- sf=sf+'*'
- CASE valtempstr=7
- sf='I'
- CASE valtempstr=8
- sf='X'
- CASE valtempstr > 29 .AND. valtempstr < 38
- sf = arcolors[valtempstr-29]
- IF '+' $ oldsf
- sf = sf+'+'
- ENDI
- IF '*' $ oldsf
- sf = sf+'*'
- ENDI
- CASE valtempstr > 39 .AND. valtempstr < 48
- sb = arcolors[valtempstr-39]
- ENDC
- IF ! x <= templen
- setcolor(sf+'/'+sb+','+ef+'/'+eb+',,,'+uf+'/'+ub)
- EXIT
- ENDI
- ENDD
- ENDD
- setcolor(oldcolor)
- IF timeron
- @ maxrow(),0 SAY 'Time: '
- secson = ((DATE()-gdateon)*86400)+(SECONDS()-gtimeons)
- dayson = INT(secson/86400)
- hourson = INT((secson-(dayson*86400))/3600)
- minuteson = INT((secson-(dayson*86400)-(hourson*3600))/60)
- secsleft = secson - (dayson*86400) - (hourson*3600) - (minuteson*60)
- ?? IIF(dayson>0,LTRIM(STR(dayson))+ ' days, ','')
- ?? IIF(hourson>0,LTRIM(STR(hourson))+ ' hours, ','')
- ?? IIF(minuteson>0,LTRIM(STR(minuteson))+ ' minute'+IIF(minuteson=1,'','s')+', ','')
- ?? LTRIM(STR(secsleft))
- ?? ' second'+IIF(secsleft=1,'','s')+'.'
- ENDI
- RETURN ''
-
-
-
- //: EOF: ANSICLIP.PRG