home *** CD-ROM | disk | FTP | other *** search
- /* 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"
-
- #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 pentocursor(VW *);
- _PR void pentoline(VW *, short);
- _PR void pentopos(VW *, short, short);
- _PR void cursor(VW *, bool);
- _PR void drawbit(VW *, int, u_char *, int, long, long);
- _PR void drawline(VW *, LINE *, long);
- _PR void drawlinelength(VW *, LINE *, long, long, long);
- _PR void redrawall(VW *);
- _PR void redrawallfrom(VW *, long, long);
- _PR void redrawregion(VW *, POS *, POS *);
- _PR void redrawline(VW *, long);
- _PR void redrawlines(VW *, long, long);
- _PR void redrawlinesclr(VW *, long, long);
- _PR void redrawlinefrom(VW *, long, long);
- _PR void redrawrect(VW *, POS *, POS *, bool);
- _PR void cutpastelines(VW *, long, long);
-
- void
- pentocursor(VW *vw)
- {
- int x, y;
- x = vw->vw_XStartPix +
- ((vw->vw_CursorPos.pos_Col - vw->vw_StartCol) * vw->vw_FontX);
- if(x < vw->vw_XStartPix)
- x = vw->vw_XStartPix;
- y = vw->vw_FontStart +
- ((vw->vw_CursorPos.pos_Line - vw->vw_StartLine) * vw->vw_FontY);
- MOVE(vw, x, y);
- }
-
- /*
- * note actual y coordinate not line number
- */
- void
- pentoline(VW *vw, short yPos)
- {
- MOVE(vw, vw->vw_XStartPix, vw->vw_FontStart + (yPos * vw->vw_FontY));
- }
-
- /*
- * this also takes coordinates...
- */
- void
- pentopos(VW *vw, short xPos, short yPos)
- {
- int x, y;
- x = vw->vw_XStartPix + (xPos * vw->vw_FontX);
- if(x < vw->vw_XStartPix)
- x = vw->vw_XStartPix;
- y = vw->vw_FontStart + (yPos * vw->vw_FontY);
- MOVE(vw, x, y);
- }
-
- void
- cursor(VW *vw, bool status)
- {
- if(!vw->vw_Sleeping
- && (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 = cursinblock(vw);
- if((status && inblk) || (!status && !inblk))
- pencol = P_TEXT;
- else
- pencol = P_BLOCK;
- pentocursor(vw);
- if((cursoff + 1) >= line->ln_Strlen)
- TEXT(vw, pencol, " ", 1);
- else
- TEXT(vw, pencol, line->ln_Line + cursoff, 1);
- }
- }
-
- /*
- * draws a section of a line of text, beg and end are x ordinates
- */
- void
- drawbit(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 - 1) <= 0)
- return;
- slen -= beg;
- if(slen <= 0)
- return;
- if(slen < length)
- length = slen;
- TEXT(vw, colour, str + beg, length);
- }
-
- static void
- drawblockline(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
- drawline(VW *vw, LINE *line, long lineNum)
- {
- long llen = line->ln_Strlen;
- long slen = llen - 1;
- if(vw->vw_BlockStatus != 0)
- {
- drawbit(vw, P_TEXT, line->ln_Line, slen, 0, llen);
- }
- else
- {
- long block0col = vw->vw_BlockS.pos_Col;
- long block1col = vw->vw_BlockE.pos_Col;
- if(vw->vw_Flags & VWFF_RECTBLOCKS)
- {
- if(block0col > block1col)
- {
- long tmp;
- tmp = block0col;
- block0col = block1col;
- block1col = tmp;
- }
- block1col++;
- }
- switch(lineinblock(vw, lineNum))
- {
- case 0: /* none of line in block */
- drawbit(vw, P_TEXT, line->ln_Line, slen, 0, llen);
- break;
- case 1: /* whole of line in block */
- drawbit(vw, P_BLOCK, line->ln_Line, slen, 0, llen);
- drawblockline(vw, block0col, block1col,
- vw->vw_StartCol + vw->vw_MaxX, FALSE);
- break;
- case 2: /* start of line in block */
- drawbit(vw, P_BLOCK, line->ln_Line, slen, 0, block1col + 1);
- drawbit(vw, P_TEXT, line->ln_Line, slen, block1col, llen);
- drawblockline(vw, block0col, block1col,
- vw->vw_StartCol + vw->vw_MaxX, TRUE);
- break;
- case 3: /* end of line in block */
- drawbit(vw, P_TEXT, line->ln_Line, slen, 0, block0col + 1);
- drawbit(vw, P_BLOCK, line->ln_Line, slen, block0col, llen);
- drawblockline(vw, block0col, block1col,
- vw->vw_StartCol + vw->vw_MaxX, FALSE);
- break;
- case 4: /* middle of line in block */
- drawbit(vw, P_TEXT, line->ln_Line, slen, 0, block0col + 1);
- drawbit(vw, P_BLOCK, line->ln_Line, slen, block0col,
- block1col + 1);
- drawbit(vw, P_TEXT, line->ln_Line, slen, block1col, llen);
- drawblockline(vw, block0col, block1col,
- vw->vw_StartCol + vw->vw_MaxX, TRUE);
- break;
- }
- }
- }
-
- /*
- * pen should be at first draw position
- * xEnd is *ex*clusive (ie, line->ln_Line[xEnd] isn't drawn)
- */
- void
- drawlinelength(VW *vw, LINE *line, long lineNum, long xStart, long xEnd)
- {
- int slen = line->ln_Strlen - 1;
- if(vw->vw_BlockStatus)
- {
- drawbit(vw, P_TEXT, line->ln_Line, slen, xStart, xEnd);
- }
- else
- {
- long block0col = vw->vw_BlockS.pos_Col;
- long block1col = vw->vw_BlockE.pos_Col;
- if(vw->vw_Flags & VWFF_RECTBLOCKS)
- {
- if(block0col > block1col)
- {
- long tmp;
- tmp = block0col;
- block0col = block1col;
- block1col = tmp;
- }
- block1col++;
- }
- switch(lineinblock(vw, lineNum))
- {
- case 0: /* none of line in block */
- drawbit(vw, P_TEXT, line->ln_Line, slen, xStart, xEnd);
- break;
- case 1: /* whole of line in block */
- drawbit(vw, P_BLOCK, line->ln_Line, slen, xStart, xEnd);
- drawblockline(vw, block0col, block1col, xEnd, FALSE);
- break;
- case 2: /* start of line in block */
- if(xStart < block1col)
- drawbit(vw, P_BLOCK, line->ln_Line, slen, xStart, block1col+1);
- else
- block1col = xStart;
- drawbit(vw, P_TEXT, line->ln_Line, slen, block1col, xEnd);
- drawblockline(vw, block0col, block1col, xEnd, TRUE);
- break;
- case 3: /* end of line in block */
- if(xStart < block0col)
- drawbit(vw, P_TEXT, line->ln_Line, slen, xStart, block0col+1);
- else
- block0col = xStart;
- drawbit(vw, P_BLOCK, line->ln_Line, slen, block0col, xEnd);
- drawblockline(vw, block0col, block1col, xEnd, FALSE);
- break;
- case 4: /* middle of line in block */
- if(xStart < block0col)
- drawbit(vw, P_TEXT, line->ln_Line, slen, xStart, block0col+1);
- else
- block0col = xStart;
- if(block0col < block1col)
- drawbit(vw, P_BLOCK, line->ln_Line, slen, block0col,
- block1col + 1);
- else
- block1col = block0col;
- drawbit(vw, P_TEXT, line->ln_Line, slen, block1col, xEnd);
- drawblockline(vw, block0col, block1col, xEnd, TRUE);
- break;
- }
- }
- }
-
- #define drawlinepart(vw, line, lineNum, xStart) \
- drawlinelength(vw, line, lineNum, xStart, vw->vw_StartCol + vw->vw_MaxX+1)
-
- void
- redrawall(VW *vw)
- {
- long linenum = vw->vw_StartLine;
- LINE *line = vw->vw_Tx->tx_Lines + linenum;
- short y = 0;
- CLR_RECT(vw, vw->vw_XStartPix, vw->vw_YStartPix,
- vw->vw_XEndPix, vw->vw_YEndPix);
- while((y < vw->vw_MaxY) && (linenum < vw->vw_Tx->tx_NumLines))
- {
- pentoline(vw, y);
- drawline(vw, line, linenum);
- y++;
- linenum++;
- line++;
- }
- }
-
- void
- redrawallfrom(VW *vw, long col, long lineNum)
- {
- LINE *line = vw->vw_Tx->tx_Lines + lineNum;
- short y = lineNum - vw->vw_StartLine;
- int yord = (y * vw->vw_FontY) + vw->vw_YStartPix;
- if(col < vw->vw_StartCol)
- col = vw->vw_StartCol;
- if((y >= 0) && (y < vw->vw_MaxY))
- {
- CLR_RECT(vw, ((col-vw->vw_StartCol)*vw->vw_FontX) + vw->vw_XStartPix,
- yord, vw->vw_XEndPix, yord + vw->vw_FontY);
- pentopos(vw, col - vw->vw_StartCol, y);
- drawlinepart(vw, line, lineNum, col);
- line++;
- lineNum++;
- y++;
- yord += vw->vw_FontY;
- }
- else
- {
- y = 0;
- yord = vw->vw_YStartPix;
- lineNum = vw->vw_StartLine;
- line = vw->vw_Tx->tx_Lines + lineNum;
- }
- if(y < vw->vw_MaxY)
- {
- CLR_RECT(vw, vw->vw_XStartPix, yord, vw->vw_XEndPix, vw->vw_YEndPix);
- while((y < vw->vw_MaxY) && (lineNum < vw->vw_Tx->tx_NumLines))
- {
- pentoline(vw, y);
- drawline(vw, line, lineNum);
- y++;
- lineNum++;
- line++;
- }
- }
- }
-
- void
- redrawregion(VW *vw, POS *start, POS *end)
- {
- long col = start->pos_Col;
- long linenum = start->pos_Line;
- LINE *line = vw->vw_Tx->tx_Lines + linenum;
- short y = linenum - vw->vw_StartLine;
- short yend = end->pos_Line - vw->vw_StartLine + 1;
- int yord = (y * vw->vw_FontY) + vw->vw_YStartPix;
- if(col < vw->vw_StartCol)
- col = vw->vw_StartCol;
- if(yend > vw->vw_MaxY)
- yend = vw->vw_MaxY;
- if((y >= 0) && (y < yend))
- {
- CLR_RECT(vw, ((col-vw->vw_StartCol)*vw->vw_FontX) + vw->vw_XStartPix,
- yord, vw->vw_XEndPix, yord + vw->vw_FontY);
- pentopos(vw, col - vw->vw_StartCol, y);
- if(linenum < vw->vw_Tx->tx_NumLines)
- drawlinepart(vw, line, linenum, col);
- line++;
- linenum++;
- y++;
- yord += vw->vw_FontY;
- }
- else
- {
- y = 0;
- yord = vw->vw_YStartPix;
- linenum = vw->vw_StartLine;
- line = vw->vw_Tx->tx_Lines + linenum;
- }
- if(y < yend)
- {
- CLR_RECT(vw, vw->vw_XStartPix, yord, vw->vw_XEndPix,
- vw->vw_YStartPix + (yend * vw->vw_FontY));
- while((y < yend) && (linenum < vw->vw_Tx->tx_NumLines))
- {
- pentoline(vw, y);
- drawline(vw, line, linenum);
- y++;
- linenum++;
- line++;
- }
- }
- }
-
- void
- redrawline(VW *vw, long lineNum)
- {
- int yord = ((lineNum-vw->vw_StartLine) * vw->vw_FontY) + vw->vw_YStartPix;
- CLR_RECT(vw, vw->vw_XStartPix, yord, vw->vw_XEndPix, yord + vw->vw_FontY);
- pentoline(vw, lineNum - vw->vw_StartLine);
- drawline(vw, vw->vw_Tx->tx_Lines + lineNum, lineNum);
- }
-
- /*
- * DOES NOT clear the drawing area
- */
- void
- redrawlines(VW *vw, long startLine, long endLine)
- {
- LINE *line = vw->vw_Tx->tx_Lines;
- short y;
- if(startLine < vw->vw_StartLine)
- startLine = vw->vw_StartLine;
- y = startLine - vw->vw_StartLine;
- line += startLine;
- if(endLine > vw->vw_Tx->tx_NumLines)
- endLine = vw->vw_Tx->tx_NumLines;
- endLine -= vw->vw_StartLine;
- if(endLine > vw->vw_MaxY)
- endLine = vw->vw_MaxY;
- while(y < endLine)
- {
- pentoline(vw, y);
- drawline(vw, line, startLine);
- startLine++;
- y++;
- line++;
- }
- }
-
- void
- redrawlinesclr(VW *vw, long startLine, long endLine)
- {
- LINE *line = vw->vw_Tx->tx_Lines;
- short y;
- endLine++;
- if((endLine <= vw->vw_StartLine)
- || (startLine > (vw->vw_StartLine + vw->vw_MaxY)))
- {
- return;
- }
- if(startLine < vw->vw_StartLine)
- startLine = vw->vw_StartLine;
- y = startLine - vw->vw_StartLine;
- line += startLine;
- if(endLine > vw->vw_Tx->tx_NumLines)
- endLine = vw->vw_Tx->tx_NumLines;
- endLine -= vw->vw_StartLine;
- if(endLine > vw->vw_MaxY)
- endLine = vw->vw_MaxY;
- CLR_RECT(vw, vw->vw_XStartPix, (y * vw->vw_FontY) + vw->vw_YStartPix,
- vw->vw_XEndPix, (endLine * vw->vw_FontY) + vw->vw_YStartPix);
- while(y < endLine)
- {
- pentoline(vw, y);
- drawline(vw, line, startLine);
- startLine++;
- y++;
- line++;
- }
- }
-
- void
- redrawlinefrom(VW *vw, long col, long lineNum)
- {
- if(col < vw->vw_StartCol)
- col = vw->vw_StartCol;
- if((lineNum >= vw->vw_StartLine)
- && (lineNum < vw->vw_StartLine + vw->vw_MaxY))
- {
- int yord = ((lineNum - vw->vw_StartLine) * vw->vw_FontY)
- + vw->vw_YStartPix;
- CLR_RECT(vw, vw->vw_XStartPix +((col-vw->vw_StartCol) * vw->vw_FontX),
- yord, vw->vw_XEndPix, yord + vw->vw_FontY);
- pentopos(vw, col - vw->vw_StartCol, lineNum - vw->vw_StartLine);
- drawlinepart(vw, vw->vw_Tx->tx_Lines + lineNum, lineNum, col);
- }
- }
-
- /*
- * Assumes (start, end) is valid AND totally viewable (ie, no checks, no
- * clipping). Should be ok since this is meant for Expose type events
- * start is probably trashed
- * `gapBlank' says whether or not I need to clear the space I'm drawing into.
- */
- void
- redrawrect(VW *vw, POS *start, POS *end, bool gapBlank)
- {
- TX *tx = vw->vw_Tx;
- LINE *line = tx->tx_Lines + start->pos_Line;
- int yord = ((start->pos_Line - vw->vw_StartLine) * vw->vw_FontY)
- + vw->vw_YStartPix;
- end->pos_Col++;
- end->pos_Line++;
- if(!gapBlank)
- {
- CLR_RECT(vw,
- vw->vw_XStartPix + ((start->pos_Col - vw->vw_StartCol)
- * vw->vw_FontX),
- yord,
- vw->vw_XStartPix + ((end->pos_Col - vw->vw_StartCol)
- * vw->vw_FontX),
- ((end->pos_Line - vw->vw_StartLine)
- * vw->vw_FontY) + vw->vw_YStartPix);
- }
- if(end->pos_Line > tx->tx_NumLines)
- end->pos_Line = tx->tx_NumLines;
- while(end->pos_Line > start->pos_Line)
- {
- pentopos(vw, start->pos_Col - vw->vw_StartCol,
- start->pos_Line - vw->vw_StartLine);
- drawlinelength(vw, line, start->pos_Line, start->pos_Col,
- end->pos_Col + 1);
- line++;
- start->pos_Line++;
- }
- }
-
-
- /*
- * Copies from srcLine to bottom of screen to dstLine
- */
- void
- cutpastelines(VW *vw, long srcLine, long dstLine)
- {
- int xsrc, ysrc, xwth, yht, xdst, ydst;
- long lastline = vw->vw_StartLine + vw->vw_MaxY;
- /* number of lines which are not blank. */
- int lastdisp = (vw->vw_Tx->tx_NumLines - vw->vw_Tx->tx_ModDelta)
- - vw->vw_LastDisplayOrigin.pos_Line;
- if(srcLine < vw->vw_StartLine)
- srcLine = vw->vw_StartLine;
- if(dstLine < vw->vw_StartLine)
- dstLine = vw->vw_StartLine;
- if(srcLine >= lastline)
- srcLine = lastline - 1;
- if(dstLine >= lastline)
- return;
- if(srcLine == dstLine)
- return;
- xsrc = vw->vw_XStartPix;
- xwth = vw->vw_XWidthPix;
- xdst = vw->vw_XStartPix;
- ysrc = vw->vw_YStartPix + ((srcLine - vw->vw_StartLine) * vw->vw_FontY);
- ydst = vw->vw_YStartPix + ((dstLine - vw->vw_StartLine) * vw->vw_FontY);
- if(ysrc > ydst)
- {
- if(lastdisp >= vw->vw_MaxY)
- yht = vw->vw_YEndPix - ysrc;
- else
- {
- yht = (vw->vw_YStartPix + (lastdisp * vw->vw_FontY)) - ydst;
- if((yht + ydst) > vw->vw_YEndPix)
- yht = vw->vw_YEndPix - ydst;
- }
- }
- else
- {
- if(lastdisp >= vw->vw_MaxY)
- yht = vw->vw_YEndPix - ydst;
- else
- {
- yht = (vw->vw_YStartPix + (lastdisp * vw->vw_FontY)) - ysrc;
- if((yht + ysrc) > vw->vw_YEndPix)
- yht = vw->vw_YEndPix - ysrc;
- }
- }
- if((xwth > 0) && (yht > 0))
- COPY_AREA(vw, xsrc, ysrc, xwth, yht, xdst, ydst);
- if(ysrc > ydst)
- {
- /* stuff we weren't able to blit. */
- long firstline = lastline - (srcLine - dstLine);
- if(firstline < vw->vw_Tx->tx_NumLines)
- redrawlinesclr(vw, firstline, lastline);
- else
- CLR_RECT(vw, vw->vw_XStartPix, vw->vw_YStartPix + (vw->vw_FontY * (firstline - vw->vw_StartLine)),
- vw->vw_XEndPix, vw->vw_YEndPix);
- }
- }
-