AUSAM/source/ded/map.c

#include "ded.h"
#include "char.h"

/* to allow for differing screen sizes, ded must
 * allocate its own store
 */
char *curr_break 0, *curr_lim 0;

char *my_alloc(size)
 { register char *res, *new;

    if ( (new = curr_break+size) > curr_lim)
     { res = (size-(curr_lim-curr_break)+1024) & (~ 1023);
	if ( (new = sbrk(res)) == -1)
	  editerror("no more room (my_alloc)");
	else
	 { curr_lim = new+res;
	    if (curr_break==0) curr_break = new;
	    new = curr_break+size;
	 }
     }

    res = curr_break;
    curr_break = new;
    return(res);
 }

char **newscreen()
 { register char **res, *map;
    register int row;
    int width;

    res = my_alloc(nrows*2);
    width = (ncols+2) & (~ 1);
    if (dbug('o'))
      editerror("nrows is %d, ncols is %d, width is %d", nrows, ncols, width);
    map = my_alloc(nrows*width);

    /* set pointers in map */
    for (row=0; row<nrows; row++)
     res[row] = map+row*width;

    return(res);
 }

setupscreen()
 { clearscreen();
    refreshscreen();
 }

refreshscreen()
 { register int row;
    char lbuf[ENOUGH];

    /* display file contents */
    for (row=0; row<=LASTINROW; row++)
     { getfline(topl+row,lbuf);
	redraw(row,0,lbuf);
     }

    showedit();
    ttyflush();
}

clearscreen()
 { register int row, col;
    register char *rm;
    int width;

    clear();

    /* store spaces in screen map */
    if (rowmap==0)
      editerror("screen map not yet set up (clearscreen)");

    for (row=0; row<=FOOTROW; row++)
     { rm = rowmap[row];
	for (col=0; col<=ncols-1; col++)
	  *rm++ = c_SPACE;
     }
 }

char *copyrow(srow,scol,buf)
int srow, scol;
char *buf;
 { register char *pmap, *pbuf;
    register int count;

    pmap = rowmap[srow]+scol;
    if ( (pbuf = buf)==0 ) editerror("row not set up (copyrow)");
    count = lastcol(srow)-scol+1;

    while (count-- > 0)
      *pbuf++ = *pmap++;

    *pbuf = 0;
 }

/* insert a row AFTER screen row srow.
 * this must be done so that the data on screen moves
 * (in order that the user can see that the insert really has occurred)
 * and also so that the minimum number of characters are transferred
 */
ins_row(srow,buffer,pos)
int srow;
char *buffer;
struct CURSOR *pos;
 { register int i, reg_row;
    struct CURSOR tmp;

    reg_row = srow;

    if (reg_row<=2 ||
	reg_row<LASTINROW &&
	    (reg_row<firstrow() ||
	     charsin(0,reg_row)>charsin(reg_row+1,LASTINROW)) )
    /* top rows stay on screen - just pull lower lines
     * down one
     */
     { saverow(LASTINROW);

	if (ttytype==hazeltine)
	 { saveedit(); forcedown(reg_row+1); showedit(); }
	else
	  for (i=LASTINROW; i>reg_row+1; i--)
	    redraw(i,0,rowmap[i-1]);

	if (pos->row>reg_row && pos->row<LASTINROW) pos->row++;
     }
    else
    /* make room by pushing top row off screen  - there
     * are two ways of doing this */
     { if ( ttytype==hazeltine ||
	    charsin(reg_row+1,FOOTROW)<charsin(0,reg_row) )
	/* roll up screen, and pull lower lines down one */
	 { saveedit();
	    rollup(1);
	    if (ttytype==hazeltine)
	     forcedown(reg_row);
	    else
	    { showedit();
	      for (i=LASTINROW; i>reg_row; i--)
		redraw(i,0,rowmap[i-1]);
	    }
	 }
	else
	/* push top rows up one position */
	 { saverow(0);
	    inc_topl();
	    for (i=0; i<reg_row; i++)
	      redraw(i,0,rowmap[i+1]);
	 }

	if (pos->row<=reg_row && pos->row>0) pos->row--;
	reg_row--;
     }

    shuffile(topl+reg_row+1,1);
    redraw(reg_row+1,0,buffer);
 }

/* delete a screen row - as above this should usually
 * involve moving the picture somewhat
 */
del_row(srow,pos)
int srow;
struct CURSOR *pos;
 { register int i, reg_row;
    char linebuf[ENOUGH];
    struct CURSOR tmp;

    reg_row=srow;

    if (topl!=0 &&
	(reg_row<=firstrow() ?
	   !emptyline(topl-1) ||
	    (reg_row>lastrow() && topl+LASTINROW>=maxl) :
	   topl+LASTINROW>=maxl ||
	    (reg_row>=lastrow() ?
	       emptyline(topl+LASTINROW+1) :
	       (ttytype==itt &&
		charsin(0,reg_row-1)<charsin(reg_row+1,LASTINROW))) ))
    /* pull the top lines down */
     { for (i=reg_row; i>=0; i--)
	 { getline(topl+i-1,linebuf);
	    redraw(i,0,linebuf);
	 }
	if (pos->row<=reg_row && pos->row<LASTINROW) pos->row++;
	shuffile(topl+reg_row+1,-1);
	topl--;
     }
    else
    /* pull the bottom lines up */
     { while (topl+LASTINROW>=maxl) inc_maxl();

	if (ttytype==hazeltine)
	 { saveedit(); forceup(reg_row);
	   getline(topl+LASTINROW+1, linebuf);
	   redraw(LASTINROW, 0, linebuf);
	   showedit();
	 }
	else
	  for (i=reg_row; i<=LASTINROW; i++)
	   { getline(topl+i+1,linebuf);
	     redraw(i,0,linebuf);
	   }

	if (pos->row>reg_row && pos->row>0) pos->row--;
	shuffile(topl+reg_row+1,-1);
     }
 }

/* contents of editrow - saved by saveedit etc. */
char erow[ENOUGH];

/* two functions to help when rolling about the screen */
saveedit()
 { copyrow(EDITROW,0,erow); }

showedit()
 { redraw(EDITROW,0,erow); ttyflush(); }


clear()
{	switch (ttytype)
	{
	case itt:	ttyout(c_CLEAR);
			break;
	case hazeltine: ttyout(c_LEADIN);
			ttyout('\034');
			break;
	case VC404:	ttyout('\030');
			ttyout('\014'); /* for screen clear delay */
			break;
	case T1061:	ttyout('\014');
			break;
	default:	 editerror("tty type not set up (clear)");
	}

    real_c.row = real_c.col = 0;
 }

/* looks at the screen row srow and the file line fline.
 * If they are different, it rewrites the line.
 */
int tmp_changed false;

saverow(srow)
int srow;
 { char sstr[ENOUGH], fstr[ENOUGH];

    copyrow(srow, 0, sstr); /* essential to convert it into a string */
    getfline(topl+srow,fstr);

    if (!streq(sstr, fstr))
     { addline(topl+srow, sstr); tmp_changed = true; }
 }

savescreen()
 { int i;

    for (i=0; i<=LASTINROW; i++)
     saverow(i);

    saveedit();
 }

/* procedures to help in hardware-scrolling terminals */
forcedown(row)
int row;
 { register int reg_row;
   struct CURSOR tmp;

   store_c(&virt_c, &tmp);
   virt_c.row = reg_row = row;
   if (ttytype==hazeltine)
    { fixpos(); ttyout(c_LEADIN); ttyout(04032); /* confuse ttyout */
      real_c.col = 0;
    }
   else editerror("forcedown on non-hazeltine");

   store_c(&tmp, &virt_c);
   shufscreen(reg_row, FOOTROW, 1);
 }

forceup(row)
int row;
 { register int reg_row;
   struct CURSOR tmp;

   store_c(&virt_c, &tmp);
   virt_c.row = reg_row = row;
   if (ttytype==hazeltine)
    { fixpos(); ttyout(c_LEADIN); ttyout(023);
      real_c.col = 0;
    }
   else editerror("forceup on non-hazeltine");

   store_c(&tmp, &virt_c);
   shufscreen(reg_row, FOOTROW, -1);
 }