|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T v
Length: 9529 (0x2539)
Types: TextFile
Names: »view.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Life/view.c«
#ifdef SCCS
static char *sccsid = "@(#)view.c 1.5 2/2/85";
static char *cpyrid = "@(#)Copyright (C) 1985 by D Bell";
#endif
#include "life.h"
/*
* Set the scaling factor for the specified object. This also centers
* the view around the current cursor location.
*/
setscale(obj, sf)
register struct object *obj; /* object to set scale of */
register int sf; /* scaling factor */
{
if (sf <= 0) sf = 1;
if (sf > MAXSCALE) sf = MAXSCALE;
obj->o_scale = sf;
obj->o_minrow = obj->o_currow - (rowradius * sf) + (sf / 2);
obj->o_maxrow = obj->o_minrow + (2 * rowradius * sf);
obj->o_mincol = obj->o_curcol - (colradius * sf) + (sf / 2);
obj->o_maxcol = obj->o_mincol + (2 * colradius * sf);
if (obj == curobj) redraw = 1; /* update if object visible */
}
/*
* Perform auto-scaling of the current object. This implies picking a
* scaling factor such that the whole object fits in the screen. The
* scale factor is never decreased. When the scale factor is large,
* convenient ones are picked. Returns the new scale factor.
*/
autoscale()
{
register struct object *obj; /* current object */
register int sf; /* scaling factor */
int minrow, maxrow, mincol, maxcol; /* limits of object */
obj = curobj;
minmax(obj, &minrow, &maxrow, &mincol, &maxcol);
sf = obj->o_scale;
if (mincol > maxcol) return(sf);
while ((sf <= MAXSCALE) &&
((minrow < obj->o_minrow) || (maxrow > obj->o_maxrow) ||
(mincol < obj->o_mincol) || (maxcol > obj->o_maxcol))) {
sf++;
if (sf > 20) sf += (5 - (sf % 5));
if (sf > 50) sf += (10 - (sf % 10));
if (sf > 200) sf += (100 - (sf % 100));
setscale(obj, sf);
}
return(obj->o_scale);
}
/*
* Position the view of the current object to show both the given region and
* the current cursor location. If this is impossible, just the cursor
* location will be positioned.
*/
positionview(minrow, maxrow, mincol, maxcol)
register long minrow, maxrow, mincol, maxcol; /* region to show */
{
register struct object *obj; /* current object */
register int sf; /* current scale factor */
obj = curobj;
sf = obj->o_scale;
if (minrow > obj->o_currow) minrow = obj->o_currow;
if (maxrow < obj->o_currow) maxrow = obj->o_currow;
if (mincol > obj->o_curcol) mincol = obj->o_curcol;
if (maxcol < obj->o_curcol) maxcol = obj->o_curcol;
if ((maxrow - minrow) > (2 * sf * rowradius)) { /* too many rows */
minrow = obj->o_currow;
maxrow = obj->o_currow;
}
if ((maxcol - mincol) > (2 * sf * colradius)) { /* too many columns */
mincol = obj->o_curcol;
maxcol = obj->o_curcol;
}
if (minrow < obj->o_minrow) {
obj->o_minrow = minrow;
obj->o_maxrow = minrow + (rowradius * sf * 2) + sf - 1;
redraw = 1;
}
if (maxrow > obj->o_maxrow) {
obj->o_maxrow = maxrow;
obj->o_minrow = maxrow - (rowradius * sf * 2) + sf - 1;
redraw = 1;
}
if (mincol < obj->o_mincol) {
obj->o_mincol = mincol;
obj->o_maxcol = mincol + (colradius * sf * 2) + sf - 1;
redraw = 1;
}
if (maxcol > obj->o_maxcol) {
obj->o_maxcol = maxcol;
obj->o_mincol = maxcol - (colradius * sf * 2) + sf - 1;
redraw = 1;
}
}
/*
* Show the view around the current window location if the view has changed.
* The update flag indicates that the status line and cursor need updating.
* The redraw flag indicates that the view of the cells also needs updating.
*/
updateview()
{
register struct object *obj; /* current object */
if ((interact | redraw | update) == 0) return;
obj = curobj;
positionview(obj->o_currow,obj->o_currow,obj->o_curcol,obj->o_curcol);
if (obj->o_autoscale) autoscale();
if (redraw) { /* show visible cells */
freqcount = frequency;
dpywindow(1, -1, 0, -1);
if (obj->o_scale <= 1)
viewnormal();
else
viewscale(obj->o_scale);
dpyclrwindow();
}
if (redraw || update) { /* show status and position cursor */
viewstatus();
dpywindow(1, -1, 0, -1);
dpymove((obj->o_currow - obj->o_minrow) / obj->o_scale,
(obj->o_curcol - obj->o_mincol) / obj->o_scale);
dpyupdate();
}
update = 0; /* no more updates until prodded */
redraw = 0;
interact = 0;
}
/*
* Update the status line for the object.
*/
viewstatus()
{
register struct object *obj; /* current object */
dpywindow(0, 0, 0, -1); /* output in top line */
if (errorstring) { /* show error string if present */
dpystr(errorstring);
dpyclrline();
return;
}
obj = curobj;
dpyprintf("Gen:%d cells:%d", obj->o_gen, obj->o_count);
if (obj->o_count > seecount)
dpyprintf("(%du)", obj->o_count - seecount);
if (obj->o_born) dpyprintf(" born:%d", obj->o_born);
if (obj->o_died) dpyprintf(" died:%d", obj->o_died);
if (frequency > 1) dpyprintf(" freq:%d", frequency);
if ((obj->o_scale > 1) || (obj->o_autoscale))
dpyprintf(" %scale:%d",
(obj->o_autoscale ? "autos" : "s") , obj->o_scale);
if (strcmp(rulestring, "3,23")) dpyprintf(" rules:%s", rulestring);
if (obj->o_lock) dpystr(" locked");
if (curinput > inputs) dpyprintf(" cmd-nest:%d", curinput - inputs);
switch (curinput->i_type) {
case INP_TTY: /* reading from terminal */
if (curinput != inputs) dpystr(" tty-wait");
break;
case INP_FILE: /* reading from file */
dpystr(" cmd-file");
break;
case INP_LOOP: /* reading from loop */
if (curinput->i_macro) {
dpyprintf(" macro-define-%c",curinput->i_macro);
break;
}
dpyprintf(" loop%s (curval:%d end:%d)",
curinput->i_first ? "-define" : "",
curinput->i_curval, curinput->i_endval);
break;
case INP_MACRO: /* reading from macro */
dpyprintf(" macro-%c", curinput->i_macro);
break;
}
if (mode == M_INSERT) dpystr(" inserting");
if (mode == M_DELETE) dpystr(" deleting");
if (curobj != mainobject) dpyprintf(" \"%s\"", curobj->o_name);
dpyclrwindow();
}
/* Show the cells around the cursor normally (scale factor of 1) */
viewnormal()
{
register struct row *rp; /* current row */
register struct cell *cp; /* current cell */
register int row; /* current row number */
register int col; /* current column number */
register char *str; /* characters for line */
register char *endstr; /* end of characters for line */
register struct object *obj; /* current object */
obj = curobj;
rp = obj->o_firstrow;
row = obj->o_minrow;
seecount = 0;
while (row > rp->r_row) rp = rp->r_next;
for (; row <= obj->o_maxrow; row++) {
if (row != rp->r_row) { /* blank row */
if (gridchar == ' ') {
dpychar('\n');
continue;
}
str = stringbuf;
for (col = obj->o_mincol; col <= obj->o_maxcol; col++) {
*str++ = gridchar;
}
*str++ = '\n';
dpywrite(stringbuf, str - stringbuf);
continue;
}
str = stringbuf;
endstr = str;
cp = rp->r_firstcell;
col = obj->o_mincol;
while (col > cp->c_col) cp = cp->c_next;
for (; col <= obj->o_maxcol; col++) {
if (col != cp->c_col) { /* blank cell */
*str++ = gridchar;
if (gridchar != ' ') endstr = str;
continue;
}
*str = '#';
if ((cp->c_marks & MARK_SEE) == 0) *str = 'O';
endstr = ++str;
seecount++;
cp = cp->c_next;
}
*endstr++ = '\n';
dpywrite(stringbuf, endstr - stringbuf);
rp = rp->r_next;
}
}
/*
* Show the view around the cursor with an arbitrary scale factor.
* When in this mode, characters from 1 to 9 (or * if 10 or more)
* are used to indicate how many cells are in each n by n square.
*/
viewscale(sf)
register int sf; /* scale factor */
{
register int row; /* current row number */
register int col; /* current column number */
register int sum; /* number of cells in square */
register struct cell *cp; /* current cell structure */
register struct object *obj; /* current object */
struct cell **cpp; /* pointer into cell table */
struct cell **endcpp; /* end of cell table */
struct row *rp; /* row pointer */
char *str; /* buffer pointer */
char *endstr; /* end of buffer */
struct cell *cptab[MAXSCALE]; /* table of rows */
obj = curobj;
row = obj->o_minrow;
col = obj->o_mincol;
endcpp = &cptab[sf];
seecount = 0;
for (rp = curobj->o_firstrow; (rp->r_row < row); rp = rp->r_next) ;
while (row <= obj->o_maxrow) {
/*
* If there is a large gap to the next row number then
* the terminal line is empty.
*/
if (rp->r_row >= (row + sf)) { /* no rows here */
if (gridchar == ' ') {
dpychar('\n');
row += sf;
continue;
}
str = stringbuf;
for (col=obj->o_mincol; col<=obj->o_maxcol; col+=sf) {
*str++ = gridchar;
}
*str++ = '\n';
dpywrite(stringbuf, str - stringbuf);
row += sf;
continue;
}
/*
* Collect the rows to be searched for one terminal line.
* Dummy up empty rows if necessary.
*/
for (cpp = cptab; cpp < endcpp; cpp++) {
*cpp = termcell;
if (rp->r_row > row++) continue;
*cpp = rp->r_firstcell;
rp = rp->r_next;
}
str = stringbuf;
endstr = str;
/*
* Advance along each row to the next range of columns,
* adding cells found to get the result for each square.
*/
for (col = obj->o_mincol; col <= obj->o_maxcol; col += sf) {
sum = 0;
for (cpp = cptab; cpp < endcpp; cpp++) {
cp = *cpp;
while (col > cp->c_col) cp = cp->c_next;
while ((col + sf) >= cp->c_col) {
sum++;
cp = cp->c_next;
}
*cpp = cp;
}
if (sum == 0) { /* no cells in square */
*str++ = gridchar;
if (gridchar != ' ') endstr = str;
continue;
}
*str = '*'; /* show number of cells */
if (sum <= 9) *str = '0' + sum;
endstr = ++str;
seecount += sum;
}
*endstr++ = '\n';
dpywrite(stringbuf, endstr - stringbuf);
}
}