home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
new
/
util
/
edit
/
jade
/
src
/
render.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-09
|
22KB
|
782 lines
/* render.c -- System-independant rendering
Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
This file is part of Jade.
Jade is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Jade is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jade; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "jade.h"
#include "jade_protos.h"
#include <assert.h>
#ifdef HAVE_AMIGA
# ifdef _DCC
# define GfxBase_DECLARED
# endif
# include <clib/graphics_protos.h>
# include <graphics/gfxbase.h>
# include <graphics/gfxmacros.h>
extern struct GfxBase *GfxBase;
#endif
_PR void cursor(VW *, bool);
_PR void pen_to_line(VW *, long);
_PR void pen_to_pos(VW *, long, long);
_PR void pen_to_glyph_pos(VW *, long, long);
_PR void draw_bit(VW *, int, u_char *, int, long, long);
_PR void draw_line(VW *, LINE *, long);
_PR void redraw_all(VW *);
_PR void redraw_region(VW *, POS *, POS *);
_PR void redraw_lines(VW *, long, long);
_PR void redraw_lines_clr(VW *, long, long);
_PR void redraw_line_from(VW *, long, long);
_PR void redraw_rect(VW *, POS *, POS *, bool);
_PR void cut_paste_lines(VW *, long, long);
_PR void draw_message_line(VW *);
_PR void redraw_message(VW *, u_char *, int);
_PR void redraw_cmd_line(VW *, u_char *, u_char *, long, long);
_PR void redraw_cmd_line_from(VW *, u_char *, u_char *, long, long, long);
_PR void cmd_line_cursor(VW *, bool);
/* I hope this is enough!? :-| */
static u_char glyph_buf[512];
static void
pen_to_cursor(VW *vw)
{
register int x, y;
calc_cursor_offset(vw);
y = vw->vw_FontStart +
((vw->vw_CursorPos.pos_Line - vw->vw_StartLine) * vw->vw_FontY);
x = vw->vw_XStartPix +
((vw->vw_LastCursorOffset - vw->vw_StartCol) * vw->vw_FontX);
if(x < vw->vw_XStartPix)
x = vw->vw_XStartPix;
MOVE(vw, x, y);
}
void
pen_to_line(VW *vw, long line)
{
MOVE(vw, vw->vw_XStartPix,
vw->vw_FontStart + ((line - vw->vw_StartLine) * vw->vw_FontY));
}
void
pen_to_pos(VW *vw, long col, long line)
{
TX *tx = vw->vw_Tx;
int x, y;
y = vw->vw_FontStart + ((line - vw->vw_StartLine) * vw->vw_FontY);
assert(line < tx->tx_NumLines);
x = vw->vw_XStartPix + ((glyph_col(tx, col, line) - vw->vw_StartCol)
* vw->vw_FontX);
if(x < vw->vw_XStartPix)
x = vw->vw_XStartPix;
MOVE(vw, x, y);
}
void
pen_to_glyph_pos(VW *vw, long gcol, long line)
{
int x, y;
y = vw->vw_FontStart + ((line - vw->vw_StartLine) * vw->vw_FontY);
x = vw->vw_XStartPix + ((gcol - vw->vw_StartCol) * vw->vw_FontX);
if(x < vw->vw_XStartPix)
x = vw->vw_XStartPix;
MOVE(vw, x, y);
}
void
cursor(VW *vw, bool status)
{
if((vw->vw_Flags & VWFF_SLEEPING) == 0)
{
if(vw->vw_Flags & VWFF_STATUS_CURS)
{
PEN_X(vw) = vw->vw_XStartPix
+ ((vw->vw_MessageLen < vw->vw_MaxX)
? vw->vw_MessageLen
: (vw->vw_MaxX - 1)) * vw->vw_FontX;
PEN_Y(vw) = vw->vw_MessageFontY;
TEXT(vw, P_BLOCK, " ", 1);
}
else
{
if(vw->vw_CursorPos.pos_Line < vw->vw_StartLine + vw->vw_MaxY)
{
int pencol;
LINE *line = vw->vw_Tx->tx_Lines + vw->vw_CursorPos.pos_Line;
long cursoff = vw->vw_CursorPos.pos_Col;
int inblk = cursor_in_block(vw);
if((status && inblk) || (!status && !inblk))
pencol = P_TEXT;
else
pencol = P_BLOCK;
pen_to_cursor(vw);
if((cursoff + 1) >= line->ln_Strlen)
TEXT(vw, pencol, " ", 1);
else
TEXT(vw, pencol, char_glyphs(vw->vw_Tx,
line->ln_Line[cursoff]), 1);
}
}
}
}
/*
* draws a section of a line of bytes, beg and end are x ordinates
*/
void
draw_bit(VW *vw, int colour, u_char *str, int slen, long beg, long end)
{
long startx = vw->vw_StartCol;
long endx = vw->vw_MaxX + startx + 1;
long length;
if(end < startx)
return;
if(beg < startx)
beg = startx;
if(end > endx)
end = endx;
if((length = end - beg) <= 0)
return;
slen -= beg;
if(slen <= 0)
return;
if(slen < length)
length = slen;
TEXT(vw, colour, str + beg, length);
}
static void
draw_block_line(VW *vw, long blockStartCol, long blockEndCol,
long drawEndCol, bool useBEC)
{
int xend = ((drawEndCol - vw->vw_StartCol) * vw->vw_FontX)
+ vw->vw_XStartPix;
if(PEN_X(vw) < vw->vw_XEndPix)
{
int rectblocks = vw->vw_Flags & VWFF_RECTBLOCKS;
if(useBEC || rectblocks)
{
int xblkend = ((blockEndCol - vw->vw_StartCol)
* vw->vw_FontX) + vw->vw_XStartPix;
if(rectblocks)
{
if((((PEN_X(vw) - vw->vw_XStartPix) / vw->vw_FontX)
+ vw->vw_StartCol) < blockStartCol)
{
PEN_X(vw) = ((blockStartCol - vw->vw_StartCol)
* vw->vw_FontX) + vw->vw_XStartPix;
}
}
if(xblkend >= xend)
xblkend = xend;
if(xblkend > PEN_X(vw))
{
SET_AREA(vw, PEN_X(vw), PEN_Y(vw) - FONT_ASCENT(vw),
xblkend - PEN_X(vw), vw->vw_FontY);
}
}
else
{
SET_AREA(vw, PEN_X(vw), PEN_Y(vw) - FONT_ASCENT(vw),
xend - PEN_X(vw), vw->vw_FontY);
}
}
}
/*
* pen should be at start of line to draw (line should be cleared first)
*/
void
draw_line(VW *vw, LINE *line, long lineNum)
{
long glyphs = make_glyph_array(vw->vw_Tx, line->ln_Line, 0,
line->ln_Strlen-1, glyph_buf,
vw->vw_StartCol, vw->vw_MaxX);
if(vw->vw_BlockStatus != 0)
TEXT(vw, P_TEXT, glyph_buf, glyphs);
else
{
long block0col = glyph_col(vw->vw_Tx, vw->vw_BlockS.pos_Col,
vw->vw_BlockS.pos_Line);
long block1col = glyph_col(vw->vw_Tx, vw->vw_BlockE.pos_Col,
vw->vw_BlockE.pos_Line);
u_char *glyph_line = glyph_buf - vw->vw_StartCol;
long abs_glyphs = glyphs + vw->vw_StartCol;
if(vw->vw_Flags & VWFF_RECTBLOCKS)
{
if(block0col > block1col)
{
long tmp;
tmp = block0col;
block0col = block1col;
block1col = tmp;
}
}
switch(line_in_block(vw, lineNum))
{
case 0: /* none of line in block */
TEXT(vw, P_TEXT, glyph_buf, glyphs);
break;
case 1: /* whole of line in block */
TEXT(vw, P_BLOCK, glyph_buf, glyphs);
draw_block_line(vw, block0col, block1col,
vw->vw_StartCol + vw->vw_MaxX, FALSE);
break;
case 2: /* start of line in block */
draw_bit(vw, P_BLOCK, glyph_line, abs_glyphs, 0, block1col);
draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, block1col,
abs_glyphs);
draw_block_line(vw, block0col, block1col,
vw->vw_StartCol + vw->vw_MaxX, TRUE);
break;
case 3: /* end of line in block */
draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, 0, block0col);
draw_bit(vw, P_BLOCK, glyph_line, abs_glyphs, block0col,
abs_glyphs);
draw_block_line(vw, block0col, block1col,
vw->vw_StartCol + vw->vw_MaxX, FALSE);
break;
case 4: /* middle of line in block */
draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, 0, block0col);
draw_bit(vw, P_BLOCK, glyph_line, abs_glyphs, block0col,
block1col);
draw_bit(vw, P_TEXT, glyph_line, abs_glyphs, block1col,
abs_glyphs);
draw_block_line(vw, block0col, block1col,
vw->vw_StartCol + vw->vw_MaxX, TRUE);
break;
}
}
}
/*
* pen should be at first draw position, draws from character XSTART to the
* end of the line.
*/
static void
draw_line_part(VW *vw, LINE *line, long lineNum, long xStart,
long glyph_xStart)
{
u_char *src = line->ln_Line + xStart;
u_long srclen = (line->ln_Strlen - 1) - xStart;
long glyphs = make_glyph_array(vw->vw_Tx, src, glyph_xStart, srclen,
glyph_buf, 0,
(vw->vw_StartCol+vw->vw_MaxX)-glyph_xStart);
if(vw->vw_BlockStatus != 0)
TEXT(vw, P_TEXT, glyph_buf, glyphs);
else
{
long block0col = glyph_col(vw->vw_Tx, vw->vw_BlockS.pos_Col,
vw->vw_BlockS.pos_Line);
long block1col = glyph_col(vw->vw_Tx, vw->vw_BlockE.pos_Col,
vw->vw_Blo