home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
wp_dtp
/
xdme1821.lha
/
XDME
/
redraw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-25
|
27KB
|
1,089 lines
/******************************************************************************
MODUL
redraw.c
DESCRIPTION
This contains all functionality that is needed to refresh
part of the display.
******************************************************************************/
/**************************************
Includes
**************************************/
#include <defs.h>
#define MYDEBUG 0
#include "debug.h"
/**************************************
Globale Variable
**************************************/
Prototype void redraw_block (BOOL, Line, Column, Line, Column);
/**************************************
Interne Defines & Strukturen
**************************************/
#define SWAP(a,b) (void)((a)^=(b),(b)^=(a),(a)^=(b))
#define MIN(a,b) ((a) <= (b) ? (a) : (b))
#define MAX(a,b) ((a) >= (b) ? (a) : (b))
#define CLIP(l,m,h) (((m) < (l)) ? (l) : (((m) > (h)) ? (h) : (m)))
#define BF_LINESWAP 1L
#define BF_COLUMNSWAP 2L
/**************************************
Interne Variable
**************************************/
/**************************************
Interne Prototypes
**************************************/
/*****************************************************************************
NAME
redraw_block
PARAMETER
BOOL force; Shall I care for the difference between
the fields in the ActualBlock or just
redraw the block in the limits specified
in the parameters ?
Line start_line;
Column start_column;
Line end_line;
Column end_column;
RETURN
void
DESCRIPTION
This function draws a block according to the type. The parameter
force has a special meaning. If it is TRUE, you force a redraw.
The block is newly drawn. In this case, the lines specify the
clip-rect of text that is to be redrawn.
If it is FALSE, the positions specify the new start- and
end-positions for the block. The routine gurantees that the
start-position of the block is before the end-position after the
call. It is valid to call the routine with -1/-1 for one position.
In this case, you just want to move one position without touching
the other. The routine also takes care for flipping the block.
NOTES
- If force is FALSE, you MUST NOT change more than one position at
a time. You can exchange both and change one, though.
- The block is only redrawn, if the actual editor is the editor
with the block and drawing in that editor is ok !
- After the call, the new positions are written into the ActualBlock-
struct if force is FALSE. It is guranteed, that the start-position
is before the end-position, no matter how they were when the routine
was called.
******************************************************************************/
/* We note all areas that need to be drawn/erased in this structure.
(startline<=endline && startcol<=endcol) == TRUE !
*/
#define NO_INTERSECT 0
#define TOP_CLIP 0x0001
#define BOTTOM_CLIP 0x0010
#define LEFT_CLIP 0x0100
#define RIGHT_CLIP 0x1000
#define TOP_INTERSECT 0x0002
#define BOTTOM_INTERSECT 0x0020
#define LEFT_INTERSECT 0x0200
#define RIGHT_INTERSECT 0x2000
#define IS_EMPTY 0
#define NOT_EMPTY 1
#define MEMORY_ERROR 2
struct RefreshRegion
{
MLIST list; /* linked list of regions */
};
struct rect
{
Line sl; /* line where the region starts in */
Column sc; /* and the column */
Line el; /* same for end-pos */
Column ec;
};
struct Region
{
MNODE node; /* for linking into a list */
struct rect rect;
};
struct RefreshRegion * new_region (void);
void dispose_region (struct RefreshRegion *);
USHORT do_clip (struct Region *, struct rect *);
int and_rect_region (struct RefreshRegion *, struct rect *);
BOOL add_rect (struct RefreshRegion *, struct rect *);
int clear_rect_region (struct RefreshRegion *, struct rect *);
void refresh_region (RP *, struct RefreshRegion *, int);
void print_region (struct RefreshRegion *);
void print_region (struct RefreshRegion * region)
{
struct Region * ptr;
int t;
for (t=0,ptr=GetHead(®ion->list); ptr; ptr=GetSucc(&ptr->node),t++)
{
D(bug("Node %ld: (%ld/%ld) - (%ld/%ld)\n",
t, ptr->rect.sl, ptr->rect.sc, ptr->rect.el, ptr->rect.ec));
}
} /* print_region */
struct RefreshRegion * new_region (void)
{
struct RefreshRegion * new;
if (new = AllocMem (sizeof(struct RefreshRegion), 0))
{
NewList ((struct List *)&new->list);
}
return (new);
} /* new_region */
void dispose_region (struct RefreshRegion * region)
{
struct Region * ptr, * next;
for (ptr=GetHead(®ion->list); ptr; ptr=next)
{
next = GetSucc (&ptr->node);
FreeMem (ptr, sizeof(struct Region));
}
FreeMem (region, sizeof(struct RefreshRegion));
} /* dispose_region */
USHORT do_clip (struct Region * region, struct rect * rect)
{
USHORT test = NO_INTERSECT;
if (!( (region->rect.sl > rect->el) || (region->rect.el < rect->sl) ||
(region->rect.sc > rect->ec) || (region->rect.ec < rect->sc) ) )
{
if (region->rect.sl < rect->sl)
test |= TOP_CLIP;
if (region->rect.el > rect->el)
test |= BOTTOM_CLIP;
if (region->rect.sc < rect->sc)
test |= LEFT_CLIP;
if (region->rect.ec > rect->ec)
test |= RIGHT_CLIP;
if (region->rect.sl <= rect->el)
test |= TOP_INTERSECT;
if (region->rect.el >= rect->sl)
test |= BOTTOM_INTERSECT;
if (region->rect.sc <= rect->ec)
test |= LEFT_INTERSECT;
if (region->rect.ec >= rect->sc)
test |= RIGHT_INTERSECT;
}
/* D(bug("clip %04lx\n", test)); */
return (test);
} /* do_clip */
/* clip regions */
int and_rect_region (struct RefreshRegion * region, struct rect * rect)
{
struct Region * ptr, * next;
USHORT status;
for (ptr=GetHead(®ion->list); ptr; ptr=next)
{
USHORT common;
next = GetSucc (&ptr->node);
if ((common = do_clip (ptr, rect)) != NO_INTERSECT)
{
if (common & TOP_CLIP)
ptr->rect.sl = rect->sl;
if (common & BOTTOM_CLIP)
ptr->rect.el = rect->el;
if (common & LEFT_CLIP)
ptr->rect.sc = rect->sc;
if (common & RIGHT_CLIP)
ptr->rect.ec = rect->ec;
}
else
{
/* if they do not intersect, remove the Region */
Remove ((struct Node *)&ptr->node);
FreeMem (ptr, sizeof(struct Region));
}
}
if (!GetHead(region))
status = IS_EMPTY;
else
status = NOT_EMPTY;
return (status);
} /* and_rect_region */
/* make a copy of a region */
struct RefreshRegion * copy_region (struct RefreshRegion * region)
{
struct Region * ptr;
struct RefreshRegion * copy;
if (copy = new_region ())
{
for (ptr=GetHead(®ion->list); ptr; ptr=GetSucc(&ptr->node))
{
if (!(add_rect (copy, &ptr->rect)) )
{
dispose_region (copy);
return (NULL);
}
}
}
return (copy);
} /* copy_region */
/* make erase all common areas between two regions */
void clip_region (struct RefreshRegion * region, struct RefreshRegion * clip)
{
struct Region * ptr;
for (ptr=GetHead(&clip->list); ptr; ptr=GetSucc(&ptr->node))
{
clear_rect_region (region, &ptr->rect);
}
} /* clip_region */
/* create a new Region and add it to the RefreshRegion. This routine
must not be called with a rect that intersects with any of the
Regions that are already in the RefreshRegion ! */
BOOL add_rect (struct RefreshRegion * region, struct rect * rect)
{
struct Region * new;
if (new = AllocMem (sizeof(struct Region), 0))
{
movmem (rect, &new->rect, sizeof (struct rect));
/* AddHead because we might be editing the list right now :-) */
AddHead ((struct List *)®ion->list, (struct Node *)&new->node);
}
return ((new != NULL));
} /* add_rect */
/* adjust regions that none intersects with the rect anymore */
int clear_rect_region (struct RefreshRegion * region, struct rect * rect)
{
struct Region * ptr, * next;
USHORT status;
for (ptr=GetHead(®ion->list); ptr; ptr=next)
{
USHORT common;
struct rect new_rect;
next = GetSucc (&ptr->node);
/* do something only if we have an intersection */
if ((common = do_clip (ptr, rect)) != NO_INTERSECT)
{
/* if both intersect, we make sure we don't have any areas left
that are in two Regions */
if (common & TOP_CLIP)
{
/* if we have a TOP_CLIP, there must be some new Region
above. */
new_rect.sl = ptr->rect.sl;
new_rect.el = rect->sl - 1; /* this is the intersection */
new_rect.sc = ptr->rect.sc;
new_rect.ec = ptr->rect.ec;
/* is this a valid rect anyway ?? */
if (new_rect.sl <= new_rect.el)
{
if (!add_rect (region, &new_rect))
return (MEMORY_ERROR);
else
ptr->rect.sl = rect->sl; /* new topline */
} /* valid rect ? */
} /* type of intersect */
if (common & BOTTOM_CLIP)
{
/* if we have a BOTTOM_CLIP, there must be some new Region
below. */
new_rect.sl = rect->el + 1; /* clipping */
new_rect.el = ptr->rect.el;
new_rect.sc = ptr->rect.sc;
new_rect.ec = ptr->rect.ec;
/* is this a valid rect anyway ?? */
if (new_rect.sl <= new_rect.el)
{
if (!add_rect (region, &new_rect))
return (MEMORY_ERROR);
else
ptr->rect.el = rect->el;
} /* valid rect ? */
} /* type of intersect */
if (common & LEFT_CLIP)
{
/* if we have a LEFT_CLIP, there must be some new Region
below. */
new_rect.sl = ptr->rect.sl;
new_rect.el = ptr->rect.el;
new_rect.sc = ptr->rect.sc;
new_rect.ec = rect->sc - 1; /* clipping */
/* is this a valid rect anyway ?? */
if (new_rect.sc <= new_rect.ec)
{
if (!add_rect (region, &new_rect))
return (MEMORY_ERROR);
/* we do not need any ELSE here since RIGHT_CLIP
doesn't care about the left border. */
} /* valid rect ? */
} /* type of intersect */
if (common & RIGHT_CLIP)
{
/* if we have a RIGHT_CLIP, there must be some new Region
below. */
new_rect.sl = ptr->rect.sl;
new_rect.el = ptr->rect.el;
new_rect.sc = rect->ec + 1; /* clipping */
new_rect.ec = ptr->rect.ec;
/* is this a valid rect anyway ?? */
if (new_rect.sc <= new_rect.ec)
{
if (!add_rect (region, &new_rect))
return (MEMORY_ERROR);
} /* valid rect ? */
} /* type of intersect */
/* remove old area */
Remove ((struct Node *)&ptr->node);
FreeMem (ptr, sizeof (struct Region));
} /* intersection */
}
if (!GetHead(region))
status = IS_EMPTY;
else
status = NOT_EMPTY;
return (status);
} /* clear_rect_region */
int AddDrawEvent (struct RefreshRegion * region, Line sl, Column sc,
Line el, Column ec)
{
struct rect new_rect;
if (el < sl || ec < sc) /* don't add invalid blocks */
return (TRUE);
new_rect.sl = sl;
new_rect.el = el;
new_rect.sc = sc;
new_rect.ec = ec;
return (add_rect (region, &new_rect));
} /* AddDrawEvent */
/*****************************************************************************
NAME
redraw_block
PARAMETER
BOOL force;
Line start_line;
Column start_column;
Line end_line;
Column end_column;
RESULT
RETURN
void
DESCRIPTION
Draws part of the text (force = TRUE) or adjust the block
accurding to the new coordinates (force = FALSE).
NOTES
BUGS
EXAMPLES
SEE ALSO
INTERNALS
HISTORY
03. Jan 1978 ada created
******************************************************************************/
void redraw_block (BOOL force, Line start_line, Column start_column,
Line end_line, Column end_column)
{
RP * rp;
struct RefreshRegion * old, /* the old block that has to be erased */
* new, /* the new block that has to be drawn */
* update, /* region where we have to redraw the
text */
* copy; /* and a copy of old for removing common
areas. */
struct rect new_rect;
D(bug("----> redraw_block\nforce:%ld start:%3ld/%3ld end:%3ld/%3ld\n",
force,
start_line+1, start_column+1,
end_line+1, end_column+1 ));
old = new_region ();
new = new_region ();
update = new_region ();
if (!old || !new || !update) /* out of memory */
return;
if (block_ok () && ActualBlock.ep == Ep) /* do this only if there really is a block */
{
if (ActualBlock.start_line > ActualBlock.end_line)
{
SWAP (ActualBlock.start_line, ActualBlock.end_line);
ActualBlock.flags ^= BF_LINESWAP;
if ( ActualBlock.type == BT_NORMAL ||
ActualBlock.start_column > ActualBlock.end_column)
{
SWAP (ActualBlock.start_column, ActualBlock.end_column);
ActualBlock.flags ^= BF_COLUMNSWAP;
}
} else if ((ActualBlock.type == BT_VERTICAL ||
(ActualBlock.start_line == ActualBlock.end_line &&
ActualBlock.type == BT_NORMAL)) &&
ActualBlock.start_column > ActualBlock.end_column)
{
SWAP (ActualBlock.start_column, ActualBlock.end_column);
ActualBlock.flags ^= BF_COLUMNSWAP;
}
}
else /* no matter what we have to do: it cannot be something that
has to do with a block. So we just redraw the current area. */
{
update_only: /* jump here if we are sure there is no block to draw */
D(bug("Update only\n"));
if (end_line < start_line)
SWAP(start_line,end_line);
if (end_column < start_column)
SWAP(start_column,end_column);
AddDrawEvent (update, start_line, start_column,
end_line, end_column);
goto draw; /* I really don't like goto but I also don't
want to indent all that crap below :-) */
}
/* find drawing positions. After this if, the redraw-struct is filled with
all information to draw the new situation */
if (force)
{
/* here, we must make sure, that start <= end ! */
if (start_line > end_line)
{
SWAP (start_line, end_line);
if (ActualBlock.type == BT_NORMAL)
SWAP (start_column, end_column);
else if (ActualBlock.type == BT_VERTICAL &&
start_column > end_column)
SWAP (start_column, end_column);
} else if (((start_line == end_line && ActualBlock.type == BT_NORMAL) ||
ActualBlock.type == BT_VERTICAL) &&
start_column > end_column)
SWAP (start_column, end_column);
/* clip end-line */
if (end_line >= Ep->lines)
end_line = Ep->lines-1;
if (globalflags.Comlinemode)
{
text_redraw_cmdline ();
return;
} else {
/* clip all areas against the draw-area */
new_rect.sl = start_line;
new_rect.el = end_line;
new_rect.sc = start_column;
new_rect.ec = end_column;
switch (ActualBlock.type)
{
case BT_LINE:
{
AddDrawEvent (update, start_line, start_column,
ActualBlock.start_line - 1, end_column);
AddDrawEvent (new,
ActualBlock.start_line, start_column,
ActualBlock.end_line, end_column);
AddDrawEvent (update, ActualBlock.end_line + 1, start_column,
end_line, end_column);
}
break;
case BT_VERTICAL:
{
/* this is something like this:
+---------------------+
| (A) |
+-----+-------+-------+
| (B) | (C) | (D) |
+-----+-------+-------+
| (E) |
+---------------------+
*/
AddDrawEvent (update, start_line, start_column,
ActualBlock.start_line - 1, end_column);
AddDrawEvent (update,
ActualBlock.start_line, start_column,
ActualBlock.end_line, ActualBlock.start_column - 1);
AddDrawEvent (new,
ActualBlock.start_line, ActualBlock.start_column,
ActualBlock.end_line, ActualBlock.end_column);
AddDrawEvent (update,
ActualBlock.start_line, ActualBlock.end_column + 1,
ActualBlock.end_line, end_column);
AddDrawEvent (update, ActualBlock.end_line + 1, start_column,
end_line, end_column);
}
break;
case BT_NORMAL:
{
Column scol, ecol;
int start_len, end_len;
/* The situation is like this :
+-----------------------+
| (A) | (A) The area above the block
| +------------+ (B) The area in the line where
| (B) | (C) | the block starts BEFORE the
+----------+------------+ block
| (D) | (C) The area inside the block in
+-------------+---------+ the line where the block
| (E) | (F) | begins
+-------------+ | (D) the main body
| (G) | (E) the rest of the block in the
+-----------------------+ last line
(F) the rest of this line
(G) anything below the block
*/
start_len = LINELEN(Ep,ActualBlock.start_line);
if (start_len <= ActualBlock.start_column)
scol = start_len;
else
scol = ActualBlock.start_column;
AddDrawEvent (update, start_line, start_column,
ActualBlock.start_line-1, end_column);
end_len = LINELEN(Ep,ActualBlock.end_line);
if (end_len <= ActualBlock.end_column)
ecol = end_column;
else
ecol = ActualBlock.end_column;
if (ActualBlock.start_line != ActualBlock.end_line)
{
/* (B) (C) */
AddDrawEvent (update,
ActualBlock.start_line, start_column,
ActualBlock.start_line, scol-1);
AddDrawEvent (new,
ActualBlock.start_line, scol,
ActualBlock.start_line, end_column);
/* (D) */
AddDrawEvent (new,
ActualBlock.start_line+1, start_column,
ActualBlock.end_line-1, end_column);
/* (E) (F) */
AddDrawEvent (new,
ActualBlock.end_line, start_column,
ActualBlock.end_line, ecol);
AddDrawEvent (update,
ActualBlock.end_line, ecol+1,
ActualBlock.end_line, end_column);
} else
{
AddDrawEvent (update,
ActualBlock.start_line, start_column,
ActualBlock.start_line, scol-1);
AddDrawEvent (new,
ActualBlock.start_line, scol,
ActualBlock.start_line, ecol);
AddDrawEvent (update,
ActualBlock.start_line, ecol+1,
ActualBlock.start_line, end_column);
}
/* (G) */
AddDrawEvent (update, ActualBlock.end_line+1, start_column,
end_line, end_column);
if (start_len <= ActualBlock.start_column)
start_column = start_len;
if (end_len <= ActualBlock.end_column)
end_column = end_len;
}
break;
} /* switch */
and_rect_region (update, &new_rect);
and_rect_region (new, &new_rect);
/* D(bug("Update :\n")); print_region (update);
D(bug("new :\n")); print_region (new); */
}
} else /* force == FALSE */
{
Line top, bottom;
Column left, right;
D(bug("Flags %ld\n", ActualBlock.flags));
top = ActualBlock.start_line;
bottom = ActualBlock.end_line;
left = ActualBlock.start_column;
right = ActualBlock.end_column;
if (ActualBlock.flags & BF_LINESWAP)
SWAP (top, bottom);
if (ActualBlock.flags & BF_COLUMNSWAP)
SWAP (left, right);
if (start_line == -1) /* find correct start-pos */
{
start_line = top;
start_column = left;
} else if (end_line == -1) /* find correct end-pos */
{
end_line = bottom;
end_column = right;
}
D(bug("Drawing: start:%3ld/%3ld end:%3ld/%3ld\n",
start_line+1,
start_column+1,
end_line+1,
end_column+1
));
D(bug("(old) start:%3ld/%3ld end:%3ld/%3ld\n",
ActualBlock.start_line+1,
ActualBlock.start_column+1,
ActualBlock.end_line+1,
ActualBlock.end_column+1
));
left = Ep->topcolumn;
top = Ep->topline;
right = left + Columns - 1;
bottom = top + Lines - 1;
/* all these routines work basically the same way. First,
we copy the start- and end-pos. Then we make sure that
the start-pos is before to end-pos. Now we check if the new
block is visible.
We have 2 versions of every positions, one normal and one
clipped against the window-borders.
The sl/el/sc/ec-coords are the sorted new positions, csl/cel/...
are the clipped version, the old positions are in ActualBlock.xx
and the clipped version in osl/sel/...
*/
switch (ActualBlock.type)
{
case BT_LINE:
{
Line sl, el;
sl = start_line;
el = end_line;
if (el < sl)
SWAP(sl,el);
AddDrawEvent (old, ActualBlock.start_line, left,
ActualBlock.end_line, right);
AddDrawEvent (new, sl, left, el, right);
}
break;
case BT_NORMAL:
{
Line sl, el;
Column sc, ec, scol, ecol;
int slen, elen;
USHORT flags;
sl = start_line;
el = end_line;
sc = start_column;
ec = end_column;
flags = 0;
if (el < sl)
{
SWAP (sl, el);
SWAP (sc, ec);
flags |= BF_LINESWAP | BF_COLUMNSWAP;
} else if (sl == el && ec < sc)
{
SWAP (sc, ec);
flags |= BF_COLUMNSWAP;
}
slen = LINELEN(Ep,ActualBlock.start_line);
if (slen <= ActualBlock.start_column)
scol = slen;
else
scol = ActualBlock.start_column;
elen = LINELEN(Ep,ActualBlock.end_line);
if (elen <= ActualBlock.end_column)
ecol = right;
else
ecol = ActualBlock.end_column;
if (ActualBlock.start_line != ActualBlock.end_line)
{
AddDrawEvent (old,
ActualBlock.start_line, scol,
ActualBlock.start_line, right);
AddDrawEvent (old,
ActualBlock.start_line+1, left,
ActualBlock.end_line-1, right);
AddDrawEvent (old,
ActualBlock.end_line, left,
ActualBlock.end_line, ecol);
}
else
AddDrawEvent (old,
ActualBlock.start_line, scol,
ActualBlock.start_line, ecol);
slen = LINELEN(Ep,sl);
if (slen <= sc)
scol = slen;
else
scol = sc;
elen = LINELEN(Ep,el);
if (elen <= ec)
ecol = right;
else
ecol = ec;
if (sl != el)
{
AddDrawEvent (new, sl, scol, sl, right);
AddDrawEvent (new, sl+1, left, el-1, right);
AddDrawEvent (new, el, left, el, ecol);
}
else
AddDrawEvent (new, sl, scol, sl, ecol);
if (slen <= sc)
sc = slen;
if (elen <= ec)
ec = elen;
if (flags & BF_COLUMNSWAP)
SWAP(sc,ec);
start_column = sc;
end_column = ec;
}
break;
case BT_VERTICAL:
{
Line sl, el;
Column sc, ec;
/* create sorted coords for new block */
sl = start_line;
el = end_line;
sc = start_column;
ec = end_column;
if (el < sl) SWAP(sl,el);
if (ec < sc) SWAP(sc,ec);
AddDrawEvent (old,
ActualBlock.start_line, ActualBlock.start_column,
ActualBlock.end_line, ActualBlock.end_column);
AddDrawEvent (new, sl, sc, el, ec);
/* that's all folx ! */
}
break;
} /* switch (ActualBlock.type) */
copy = copy_region (old); /* make a copy of the old block */
clip_region (old, new); /* clear all common areas in old */
clip_region (new, copy); /* clear all common areas in new */
dispose_region (copy); /* free copy */
/* undo swap drawing-positions accordingly to blockflags */
/* if (ActualBlock.flags & BF_LINESWAP)
SWAP (start_line, end_line);
if (ActualBlock.flags & BF_COLUMNSWAP)
SWAP (start_column, end_column); */
D(bug("copy: start:%3ld/%3ld end:%3ld/%3ld\n",
start_line+1,
start_column+1,
end_line+1,
end_column+1
));
/* copy new positions */
ActualBlock.start_line = start_line;
ActualBlock.start_column = start_column;
ActualBlock.end_line = end_line;
ActualBlock.end_column = end_column;
ActualBlock.flags &= ~(BF_LINESWAP | BF_COLUMNSWAP);
/* reset flags */
if (ActualBlock.start_line > ActualBlock.end_line)
{
SWAP (ActualBlock.start_line, ActualBlock.end_line);
ActualBlock.flags |= BF_LINESWAP;
if (ActualBlock.type == BT_NORMAL)
{
SWAP (ActualBlock.start_column, ActualBlock.end_column);
ActualBlock.flags |= BF_COLUMNSWAP;
} else if (ActualBlock.type == BT_VERTICAL)
{
if (ActualBlock.start_column > ActualBlock.end_column)
{
SWAP (ActualBlock.start_column, ActualBlock.end_column);
ActualBlock.flags |= BF_COLUMNSWAP;
}
}
} else if (ActualBlock.start_column > ActualBlock.end_column &&
( (ActualBlock.type == BT_VERTICAL) ||
(ActualBlock.type == BT_NORMAL &&
ActualBlock.start_line == ActualBlock.end_line)
)
)
{
SWAP (ActualBlock.start_column, ActualBlock.end_column);
ActualBlock.flags |= BF_COLUMNSWAP;
}
/* D(bug("NEW: start:%3ld/%3ld end:%3ld/%3ld\n",
ActualBlock.start_line+1,
ActualBlock.start_column+1,
ActualBlock.end_line+1,
ActualBlock.end_column+1
)); */
D(bug("Flags %ld\n", ActualBlock.flags));
} /* if (force) */
draw: /* jump here is all DrawEvents are correctly initialized */
/* Are we allowed to draw ? */
if (!Nsu && !Ep->iconmode)
{
/* init rastport */
rp = Ep->win->RPort;
/* clip the update-region */
new_rect.sl = Ep->topline;
new_rect.el = new_rect.sl + Lines - 1;
new_rect.sc = Ep->topcolumn;
new_rect.ec = new_rect.sc + Columns - 1;
/* make sure we don't get below the last line */
if (new_rect.el >= Ep->lines)
new_rect.el = Ep->lines - 1;
/* clip away everything that exceeds the displayable area */
and_rect_region (update, &new_rect);
and_rect_region (old, &new_rect);
and_rect_region (new, &new_rect);
refresh_region (rp, update, 2);
refresh_region (rp, old, 0);
refresh_region (rp, new, 1);
dispose_region (update);
dispose_region (old);
dispose_region (new);
}
} /* redraw_block */
void refresh_region (RP * rp, struct RefreshRegion * region, int mode)
{
struct Region * ptr;
int t;
Line start_line, end_line;
Column start_column, end_column;
t=0;
for (ptr=GetHead(®ion->list); ptr; ptr=GetSucc(&ptr->node))
{
start_line = ptr->rect.sl;
end_line = ptr->rect.el;
start_column = ptr->rect.sc;
end_column = ptr->rect.ec + 1;
D(bug("Draw %ld: %ld (%2ld,%2ld) - (%2ld/%2ld)\n", t ++,
mode, start_line+1, start_column+1, end_line+1, end_column+1));
if (start_line > end_line ||
start_column >= end_column)
{
D(bug("ERROR !!!!\n"));
continue;
}
if (mode != 2)
{
if (mode == 1)
SetAPen (rp, BLOCK_BPEN);
else
SetAPen (rp, TEXT_BPEN);
SetWrMsk (rp, BLOCK_MASK);
SetDrMd (rp, JAM2);
RectFill (rp, COL(start_column - Ep->topcolumn),
ROW(start_line - Ep->topline),
COL(end_column - Ep->topcolumn)-1,
ROW(end_line + 1 - Ep->topline)-1 );
}
for ( ; start_line <= end_line; start_line ++)
redraw_textlineseg (start_line, start_column, end_column);
}
} /* refresh_region */
/******************************************************************************
***** ENDE redraw.c
******************************************************************************/