Files
harbour-core/harbour/contrib/hbnf/dispc.c
Viktor Szakats 7df0d4b153 2010-07-14 14:52 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* contrib/hbnf/acctyear.prg
  * contrib/hbnf/byteneg.prg
  * contrib/hbnf/isshare.prg
  * contrib/hbnf/sinkey.prg
  * contrib/hbnf/kspeed.c
  * contrib/hbnf/prtscr.c
  * contrib/hbnf/descendn.c
  * contrib/hbnf/peek.c
  * contrib/hbnf/scancode.prg
  * contrib/hbnf/vidmode.prg
  * contrib/hbnf/nwsem.prg
  * contrib/hbnf/acctadj.prg
  * contrib/hbnf/week.prg
  * contrib/hbnf/vidcur.prg
  * contrib/hbnf/iamidle.c
  * contrib/hbnf/miltime.prg
  * contrib/hbnf/prtesc.prg
  * contrib/hbnf/acctmnth.prg
  * contrib/hbnf/proper.c
  * contrib/hbnf/savearr.prg
  * contrib/hbnf/madd.prg
  * contrib/hbnf/rand1.prg
  * contrib/hbnf/dispmsg.prg
  * contrib/hbnf/fttext.c
  * contrib/hbnf/mouse1.prg
  * contrib/hbnf/settime.prg
  * contrib/hbnf/page.prg
  * contrib/hbnf/restsets.prg
  * contrib/hbnf/byt2bit.prg
  * contrib/hbnf/setkeys.c
  * contrib/hbnf/month.prg
  * contrib/hbnf/byt2hex.prg
  * contrib/hbnf/findith.prg
  * contrib/hbnf/at2.prg
  * contrib/hbnf/acctweek.prg
  * contrib/hbnf/dispc.c
  * contrib/hbnf/gcd.prg
  * contrib/hbnf/pegs.prg
  * contrib/hbnf/min2dhm.prg
  * contrib/hbnf/acctqtr.prg
  * contrib/hbnf/numlock.c
  * contrib/hbnf/dosver.prg
  * contrib/hbnf/nooccur.prg
  * contrib/hbnf/dayofyr.prg
  * contrib/hbnf/metaph.prg
  * contrib/hbnf/ontick.c
  * contrib/hbnf/menu1.prg
  * contrib/hbnf/byteand.prg
  * contrib/hbnf/sqzn.prg
  * contrib/hbnf/bytexor.prg
  * contrib/hbnf/ftidle.c
  * contrib/hbnf/workdays.prg
  * contrib/hbnf/byteor.prg
  * contrib/hbnf/asum.prg
  * contrib/hbnf/shift.c
  * contrib/hbnf/sleep.prg
  * contrib/hbnf/wda.prg
  * contrib/hbnf/woy.prg
  * contrib/hbnf/aavg.prg
  * contrib/hbnf/any2any.prg
  * contrib/hbnf/origin.c
  * contrib/hbnf/mouse.c
  * contrib/hbnf/chdir.c
  * contrib/hbnf/adessort.prg
  * contrib/hbnf/setdate.prg
  * contrib/hbnf/netpv.prg
  * contrib/hbnf/amedian.prg
  * contrib/hbnf/blink.prg
  * contrib/hbnf/stod.c
  * contrib/hbnf/vertmenu.prg
  * contrib/hbnf/linked.prg
  * contrib/hbnf/qtr.prg
  * contrib/hbnf/aredit.prg
  * contrib/hbnf/n2color.c
  * contrib/hbnf/alt.c
  * contrib/hbnf/xbox.prg
  * contrib/hbnf/ftround.prg
  * contrib/hbnf/hex2dec.prg
  * contrib/hbnf/getver.c
  * contrib/hbnf/nwuid.prg
  * contrib/hbnf/dectobin.prg
  * contrib/hbnf/aemaxlen.prg
  * contrib/hbnf/bitset.prg
  * contrib/hbnf/nwlstat.prg
  * contrib/hbnf/invclr.prg
  * contrib/hbnf/ctrl.c
  * contrib/hbnf/popadder.prg
  * contrib/hbnf/lastday.prg
  * contrib/hbnf/tempfile.prg
  * contrib/hbnf/diskfunc.prg
  * contrib/hbnf/scregion.prg
  * contrib/hbnf/d2e.prg
  * contrib/hbnf/mouse2.prg
  * contrib/hbnf/ftisprn.c
  * contrib/hbnf/pickday.prg
  * contrib/hbnf/firstday.prg
  * contrib/hbnf/daytobow.prg
  * contrib/hbnf/anomatch.prg
  * contrib/hbnf/menutonf.prg
  * contrib/hbnf/ftattr.c
  * contrib/hbnf/pvid.prg
  * contrib/hbnf/isbiton.prg
  * contrib/hbnf/color2n.c
  * contrib/hbnf/isbit.prg
  * contrib/hbnf/datecnfg.prg
  * contrib/hbnf/cntryset.prg
  * contrib/hbnf/putkey.c
  * contrib/hbnf/getenvrn.c
  * contrib/hbnf/easter.prg
  * contrib/hbnf/bytenot.prg
  * contrib/hbnf/ntow.prg
  * contrib/hbnf/aeminlen.prg
  * contrib/hbnf/poke.c
  * contrib/hbnf/floptst.prg
  * contrib/hbnf/pchr.prg
  * contrib/hbnf/savesets.prg
  * contrib/hbnf/tbwhile.prg
  * contrib/hbnf/mkdir.c
  * contrib/hbnf/year.prg
  * contrib/hbnf/caplock.c
  * contrib/hbnf/rmdir.c
  * contrib/hbnf/calendar.prg
  * contrib/hbnf/e2d.prg
  * contrib/hbnf/elapsed.prg
  * contrib/hbnf/sysmem.prg
  * contrib/hbnf/bitclr.prg
  * contrib/hbnf/eltime.prg
  * contrib/hbnf/aading.prg
  * contrib/hbnf/dfile.prg
  * contrib/hbnf/elapmil.prg
  * contrib/hbnf/setlastk.c
  * contrib/hbnf/pending.prg
  * contrib/hbnf/clrsel.prg
    - Stripped NFDOC/HBDOC from source code.
2010-07-14 12:57:05 +00:00

774 lines
23 KiB
C

/*
* $Id$
*/
/*
* File......: dispc.c
* Author....: Mike Taylor
* CIS ID....: ?
*
* This is an original work by Mike Taylor and is placed in the
* public domain.
*
* Modification history:
* ---------------------
*
* Rev 1.10 22 Apr 2004 15:32:00 David G. Holm <dholm@jsd-llc.com>
* Corrected all hb_fsSeek calls to use FS_ defines instead of using
* redefined SEEK_ ones that conflict with the C-level SEEK_ defines.
* Rev 1.9 ? ?
* An unknown number of changes were made between Rev 1.8 and Rev 1.10.
*
* Rev 1.8 24 May 2002 19:25:00 David G. Holm <dholm@jsd-llc.com>
* Fixed some problems that caused C++ compiles to fail.
*
* Rev 1.7 29 Mar 2002 17:00:00 Walter Negro <anegro@overnet.com.ar>
* Ported to Harbour
*
* Rev 1.6 01 Jan 1995 03:01:00 TED
* Changed some prototypes to eliminate compiler warnings.
*
* Rev 1.5 14 Feb 1994 16:58:42 GLENN
* Steve Tyrakowski and Kevin Maher modified to be CPMI-compliant.
*
* Rev 1.4 18 Nov 1991 02:20:20 GLENN
* Mike fixed a bug in _ft_dfinit() related to allocating memory. Some
* users had been reporting problems, but everyone who tested this patch
* reported success.
*
* Rev 1.3 17 Aug 1991 15:25:46 GLENN
* Don Caton fixed some spelling errors in the doc
*
* Rev 1.2 15 Aug 1991 23:08:14 GLENN
* Forest Belt proofread/edited/cleaned up doc
*
* Rev 1.1 14 Jun 1991 19:53:42 GLENN
* Minor edit to file header
*
* Rev 1.0 01 Apr 1991 01:02:46 GLENN
* Nanforum Toolkit
*
*
*/
#include "hbapi.h"
#include "hbapifs.h"
#include "hbapigt.h"
#include "inkey.ch"
#define K_STRING 0
#define K_LIST (!K_STRING)
#define CR ((char) 13)
#define LF ((char) 10)
#define FEOF ((char) 26)
#define READONLY 0 /* open file modes */
#define WRITEONLY 1
#define READWRITE 2
#define BUFFERSIZE 4096 /* maximum size of the file buffer */
#define MAXLINE 255 /* default maximum size of a line */
#define TABSET 8
HB_FOFFSET buffoffset; /* offset into buffer of current line */
HB_FOFFSET fsize; /* file size in bytes */
HB_ISIZ bufftop, buffbot; /* first and last character in buffer */
int wintop, winbot; /* first and last character in window */
int winrow, wincol; /* row and column of window highlight */
int sline, eline; /* start and end line of window */
int scol, ecol; /* start and end col of window */
int height, width; /* height and width of window */
HB_FHANDLE infile; /* input file handle */
int maxlin; /* line size */
HB_ISIZ buffsize; /* buffer size */
int hlight; /* highlight attribute */
int norm; /* normal attribute */
HB_ISIZ kcount; /* number of keys in terminate key list*/
int colinc; /* col increment amount */
HB_BOOL bBrowse; /* browse flag */
HB_BOOL bRefresh; /* HB_TRUE means refresh screen */
char kstr[25]; /* terminate key string */
int keylist[24]; /* terminate key list */
int keytype; /* K_STRING or K_LIST */
HB_BOOL bIsAllocated; /* if buffers were allocated */
char *buffer; /* file buffer pointer */
char *lbuff; /* line buffer pointer */
char *vseg; /* video segment variable */
/* prototypes */
static void chattr(int x, int y, int len, int attr);
static HB_FOFFSET getblock( HB_FOFFSET offset );
static void buff_align(void);
static void win_align(void);
static void disp_update(int offset);
static void windown(void);
static void winup(void);
static void linedown(void);
static void lineup(void);
static void filetop(void);
static void filebot(void);
/*
* chattr() replace the color attribute with a new one starting at
* location x, y and going for length len.
*
*/
static void chattr(int x, int y, int len, int attr)
{
int i;
char *vmem;
vmem = vseg + (y * (width + 1) * 2) + (x * 2) + 1;
/* calc the screen memory coord */
for (i = 0; i <= len; i++, vmem += 2) /* write the new attribute value */
*vmem = (char) attr;
}
/*
* function getblock() reads the text file and returns the a block.
* the variables offset and buffsize tell it where to start reading and
* how many bytes to try to read. if the block read in would not fill
* the buffer then the offset is adjusted so that the start or end of
* of the file is positioned at the head or tail of the buffer.
*
* it returns the offset into the file of the first byte of the buffer.
*
*/
static HB_FOFFSET getblock( HB_FOFFSET offset )
{
/*
set the file pointer to the proper offset
and if an error occured then check to see
if a positive offset was requested, if so
then set the pointer to the offset from
the end of the file, otherwise set it from
the beginning of the file.
*/
hb_fsSeekLarge( infile, offset, FS_SET );
/* read in the file and set the buffer bottom variable equal */
/* to the number of bytes actually read in. */
buffbot = hb_fsReadLarge( infile, buffer, buffsize );
/* if a full buffer's worth was not read in, make it full. */
if (( buffbot != buffsize ) && ( fsize > buffsize ))
{
if ( offset > 0 )
hb_fsSeekLarge( infile, -buffsize, FS_END );
else
hb_fsSeekLarge( infile, buffsize, FS_SET );
buffbot = hb_fsReadLarge( infile, buffer, buffsize );
}
/* return the actual file position */
return hb_fsSeekLarge( infile, 0, FS_RELATIVE ) - buffbot;
}
/*
* buff_align makes sure the buffer top and bottom variables point
* to actual complete lines of text.
*
*/
static void buff_align()
{
HB_ISIZ i;
bufftop = 0;
buffbot = buffsize;
if ( buffoffset != 0 ) /* if the buffoffset is otherthan 0 */
{
i = bufftop; /* start at the top of the file and scan */
/* forward until a CR is reached. */
while (( buffer[i] != CR ) && ( i < buffbot ))
i++;
bufftop = i + 2;
}
/* if the buffer offset is not a complete */
/* buffer's length away from the file end */
if ( buffoffset + buffbot != fsize )
{
/*
if the file position of the last byte
of the buffer would end up past the
end of the file, then the buffer does
contain a complete buffer full and the
buffer end pointer needs to be set to
the last character of the file.
*/
if ( buffoffset + buffbot > fsize )
buffbot = ( HB_ISIZ ) ( fsize - buffoffset );
i = buffbot; /* point the end of the buffer to a valid */
/* complete text line. */
while (( buffer[i] != CR ) && ( i > bufftop ))
i--;
buffbot = i + 2;
}
}
/*
* win_align takes the value for wintop and then figures out where
* winbot would be. if winbot would extend past the end of the
* buffer, then the top of the window is adjusted to ensure that a full
* screen of text will appear. This simplifies the cursor routines.
*
*/
static void win_align()
{
int i;
winbot = wintop; /* find out if there is enough text for */
i = 0; /* full window. */
while (( winbot < buffbot ) && ( i < height ))
{
if ( buffer[winbot] == CR )
i++;
winbot++;
}
if ( i < height ) /* if there is not a full window, */
{
/* then retrofit winbot to the end of a line */
while ( buffer[winbot] != LF && winbot > bufftop)
winbot--;
wintop = winbot;
i = 0; /* and setup wintop */
while (( wintop > bufftop ) && ( i <= height ))
{
if ( buffer[wintop] == LF )
i++;
wintop--;
}
if ( wintop != bufftop )
wintop += 2;
}
}
/*
* this routine displays the actual text in the window. This is done
* by taking each line and placing it in a string. the screen line
* is then taken from the appropriate group of characters in the string.
* this allows a window to page left-right across the buffer without
* having to use any complex algorithm to calc the needed chars.
*
*/
static void disp_update(int offset)
{
int line, col, pos, i;
char *vmem;
bRefresh = HB_FALSE;
line = 0;
while ( line < height )
{
/*
calculate the initial position, this save execution
time because each column is considered as a offset
from the line start
*/
pos = (line * (width + 1) * 2);
/* copy string to temp buffer */
for (i = 0; buffer[offset] != CR && offset <= winbot; offset++)
{
if ( i <= maxlin )
{
if (buffer[offset] == '\t') /* check for a tab */
{
lbuff[i++] = ' '; /* pad with spaces */
while (i % TABSET && i <= maxlin) /* until tab stop */
lbuff[i++] = ' '; /* is reached or EOL */
}
else lbuff[i++] = buffer[offset];
}
}
for (; i <= maxlin; i++) /* fill out with spaces */
lbuff[i] = ' ';
/* place the proper characters onto the screen */
for (i = wincol, col = 0; col <= width; col++)
{
vmem = vseg + pos + (col * 2);
*vmem = lbuff[i++];
}
line += 1;
offset += 2;
}
hb_gtRest( sline, scol, eline, ecol, vseg );
}
/*
* move the window pointers so that a new window's worth of information
* is visible. it adjusts the pointers within the buffer and if necessary
* it calls the getblock function to load in a new buffer
*
*/
static void winup()
{
int k;
HB_FOFFSET i, j;
bRefresh = HB_TRUE;
k = wintop - 3;
while (( buffer[k] != CR ) && ( k > bufftop ))
k--;
if ( k >= bufftop )
{
if (buffer[k] == CR) k += 2;
wintop = k;
k = winbot - 3;
while ( buffer[k] != CR )
k--;
winbot = k + 2;
}
else
if ( bufftop + buffoffset > 0 && fsize > buffsize )
{
i = buffoffset + wintop;
j = buffoffset - (buffsize / 2);
if ( j < 0 )
j = 0;
buffoffset = getblock(j);
wintop = ((int) (i - buffoffset));
buff_align();
win_align();
}
}
/*
* move the window pointers so that a new window's worth of information
* is visible. it adjusts the pointers within the buffer and if necessary
* it calls the getblock function to load in a new buffer
*
*/
static void windown()
{
int k;
HB_FOFFSET i, j;
bRefresh = HB_TRUE;
k = winbot;
while (( buffer[k] != CR ) && ( k <= buffbot ))
k++;
k += 2;
if ( k <= buffbot )
{
winbot = k;
k = wintop;
while ( buffer[k] != CR )
k++;
wintop = k + 2;
}
else
if ( (buffbot + buffoffset) < fsize && fsize > buffsize)
{
i = buffoffset + wintop;
j = i;
if ( j > fsize )
j = fsize - buffsize;
buffoffset = getblock(j);
if ( i < buffoffset )
wintop = 0;
else
wintop = ((int) (i - buffoffset));
buff_align();
win_align();
}
}
/* move the cursor one line down */
static void linedown()
{
if ( winrow < eline ) /* if cursor not at last line */
winrow += 1;
else /* otherwise adjust the window top variable */
windown();
}
/* move the cursor one line up */
static void lineup()
{
if ( winrow > sline )
winrow -= 1;
else
winup();
}
/* go to the top of the file */
static void filetop()
{
if ( buffoffset != 0 )
{
buffoffset = getblock(0);
buff_align();
}
bRefresh = HB_TRUE;
wintop = ( int ) buffoffset;
winrow = sline;
wincol = 0;
win_align();
}
/* goto the bottom of the file */
static void filebot()
{
if( ( buffbot + buffoffset) < fsize && fsize > buffsize )
{
buffoffset = getblock(fsize + 1);
buff_align();
}
bRefresh = HB_TRUE;
wintop = ( int ) buffbot - 3;
winrow = eline;
wincol = 0;
win_align();
}
HB_FUNC( _FT_DFINIT )
{
int rval;
HB_ISIZ j;
HB_ISIZ i;
HB_SIZE ulSize;
rval = 0;
sline = hb_parni(2); /* top row of window */
scol = hb_parni(3); /* left col */
eline = hb_parni(4); /* bottom row */
ecol = hb_parni(5); /* right col */
width = ecol - scol; /* calc width of window */
height = eline - sline + 1; /* calc height of window */
hb_gtRectSize( sline, scol, eline, ecol, &ulSize );
vseg = (char * ) hb_xalloc( ulSize );
if (vseg != NULL)
hb_gtSave( sline, scol, eline, ecol, vseg );
maxlin = hb_parni(12);
buffsize = hb_parns(13); /* yes - load value */
buffer = (char *) hb_xalloc(buffsize); /* allocate memory */
lbuff = (char *) hb_xalloc(maxlin + 1); /* for buffers */
bIsAllocated = !(buffer == NULL || lbuff == NULL || vseg == NULL);
/* memory allocated? */
if (!bIsAllocated)
{
rval = 8; /* return error code 8 (memory) */
if (buffer != NULL) hb_xfree(buffer);
if (lbuff != NULL) hb_xfree(lbuff);
if (vseg != NULL) hb_xfree(vseg);
}
else /* get parameters */
{
infile = hb_numToHandle( hb_parnint( 1 ) ); /* file handle */
j = hb_parni(6); /* starting line value */
norm = hb_parni(7); /* normal color attribute */
hlight = hb_parni(8); /* highlight color attribute */
if( HB_ISARRAY( 9 ) )
{
keytype = K_LIST;
kcount = hb_parinfa( 9, 0 );
if (kcount > 24)
kcount = 24;
for (i = 1; i <= kcount; i++)
keylist[i - 1] = hb_parvni( 9, i ); /* get exit key list */
}
else
{
keytype = K_STRING;
kcount = hb_parclen( 9 );
if( kcount > 24 )
kcount = 24;
hb_strncpy(kstr, hb_parcx( 9 ), kcount - 1); /* get exit key string */
}
bBrowse = hb_parl(10); /* get browse flag */
colinc = hb_parni(11); /* column skip value */
bufftop = 0; /* init buffer top pointer */
buffbot = buffsize; /* init buffer bottom pointer */
buffoffset = 0; /* curr line offset into buffer */
winrow = sline; /* init window row */
wincol = 0; /* init window col */
wintop = 0; /* init window top pointer */
winbot = 0; /* init window bottom pointer */
/* get file size */
fsize = hb_fsSeek( infile, 0, FS_END ) - 1;
/* get the first block */
hb_fsSeek( infile, 0, FS_SET );
/* if block less than buffsize */
if ( fsize < buffbot )
buffbot = (int) fsize; /* then set buffer bottom */
/* set the current lines buffer offset pointer */
buffoffset = getblock( bufftop );
/* align buffer and window pointer to valid values */
buff_align();
win_align();
/* point line pointer to line passed by caller */
for (i = 1; i < j; i++)
linedown();
hb_gtRest( sline, scol, eline, ecol, vseg );
}
hb_retni(rval);
}
HB_FUNC ( _FT_DFCLOS )
{
if (bIsAllocated)
{
if (buffer != NULL) hb_xfree(buffer); /* free up allocated buffer memory */
if (lbuff != NULL) hb_xfree(lbuff);
if (vseg != NULL) hb_xfree(vseg);
}
}
HB_FUNC( FT_DISPFILE )
{
int i;
char rval[2];
HB_BOOL bDone;
int ch;
/* make sure buffers were allocated and file was opened */
if (bIsAllocated && infile > 0)
{
bDone = HB_FALSE;
bRefresh = HB_TRUE;
/* draw inside of window with normal color attribute */
for (i = 0; i < height; i++)
chattr(0, i, width, norm);
hb_gtRest( sline, scol, eline, ecol, vseg );
/* main processing loop -- terminated by user key press */
do
{
if( bRefresh ) /* redraw window contents? */
disp_update(wintop);
hb_gtRest( sline, scol, eline, ecol, vseg );
/* if not browse, highlight the current line */
if( ! bBrowse )
chattr(0, winrow - sline, width, hlight);
hb_gtRest( sline, scol, eline, ecol, vseg );
hb_gtSetPos( winrow, scol );
ch = hb_inkey( HB_TRUE, 0.0, INKEY_ALL );
/* if not browse, then un-highlight current line */
if( ! bBrowse )
chattr(0, winrow - sline, width, norm);
hb_gtRest( sline, scol, eline, ecol, vseg );
/* figure out what the user wants to do */
switch (ch)
{
case K_DOWN : if( bBrowse ) /* if browse flag */
winrow = eline; /* is set, force */
/* active line to */
linedown(); /* be last line */
break;
case K_UP : if( bBrowse ) /* if browse flag */
winrow = sline; /* is set, force */
/* active line to */
lineup(); /* be first line */
break;
case K_LEFT : wincol -= colinc; /* move cursor */
bRefresh = HB_TRUE; /* to the left */
if ( wincol < 0 )
wincol = 0;
break;
case K_RIGHT : wincol += colinc; /* move cursor */
bRefresh = HB_TRUE; /* to the right */
if ( wincol > (maxlin - width) )
wincol = maxlin - width;
break;
case K_HOME : wincol = 0; /* move cursor */
bRefresh = HB_TRUE; /* to first col */
break;
/* move cursor to last col */
case K_END : wincol = maxlin - width;
bRefresh = HB_TRUE;
break;
case K_CTRL_LEFT : wincol -= 16; /* move cursor */
bRefresh = HB_TRUE; /* 16 col to left */
if ( wincol < 0 )
wincol = 0;
break;
case K_CTRL_RIGHT : wincol += 16; /* move cursor */
bRefresh = HB_TRUE; /* 16 col to right */
if ( wincol > (maxlin - width) )
wincol = maxlin - width;
break;
case K_PGUP : for (i = 0; i < height; i++) /* move window */
winup(); /* up one page */
break;
case K_PGDN : for (i = 0; i < height; i++) /* move window */
windown(); /* down 1 page */
break;
case K_CTRL_PGUP : filetop(); /* move cursor to */
break; /* to top of file */
case K_CTRL_PGDN : filebot(); /* move cursor to */
break; /* to bot of file */
case K_ENTER : bDone = HB_TRUE; /* carriage return */
break; /* terminates */
case K_ESC : bDone = HB_TRUE; /* escape key */
break; /* terminates */
/* scan key list and see if key pressed is there */
default : if (keytype == K_STRING)
{
for (i = 0; i <= kcount; i++)
if ((ch > 0) && (ch < 256))
if ( (int) kstr[i] == ch )
bDone = HB_TRUE;
break; /* if so terminate */
}
else
{
for (i = 0; i < kcount; i++)
if ( keylist[i] == ch )
bDone = HB_TRUE;
break;
}
}
} while( ! bDone );
}
else
ch = 0;
/* store the key pressed as a character to be returned */
/* return key value to caller */
if( keytype == K_STRING )
{
rval[0] = (char) ch;
rval[1] = '\0';
hb_retc( rval );
}
else
hb_retni( ch );
}