home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
zip
/
gnu
/
gemlib27.lzh
/
GEMLIB27
/
WINSUBR.C
< prev
Wrap
C/C++ Source or Header
|
1993-07-30
|
29KB
|
1,271 lines
/* subroutines for multi-window terminal emulation
*/
#ifdef __GNUC__
# include <gemfast.h>
# include <aesbind.h>
# include <vdibind.h>
#else
# include <obdefs.h>
# include <gemdefs.h>
#endif
#include <osbind.h>
#include <stdio.h>
#include "wind.h"
#include "windefs.h"
extern int handle;
/* variables used by various routines
*/
long dummy; /* dummy return variable */
extern int outwind, outport; /* window selection */
extern int scr_x, scr_y; /* size of the screen */
extern int scr_w, scr_h;
extern int fast; /* flag for fast open/close */
extern int overstrike;
extern int sliders; /* flag for sliders on new windows */
extern int titles; /* flag for title bars on new windows */
int tmp; /* temporary for anything... */
extern char alert[300]; /* used for alerts */
extern FNT *curfont; /* current font */
extern MFDB screen_mf; /* screen descriptor */
extern int mouse; /* for mouse on/off */
extern int audibell; /* What happens on BEL? */
extern int visibell;
extern int toponbel;
struct wi_str w[MAX_WIND];
/* the program code...
*/
char *getmem(size)
register long size;
{
char *got;
got = (char *) Malloc(size);
#ifdef DEBUG
printf("alloc returned %lx of %ld size\n", got, size);
#endif
if (got == NULL)
{
sprintf(alert, "[1][Could not get %ld bytes][Ok]", size);
form_alert(1, alert);
} else
{
bzero(got, size);
}
return got;
}
#ifndef __GNUC__
bzero(ptr, size)
register char *ptr;
register long size;
{
while (size--)
*ptr++ = 0;
}
#endif
/* find_port maps from window handles to UW port identifiers
*/
find_port(wnd)
{
return w[wnd].port;
}
/* find_wind maps from port ids to window handles
*/
find_wind(port)
{
int i;
for (i=1; i<MAX_WIND; i++)
if (w[i].port == port) return i;
return 0;
}
/* w_open opens a window with the supplied name and port and returns a port
* number. If port was zero, a free port is chosen.
*/
w_open(port, name, xsiz, ysiz)
char *name;
{
register struct wi_str *wp;
int wdes;
int i, cnt, wtyp;
int tmp_x, tmp_y, tmp_w, tmp_h;
if (port && find_wind(port)) return port; /* this window is already open */
if (!port)
{
for (i=1; i<MAX_WIND; i++)
{
if (!find_wind(i))
{
port = i; /* a free port */
break;
}
}
}
wtyp = (sliders ? WI_WITHSLD : 0) | (titles ? WI_NOSLD : 0);
wind_calc(0, wtyp, 0, 0, curfont->inc_x*xsiz+2*X0,
curfont->inc_y*ysiz+2*Y0, &dummy, &dummy, &tmp_w, &tmp_h);
if (tmp_w>scr_w)
tmp_w = scr_w; /* full size <= screen size */
tmp_x = 10*(port-1);
if (tmp_h>scr_h)
tmp_h = scr_h;
tmp_y = scr_y+16*(port-1);
wdes = wind_create(wtyp, tmp_x, tmp_y, tmp_w,
tmp_h);
if (wdes < 0)
{
form_alert(1, "[1][Sorry, GEM has|no more windows|for us...][Ok]");
return 0;
}
wp = &w[wdes];
wp->wi_w = X0*2 + curfont->inc_x*xsiz;
wp->wi_h = Y0*2 + curfont->inc_y*ysiz;
wp->port = port;
if (!fast)
graf_growbox(0, 0, 20, 10, tmp_x, tmp_y, tmp_w, tmp_h);
wind_open(wdes, tmp_x, tmp_y, tmp_w, tmp_h);
wind_get(wdes, WF_WORKXYWH, &wp->x, &wp->y, &wp->w, &wp->h);
wp->fulled = 0;
wp->used = 1;
wp->x_off = 0;
wp->y_off = 0;
wp->px_off = 0;
wp->py_off = 0;
wp->m_off = wp->x & 15;
wp->cur_x = X0;
wp->cur_y = Y0;
wp->top_y = Y0;
wp->font = curfont;
wp->x_chrs = xsiz;
wp->y_chrs = ysiz;
wp->wi_mf.wpix = 2*X0 + xsiz*curfont->inc_x;
wp->wi_mf.hpix = 2*Y0 + ysiz*curfont->inc_y;
#ifdef KOPY
wp->wi_mf.wwords = ((wp->wi_mf.wpix>>5) +1) << 1;
#else
wp->wi_mf.wwords = (wp->wi_mf.wpix>>4) +1;
#endif
wp->wi_mf.ptr = getmem(((long)wp->wi_mf.hpix+wp->font->inc_y*MAXSCROLLED)
*wp->wi_mf.wwords*2);
wp->wi_mf.format = 0;
wp->wi_mf.planes = 1;
wp->ptr_status = LOG_NONE;
wp->wi_style = wtyp;
w_rename(wdes, name);
strcpy(wp->wi_fpath, ".\\*.*");
wp->top_age = 1;
for (cnt = 1; cnt < MAX_WIND; cnt++)
if (w[cnt].port != 0)
w[cnt].top_age++;
setvslide(wdes);
sethslide(wdes);
return wp->port;
}
/* w_closei removes a window but does not release its storage.
* This is used if the window contents must be saved for later use.
*/
w_closei(wdes)
{
int xx, yy, ww, hh;
register struct wi_str *wp = &w[wdes];
if (!wp->used) return;
if (wp->wi_lfd)
fclose(wp->wi_lfd);
wind_get(wdes, WF_CURRXYWH, &xx, &yy, &ww, &hh);
wind_close(wdes);
if (!fast)
graf_shrinkbox(0, 0, 20, 10, xx, yy, ww, hh);
wind_delete(wdes);
}
/* w_close removes a window. Most work is done by GEM, although w_close
* does some cleanup functions, too.
*/
w_close(wdes)
{
register struct wi_str *wp = &w[wdes];
if (!wp->used) return;
w_closei(wdes);
Mfree(wp->wi_mf.ptr);
bzero(wp, (long)sizeof (struct wi_str));
}
/* w_resize resizes an existing window.
*/
w_resize(wdes, xsiz, ysiz)
{
register struct wi_str *wp1 = &w[wdes];
struct wi_str *wp2;
struct wi_str ws;
static int c[8];
int port, wind, i;
if (!wp1->used) return;
ws = *wp1;
port = find_port(wdes);
w_closei(wdes);
bzero(wp1, (long)sizeof (struct wi_str));
port = w_open(port, "", xsiz, ysiz);
wind = find_wind(port);
wp2 = &w[wind];
c[0] = ws.m_off;
c[1] = ws.top_y + max(0, ws.wi_mf.hpix - wp2->wi_mf.hpix);
c[2] = c[0] + min(ws.wi_mf.wpix, wp2->wi_mf.wpix);
c[3] = c[1] + min(ws.wi_mf.hpix, wp2->wi_mf.hpix);
c[4] = wp2->m_off;
c[5] = wp2->top_y;
c[6] = c[4] + min(ws.wi_mf.wpix, wp2->wi_mf.wpix);
c[7] = c[5] + min(ws.wi_mf.hpix, wp2->wi_mf.hpix);
/* copy screen */
vro_cpyfm(handle, FM_COPY, c, &ws.wi_mf, &wp2->wi_mf);
/* copy parameters */
wp2->inverse = ws.inverse;
wp2->insmode = ws.insmode;
if (wp2->font != ws.font)
{
wp2->cur_x = X0;
wp2->cur_y = (wp2->y_chrs - 1) * wp2->font->inc_y + Y0;
}
else
{
wp2->cur_x = (wp2->x_chrs - 1) * wp2->font->inc_x + X0;
if (ws.cur_x < wp2->cur_x)
wp2->cur_x = ws.cur_x;
wp2->cur_y = max(0, ws.cur_y - c[1]) + Y0;
}
wp2->state = ws.state;
for (i=0; i<80; i++) wp2->nuname[i] = ws.nuname[i];
for (i=0; i<80; i++) wp2->wi_fpath[i] = ws.wi_fpath[i];
for (i=0; i<20; i++) wp2->wi_fname[i] = ws.wi_fname[i];
wp2->nuptr = ws.nuptr;
wp2->ptr_status = ws.ptr_status;
wp2->wi_lfd = ws.wi_lfd;
wp2->kerm_act = ws.kerm_act;
w_rename(wind, ws.name);
Mfree(ws.wi_mf.ptr);
return port;
}
/* w_rename changes the title bar of a window
*/
w_rename(wdes, name)
char *name;
{
register struct wi_str *wp = &w[wdes];
if (name)
strcpy(wp->name, name);
if (wp->wi_style & NAME)
{
sprintf(wp->dname, " %s%s %s ", (wp->ptr_status != LOG_NONE)? "\275": "",
wp->wi_lfd? "\237": "", wp->name);
wind_set(wdes, WF_NAME, wp->dname + (wp->dname[1] == ' '), 0, 0);
}
}
/* w_redraw redraws part of the screen from window contents.
* The coordinates are screen relative.
*/
w_redraw(wdes, logic, xx, yy, ww, hh)
{
static int c[8];
static GRECT t1, t2;
register struct wi_str *wp = &w[wdes];
if (xx+ww > scr_w)
ww = scr_w - xx;
if (yy+hh > scr_h+scr_y)
hh = scr_h+scr_y - yy;
t2.g_x = xx; t2.g_y = yy;
t2.g_w = ww; t2.g_h = hh;
t1.g_x = wp->x; t1.g_y = wp->y;
t1.g_w = wp->w; t1.g_h = wp->h;
if (!rc_intersect(&t2, &t1)) return; /* nothing to do... */
wind_update(TRUE);
wind_get(wdes, WF_FIRSTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
while (t1.g_w && t1.g_h)
{
if (rc_intersect(&t2, &t1))
{
if (mouse)
{
/* we have to do graphics, so switch the mouse off.
* mouse will be switched on again in main loop.
* this is ugly, but it improves speed a bit...
*/
mouse = 0;
graf_mouse(M_OFF, NULL);
}
#ifdef KCOPY
tfbmr(wp->wi_mf.ptr, t1.g_x - wp->x + wp->x_off + wp->m_off,
t1.g_y - wp->y + wp->y_off + wp->top_y - Y0, wp->wi_mf.wwords >> 1,
screen_mf.ptr, t1.g_x, t1.g_y, screen_mf.wwords >> 1,
t1.g_w, t1.g_h, logic);
#else
c[0] = t1.g_x - wp->x + wp->x_off + wp->m_off;
c[1] = t1.g_y - wp->y + wp->y_off + wp->top_y - Y0;
c[2] = c[0] + t1.g_w - 1;
c[3] = c[1] + t1.g_h - 1;
c[4] = t1.g_x;
c[5] = t1.g_y;
c[6] = c[4] + t1.g_w - 1;
c[7] = c[5] + t1.g_h - 1;
vro_cpyfm(handle, logic, c, &wp->wi_mf, &screen_mf);
#endif
}
wind_get(wdes, WF_NEXTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
}
if (!fast && !mouse)
{
mouse = 1;
graf_mouse(M_ON, NULL);
}
wind_update(FALSE);
}
/* w_update copies a portion of the window to the screen. Coordinates
* are window-relative
*/
w_update(wdes, logic, xx, yy, ww, hh)
{
register struct wi_str *wp = &w[wdes];
w_redraw(wdes, logic, xx + wp->x - wp->x_off,
yy + wp->y - wp->y_off - wp->top_y + Y0, ww, hh);
}
/* w_move sets the window's idea of its own position on the screen
*/
w_move(wdes, xx, yy, ww, hh)
{
register struct wi_str *wp = &w[wdes];
int flag = 0;
int m_w, m_h;
int x1, x2;
int tmp;
wind_calc(1, wp->wi_style, xx, yy, ww, hh, &dummy, &dummy, &m_w, &m_h);
if (tmp = (m_w-2*X0)%wp->font->inc_x)
{
ww -= tmp;
m_w -= tmp;
}
if (tmp = (m_h-2*Y0)%wp->font->inc_y)
{
hh -= tmp;
m_h -= tmp;
}
if (m_w>wp->wi_w) ww = ww-(m_w-wp->wi_w);
if (m_h>wp->wi_h) hh = hh-(m_h-wp->wi_h);
wind_set(wdes, WF_CURRXYWH, xx, yy, ww, hh);
wind_get(wdes, WF_WORKXYWH, &wp->x, &wp->y, &wp->w, &wp->h);
if (wp->x_off+wp->w > wp->wi_w)
{
register int inc_x = wp->font->inc_x;
flag = 1;
wp->x_off = (wp->wi_w - wp->w)/inc_x*inc_x;
}
if (wp->y_off+wp->h > wp->wi_h)
{
register int inc_y = wp->font->inc_y;
flag = 1;
wp->y_off = (wp->wi_h - wp->h)/inc_y*inc_y;
}
x1 = wp->m_off;
x2 = (wp->x - wp->x_off) & 15;
if (x1 != x2)
{
#ifdef KOPY
int top = wp->top_y;
int cnt = wp->wi_mf.wwords >> 1;
cpbmr(wp->wi_mf.ptr, x1, top, cnt, wp->wi_mf.ptr, x2, top, cnt,
wp->wi_w, wp->wi_h);
#else
int c[8];
c[0] = x1;
c[1] = wp->top_y; /* displayed part of memory form starts here */
c[2] = x1 + wp->wi_w - 1;
c[3] = wp->wi_h - 1 + c[1];
c[4] = x2;
c[5] = c[1];
c[6] = x2 + wp->wi_w - 1;
c[7] = c[3];
vro_cpyfm(handle, 3, c, &wp->wi_mf, &wp->wi_mf);
#endif
wp->m_off = x2;
}
if (flag)
w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
setvslide(wdes);
sethslide(wdes);
}
/*
* w_top makes win the top window.
*/
w_top(win)
int win;
{
int cnt;
wind_set(win, WF_TOP, 0, 0, 0, 0);
outport = find_port(win);
outwind = win;
w[outwind].top_age = 0;
for (cnt = 1; cnt < MAX_WIND; cnt++)
if (find_port(cnt)) /* if window is in use */
w[cnt].top_age++;
printer_mark(outwind);
}
/*
* w_bottom finds the bottom window and puts it on top
*/
w_bottom()
{
int i;
int highwin, highcnt;
highcnt = 0;
highwin = 1;
for (i = 1; i < MAX_WIND; i++)
if (w[i].top_age > highcnt)
{
highcnt = w[i].top_age;
highwin = i;
}
if (w[highwin].used)
w_top(highwin);
}
/*
* w_hide puts the top window on the bottom. The new top window is returned.
*/
int w_hide()
{
int i, j;
int newtop, botwin, highcnt;
int oldtop, dum;
wind_get(0, WF_TOP, &oldtop, &dum, &dum, &dum);
if (!oldtop)
return (0);
j = -1;
botwin = 0;
for (j = -1; ; j--)
{
newtop = botwin;
botwin = oldtop;
highcnt = 0;
for (i = 1; i < MAX_WIND; i++)
{
if (w[i].top_age > highcnt)
{
highcnt = w[i].top_age;
botwin = i;
}
}
if (botwin == oldtop)
break;
wind_set(botwin, WF_TOP, 0, 0, 0, 0);
w[botwin].top_age = j; /*top_age less than untouched windows (top_age < 0)*/
}
for (j = 1; j < MAX_WIND; j++)
if (find_port(j)) /* if window is in use */
w[j].top_age += MAX_WIND + 3; /* correct top_age to reflect new order */
return(newtop ? newtop : oldtop);
}
#define TINYX 80
#define TINYY 70
/*
* w_shrink saves current size and location and shrinks to standard tiny size.
* The second from the top non-shrunk window is placed on top.
*/
w_shrink(wdes)
int wdes;
{
register struct wi_str *wp = &w[wdes];
int curw, dummy;
/*
* Don't shrink a window that is currently shrunk
*/
wind_get(wdes, WF_CURRXYWH, &dummy, &dummy, &curw, &dummy);
if (curw <= TINYX)
return;
/*
* Set up fulled and previous size and location window variables to tiny
* size. Then call w_full
*/
wp->fulled = 1;
wp->px = scr_x + scr_w - TINYX + 2;
wp->py = scr_y + (wdes - 1) * (TINYY - 2);
wp->pw = TINYX;
wp->ph = TINYY;
if (wp->py + 10 > scr_y + scr_h)
{
wp->py = wp->py - scr_h + 10;
wp->px = scr_x + scr_w - TINYY * 2;
}
return (w_full(wdes));
}
/* w_full toggles size and location
*/
w_full(wdes)
{
register struct wi_str *wp = &w[wdes];
int x1, y1, w1, h1;
int x2, y2, w2, h2;
int full, topwin;
full = wp->fulled;
if (full) {
x1 = wp->px;
y1 = wp->py;
w1 = wp->pw;
h1 = wp->ph;
} else
wind_get(wdes, WF_FULLXYWH, &x1, &y1, &w1, &h1);
wind_get(wdes, WF_CURRXYWH, &x2, &y2, &w2, &h2);
wp->px = x2;
wp->py = y2;
wp->pw = w2;
wp->ph = h2;
if (!fast)
{
if (w2>=w1 && h2>=h1)
graf_growbox(x2, y2, w2, h2, x1, y1, w1, h1);
else if (w2<=w1 && h2<=h1)
graf_shrinkbox(x1, y1, w1, h1, x2, y2, w2, h2);
}
x2 = wp->x_off;
y2 = wp->y_off;
wp->x_off = wp->px_off;
wp->y_off = wp->py_off;
wp->px_off = x2;
wp->py_off = y2;
w_move(wdes, x1, y1, w1, h1);
w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
wp->fulled = 1;
topwin = wdes;
if (h1 < TINYY + 10)
{
int lowcnt, i;
lowcnt = 32000;
for (i = 1; i< MAX_WIND; i++)
{
if (find_port(i))
{
wind_get(i, WF_CURRXYWH, &x2, &y2, &w2, &h2);
if (w[i].top_age < lowcnt && h2 > TINYY + 10 )
{ /* find top non-tiny open window */
lowcnt = w[i].top_age;
topwin = i;
}
}
}
wind_set(topwin, WF_TOP, 0, 0, 0, 0);
}
return(topwin);
}
w_arrow(wdes, arrow)
{
register struct wi_str *wp = &w[wdes];
int inc_x = wp->font->inc_x;
int inc_y = wp->font->inc_y;
switch (arrow)
{
case 0: /* page up */
wp->y_off -= wp->h/inc_y*inc_y;
goto y_upd;
case 1: /* page down */
wp->y_off += wp->h/inc_y*inc_y;
goto y_upd;
case 2: /* row up */
wp->y_off -= inc_y;
goto y_upd;
case 3: /* row down */
wp->y_off += inc_y;
goto y_upd;
case 4: /* page left */
wp->x_off -= wp->w/inc_x*inc_x;
goto x_upd;
case 5: /* page right */
wp->x_off += wp->w/inc_x*inc_x;
goto x_upd;
case 6: /* column left */
wp->x_off -= inc_x;
goto x_upd;
case 7: /* column right */
wp->x_off += inc_x;
goto x_upd;
}
x_upd:
if (wp->x_off<0) wp->x_off = 0; else
if (wp->x_off+wp->w > wp->wi_w) wp->x_off = (wp->wi_w - wp->w)/inc_x*inc_x;
sethslide(wdes);
goto upd;
y_upd:
if (wp->y_off<0) wp->y_off = 0; else
if (wp->y_off+wp->h > wp->wi_h) wp->y_off = (wp->wi_h - wp->h)/inc_y*inc_y;
setvslide(wdes);
upd:
w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
}
w_slide(wdes, hor, val)
{
register struct wi_str *wp = &w[wdes];
if (hor)
{
tmp = wp->font->inc_x;
wp->x_off = ((long)val*(wp->wi_w-wp->w)/1000)/tmp*tmp;
sethslide(wdes);
} else
{
tmp = wp->font->inc_y;
wp->y_off = ((long)val*(wp->wi_h-wp->h)/1000)/tmp*tmp;
setvslide(wdes);
}
w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
}
sethslide(wdes)
{
register struct wi_str *wp = &w[wdes];
if (wp->wi_style & HSLIDE)
{
tmp = (long)1000*wp->x_off/(wp->wi_w-wp->w);
wind_set(wdes, WF_HSLIDE, tmp, 0, 0, 0);
tmp = (long)1000*wp->w/wp->wi_w;
wind_set(wdes, WF_HSLSIZE, tmp, 0, 0, 0);
}
}
setvslide(wdes)
{
register struct wi_str *wp = &w[wdes];
if (wp->wi_style & VSLIDE)
{
tmp = (long)1000*wp->y_off/(wp->wi_h-wp->h);
wind_set(wdes, WF_VSLIDE, tmp, 0, 0, 0);
tmp = (long)1000*wp->h/wp->wi_h;
wind_set(wdes, WF_VSLSIZE, tmp, 0, 0, 0);
}
}
w_flash(wdes, state)
{
register struct wi_str *wp = &w[wdes];
static int wdes_last;
#ifdef KOPY
int x, y, cnt;
#else
int t[8];
#endif
if (wdes != wdes_last) w_flash(wdes_last, 1);
wdes_last = wdes;
if (!wp->used || wp->curstate == state) return;
if (state == 2)
wp->curstate = !wp->curstate;
else
wp->curstate = state;
#ifdef KOPY
x = wp->cur_x + wp->m_off;
y = wp->cur_y;
cnt = wp->wi_mf.wwords >> 1;
tfbmr(wp->wi_mf.ptr, x, y, cnt, wp->wi_mf.ptr, x, y, cnt,
wp->font->inc_x, wp->font->inc_y, 12);
#else
t[0] = t[4] = wp->cur_x + wp->m_off;
t[1] = t[5] = wp->cur_y;
t[2] = t[6] = t[0]+wp->font->inc_x-1;
t[3] = t[7] = t[1]+wp->font->inc_y-1;
vro_cpyfm(handle, 12, t, &wp->wi_mf, &wp->wi_mf);
#endif
w_update(wdes, FM_COPY, wp->cur_x, wp->cur_y, wp->font->inc_x, wp->font->inc_y);
}
/* w_output prints a string onto the window. The string may
* contain control chars and escape sequences. It ends with \0.
*/
w_output(wdes, ptr)
char *ptr;
{
register struct wi_str *wp = &w[wdes];
static char ch;
static int inc_x, cur_x;
static int state;
static int inc_y, cur_y;
#ifdef KOPY
int x, w, cnt;
#else
static int t[8];
#endif
static int f_x, f_y, f_mod;
static int scrolled; /* Number of scrolling operations delayed */
static int xsiz, ysiz;/* Size in chars of terminal emulation for this window*/
register unsigned char *sptr;
register unsigned long *dptr;
register unsigned long mask;
register int shift;
register unsigned long val;
static int count;
static char * fdata;
static long width;
static char * wimfptr;
static int moffincx;
static char * savptr;
#ifdef DEBUG
printf("entered w_output\n");
#endif
if (!wp->font) return;
state = wp->state;
inc_x = wp->font->inc_x;
inc_y = wp->font->inc_y;
xsiz = wp->x_chrs;
ysiz = wp->y_chrs;
f_x = cur_x = wp->cur_x;
f_y = cur_y = wp->cur_y;
scrolled = wp->top_y/inc_y;
fdata = wp->font->f_data;
width = 2 * wp->wi_mf.wwords;
wimfptr = ((char *) (wp-> wi_mf.ptr)) - 2;
moffincx = wp->m_off + inc_x - 1;
f_mod = 0;
savptr = ptr;
if (wp->curstate) w_flash(wdes, 0);
while (ch = *ptr++)
{
switch (state)
{
case S_NORMAL:
if (ch >= ' ')
{
if (wp->insmode) /* open space for character */
{
#ifdef KOPY
x = cur_x + wp->m_off;
cnt = wp->wi_mf.wwords >> 1;
cpbmr(wp->wi_mf.ptr, x, cur_y, cnt,
wp->wi_mf.ptr, x + inc_x, cur_y, cnt,
(xsiz - 1) * inc_x + wp->m_off - x, inc_y);
#else
t[0] = cur_x + wp->m_off;
t[1] = t[5] = cur_y;
t[2] = (xsiz - 1) * inc_x + wp->m_off - 1;
t[3] = t[7] = cur_y + inc_y - 1;
t[4] = t[0] + inc_x;
t[6] = t[2] + inc_x;
vro_cpyfm(handle, 3, t, &wp->wi_mf, &wp->wi_mf);
#endif
}
/* paint the character */
sptr = fdata+ch*16;
dptr = wimfptr + cur_y*width
+ (((moffincx + cur_x)>>4)<<1);
shift = 15 - ((moffincx + cur_x)&15);
if (overstrike)
mask = -1L;
else
mask = (-1L<<(shift+inc_x)|(1<<shift)-1);
if (wp->inverse)
{
for (count = inc_y; count; count--)
{
val = ((long)(*sptr++))<<shift ^ ~mask;
*dptr = (*dptr&mask)|val;
((char *)dptr) += width;
}
} else
{
for (count = inc_y; count; count--)
{
val = ((long)(*sptr++))<<shift;
*dptr = (*dptr&mask)|val;
((char *)dptr) += width;
}
}
cur_x += inc_x;
f_mod = 1;
if (cur_x > inc_x * xsiz) /* autowrap */
{
cur_y += inc_y;
if (cur_y >= wp->top_y + inc_y * ysiz) {
if (wp->ptr_status & LOG_TOP)
dump_line(wdes, 0);
wp->top_y += inc_y;
++ scrolled;
}
if (! scrolled)
{
w_update(wdes, FM_COPY, f_x, f_y, cur_x-f_x, inc_y);
f_mod = 0;
}
cur_x = X0;
f_x = cur_x;
f_y = cur_y;
}
} else /* not printable character */
{
if (f_mod && !scrolled)
{
if (!wp->insmode)
w_update(wdes, FM_COPY, f_x, f_y, cur_x - f_x, inc_y);
else
w_update(wdes, FM_COPY, f_x, f_y, xsiz * inc_x-f_x, inc_y);
f_mod = 0;
}
switch (ch)
{
case '\007': /* Bell */
if (audibell)
Bconout(2, '\007');
if (toponbel)
/* put this window on top but don't make it the current window.
* should we set a flag so that the first input from the current
* window puts it back on top?
*/
wind_set(wdes, WF_TOP, wdes, 0, 0, 0);
if (visibell)
{
w_redraw(wdes, FM_INVERT, wp->x, wp->y, wp->w, wp->h);
w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
/* Should clear flag to prevent need for next update? */
}
break;
case '\r': /* Carriage Return */
cur_x = X0;
break;
case '\b': /* Backspace */
if (cur_x>X0) cur_x -= inc_x;
break;
case '\n': /* Newline */
cur_y += inc_y;
if (cur_y >= inc_y * ysiz + wp->top_y)
{
if (wp->ptr_status & LOG_TOP)
dump_line(wdes, 0);
wp->top_y += inc_y;
++ scrolled;
}
break;
case '\036': /* Home */
cur_x = X0;
cur_y = wp->top_y;
break;
case '\013': /* Cursor Up */
if (cur_y!=wp->top_y) {
cur_y -= inc_y;
}
break;
case '\014': /* Cursor Right */
if (cur_x < (xsiz - 1) * inc_x) cur_x += inc_x;
break;
case '\032': /* Clear Screen */
wp->inverse = wp->insmode = 0;
cur_x = X0;
cur_y = Y0;
wp->top_y = Y0;
lineerase(wp, 0, ysiz - 1 + MAXSCROLLED);
++ scrolled;
break;
case '\t': /* Tab */
cur_x = ((cur_x/inc_x/8+1))*inc_x*8+X0;
break;
case '\033': /* ESC */
state = S_ESC;
count = 0; /* count is used for insert or delete line */
break;
}
f_x = cur_x;
f_y = cur_y;
}
break;
case S_ESC:
if (ch >= '0' && ch <= '9') {
count = count * 10 + ch - '0';
break;
}
switch (ch)
{
case '*': /* Clear Screen */
f_x = cur_x = X0;
wp->top_y = f_y = cur_y = Y0;
wp->inverse = wp->insmode = 0;
lineerase(wp, 0, ysiz - 1 + MAXSCROLLED);
++ scrolled;
state = S_NORMAL;
break;
case 'Y': /* Clear to End of Screen */
lineerase(wp, cur_y / inc_y + 1, ysiz - 1 + wp->top_y / inc_y);
if (! scrolled)
w_update(wdes, FM_COPY, X0, cur_y + inc_y, xsiz*inc_x, ysiz*inc_y);
/* fall through */
case 'T': /* Clear to End of Line */
#ifdef KOPY
x = cur_x + wp->m_off;
cnt = wp->wi_mf.wwords >> 1;
tfbmr((short *) 0, 0, 0, 0, wp->wi_mf.ptr, x, cur_y, cnt,
X0 + xsiz * inc_x + wp->m_off - x, inc_y, 0);
#else
t[0] = t[4] = cur_x + wp->m_off;
t[1] = t[5] = cur_y;
t[2] = t[6] = X0-1 + xsiz*inc_x +wp->m_off;
t[3] = t[7] = cur_y+inc_y-1;
vro_cpyfm(handle, 0, t, &wp->wi_mf, &wp->wi_mf);
#endif
if (! scrolled)
w_update(wdes, FM_COPY, cur_x, cur_y, xsiz * inc_x - cur_x, inc_y);
state = S_NORMAL;
break;
case 'E': /* Add Line */
case 'R': /* Delete Line */
if (count == 0) {
count = 1;
/* Look ahead for contiguous insert/delete line operations */
while (*ptr == '\033' && ptr[1] == ch) {
ptr +=2;
count ++;
}
}
if (ch == 'E')
scrolldn(wp, cur_y/inc_y, ysiz-(cur_y-wp->top_y+Y0)/inc_y-count, count);
else
scrollup(wp, cur_y / inc_y,
ysiz - (cur_y - wp->top_y + Y0)/inc_y - count, count);
if (! scrolled)
w_update(wdes, FM_COPY, X0, cur_y, xsiz * inc_x,
ysiz * inc_y - cur_y + wp->top_y - Y0);
state = S_NORMAL;
break;
case 'q': /* Insert Mode */
wp->insmode = 1;
state = S_NORMAL;
break;
case 'r': /* End Insert */
wp->insmode = 0;
state = S_NORMAL;
break;
case 'W': /* Delete Character */
#ifdef KOPY
x = cur_x + wp->m_off;
w = X0 + xsiz * inc_x + wp->m_off - x;
cnt = wp->wi_mf.wwords >> 1;
cpbmr(wp->wi_mf.ptr, x + inc_x, cur_y, cnt,
wp->wi_mf.ptr, x, cur_y, cnt, w, inc_y);
tfbmr((short *) 0, 0, 0, 0,
wp->wi_mf.ptr, X0 + (xsiz - 1) * inc_x + wp->m_off, cur_y, cnt,
inc_x, inc_y, 0);
#else
t[0] = cur_x + inc_x + wp->m_off;
t[1] = t[5] = cur_y;
t[2] = X0 - 1 + xsiz * inc_x + wp->m_off;
t[3] = t[7] = cur_y+inc_y - 1;
t[4] = t[0] - inc_x;
t[6] = t[2] - inc_x;
vro_cpyfm(handle, 3, t, &wp->wi_mf, &wp->wi_mf);
t[0] = t[4] = X0 + (xsiz - 1) * inc_x + wp->m_off;
t[2] = t[6] = t[0] + inc_x - 1;
vro_cpyfm(handle, 0, t, &wp->wi_mf, &wp->wi_mf);
#endif
if (! scrolled)
w_update(wdes, FM_COPY, cur_x, cur_y, xsiz * inc_x - (cur_x - X0),
inc_y);
state = S_NORMAL;
break;
case '=': /* Cursor Movement */
state = S_ESC1;
break;
case 'G': /* Switch Inverse/Normal */
state = S_ESC2;
break;
case 'S': /* Change Status Line */
state = S_STATUS;
wp->nuptr = 0;
break;
case '[': /* ascii escape */
state = S_ESCA;
wp->nuptr = 0;
break;
default: /* Unknown escape sequence */
state = S_NORMAL;
}
break;
case S_ESC1: /* get line number */
if (ch < ' ' || ch >= ' ' + ysiz) ch = ' ';
f_y = cur_y = (ch-' ')*inc_y + wp->top_y;
state = S_ESC3;
break;
case S_ESC3: /* get column number */
if (ch < ' ' || ch >= ' ' + xsiz) ch = ' ';
f_x = cur_x = (ch-' ')*inc_x +X0;
state = S_NORMAL;
break;
case S_ESC2: /* get normal/inverse state */
wp->inverse = ch&1;
state = S_NORMAL;
break;
case S_STATUS:
if (ch == '\r')
{
wp->nuname[wp->nuptr] = '\0';
w_rename(wdes, wp->nuname);
state = S_NORMAL;
} else if (wp->nuptr < 72)
{
wp->nuname[wp->nuptr++] = ch;
}
break;
case S_ESCA:
if (ch >= '0' && ch <= '9')
wp->nuptr = ch - '0' + 10 * wp->nuptr;
else if (ch == 't')
{
if (wp-> nuptr == 18)
{
char posstr[20];
sprintf(posstr, "\033[8;%d;%dt", ysiz, xsiz);
proto_out(find_port(wdes), posstr, (int)strlen(posstr));
}
state = S_NORMAL;
}
else state = S_NORMAL;
break;
} /* end switch on state */
if (scrolled >= MAXSCROLLED)
{
if (wp->top_y != Y0) {
scrollup(wp, 0, ysiz, wp->top_y/inc_y);
wp->top_y = Y0;
f_y = cur_y = Y0 + (ysiz - 1) * inc_y;
}
w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
scrolled = 0;
}
} /* end while loop for each character */
if (wp->ptr_status & LOG_BOTOM) {
ptr = savptr;
while ((ch = *ptr++) && (wp->ptr_status & LOG_BOTOM))
#if 0
if (Cprnout(ch) == 0) wp->ptr_status = LOG_NONE;
#else
;
#endif
}
if (wp->wi_lfd) {
while (ch = *savptr++)
putc(ch, wp->wi_lfd);
}
if (scrolled) {
if (scrolled >= MAXSCROLLED) {
if (wp->top_y != Y0) {
scrollup(wp, 0, ysiz, wp->top_y/inc_y);
wp->top_y = Y0;
cur_y = Y0 + (ysiz - 1) * inc_y;
}
}
w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
}
else
if (f_mod)
{
if (!wp->insmode)
w_update(wdes, FM_COPY, f_x, f_y, cur_x - f_x, inc_y);
else
w_update(wdes, FM_COPY, f_x, f_y, xsiz * inc_x-f_x, inc_y);
}
wp->cur_x = cur_x;
wp->cur_y = cur_y;
wp->state = state;
#ifdef DEBUG
printf ("calling w_flash\n");
#endif
w_flash(wdes, 1);
}
lineerase(wp, first, last)
register struct wi_str *wp;
{
register int *p;
long count;
long linespace = wp->wi_mf.wwords*wp->font->inc_y;
p = wp->wi_mf.ptr + first*linespace + Y0*wp->wi_mf.wwords - 1;
count = (last-first+1)*linespace;
while (count > 7)
{
*(((long *)p)++) = 0;
*(((long *)p)++) = 0;
*(((long *)p)++) = 0;
*(((long *)p)++) = 0;
count -= 8;
}
while (--count >= 0)
*++p = 0;
}
scrollup(wp, first, nlines, amount)
register struct wi_str *wp;
{
register int *p1, *p2;
register long count;
int linespace = wp->wi_mf.wwords*wp->font->inc_y;
p1 = wp->wi_mf.ptr + first*linespace + Y0*wp->wi_mf.wwords;
p2 = p1 + linespace * amount;
count = (long)(nlines)*linespace;
while (count > 15)
{
*(((long *)p1)++) = *(((long *)p2)++);
*(((long *)p1)++) = *(((long *)p2)++);
*(((long *)p1)++) = *(((long *)p2)++);
*(((long *)p1)++) = *(((long *)p2)++);
*(((long *)p1)++) = *(((long *)p2)++);
*(((long *)p1)++) = *(((long *)p2)++);
*(((long *)p1)++) = *(((long *)p2)++);
*(((long *)p1)++) = *(((long *)p2)++);
count -= 16;
}
while (--count >= 0)
*(p1++) = *(p2++);
count = linespace * amount;
while (count > 7)
{
*(((long *)p1)++) = 0;
*(((long *)p1)++) = 0;
*(((long *)p1)++) = 0;
*(((long *)p1)++) = 0;
count -= 8;
}
while (--count >= 0)
*(p1++) = 0;
}
scrolldn(wp, first, nlines, amount)
register struct wi_str *wp;
{
register int *p1, *p2;
register long count;
long linespace = wp->wi_mf.wwords*wp->font->inc_y;
p1 = wp->wi_mf.ptr + (nlines+first+amount)*linespace + Y0*wp->wi_mf.wwords;
p2 = p1 - linespace * amount;
count = (long)(nlines)*linespace;
while (count > 15)
{
*--(long *)p1 = *--(long *)p2;
*--(long *)p1 = *--(long *)p2;
*--(long *)p1 = *--(long *)p2;
*--(long *)p1 = *--(long *)p2;
*--(long *)p1 = *--(long *)p2;
*--(long *)p1 = *--(long *)p2;
*--(long *)p1 = *--(long *)p2;
*--(long *)p1 = *--(long *)p2;
count -= 16;
}
while (--count >= 0)
*--p1 = *--p2;
count = linespace * amount;
while (count > 7)
{
*--(long *)p1 = 0L;
*--(long *)p1 = 0L;
*--(long *)p1 = 0L;
*--(long *)p1 = 0L;
count -= 8;
}
while (--count >= 0)
*--p1 = 0;
}