home *** CD-ROM | disk | FTP | other *** search
- /* 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 "mw.h"
- #include "mwdefs.h"
-
- extern int screen_handle;
-
- /* variables used by various routines
- */
-
- extern long dummy; /* dummy return variable */
- extern int sdummy; /* short-sized dummy */
-
- extern int scr_x, scr_y; /* size of the screen */
- extern int scr_w, scr_h;
- extern int fast;
- /* this makes more updates happen in "scrolled" mode with delayed updates */
- extern int jerky_updates;
- extern int mouseflicker; /* for knowing when to turn it on */
- extern int audibell; /* What happens on BEL? */
- extern int visibell;
-
- extern FNT *curfont; /* current font */
- extern WIN_MFDB screen_mf; /* screen descriptor */
- extern int mouse; /* for mouse on/off */
-
- extern struct wi_str *wlist;
-
- extern int ncolors; /* used by ESCb and ESCc */
-
- #if DEBUG
- extern char dbstr[];
- #define DB(x) put_str(x)
- #define DB1(x,y) sprintf(dbstr,x,y), put_str(dbstr)
- #define DB2(x,y,z) sprintf(dbstr,x,y,z), put_str(dbstr)
- #define DB4(s,a,b,c,d) sprintf(dbstr,s,a,b,c,d), put_str(dbstr)
- #define DB6(s,a,b,c,d,e,f) sprintf(dbstr,s,a,b,c,d,e,f), put_str(dbstr)
- #else
- #define DB(x)
- #define DB1(x,y)
- #define DB2(x,y,z)
- #define DB4(s,a,b,c,d)
- #define DB6(s,a,b,c,d,e,f)
- #endif
-
- /* the program code... */
-
- char *getmem(size)
- register long size;
- {
- char *got;
-
- /* this relies on malloc taking size_t, and size_t being long, */
- /* or else not compiling with -mshort */
- got = (char *) malloc(size);
- if (got == NULL) {
- form_alert(1, "[1][Out of memory][ Ok ]");
- }
- else {
- bzero(got, size);
- }
- return got;
- }
-
- /*
- * w_open opens a window with the supplied name. The new window is
- * top, ergo wlist. Puts up an alert & returns -1 on errors.
- */
-
- int
- w_open(name, xpos, ypos, xsiz, ysiz, sliders, titles, usefont)
- char *name;
- int xpos, ypos, xsiz, ysiz;
- int sliders, titles; /* nonzero to get that thing */
- FNT *usefont; /* ptr to font to use */
- {
- register struct wi_str *wp;
- int wdes;
- int wtyp;
- int tmp_w, tmp_h;
-
- wtyp = (sliders ? WI_WITHSLD : 0) | (titles ? WI_WITHTITLE : 0);
- if (ypos < scr_y) ypos = scr_y;
- if (xpos < scr_x) xpos = scr_x;
-
- wind_calc(0, wtyp, 0, 0, usefont->inc_x*xsiz+2*X0,
- usefont->inc_y*ysiz+2*Y0, &sdummy, &sdummy, &tmp_w, &tmp_h);
-
- if (tmp_w>scr_w)
- tmp_w = scr_w; /* full size <= screen size */
-
- if (tmp_h>scr_h)
- tmp_h = scr_h;
-
- wp = (struct wi_str *)getmem(sizeof(struct wi_str));
- if (wp == NULL) {
- return -1;
- }
-
- wp->wi_mf.wpix = 2*X0 + xsiz*usefont->inc_x;
- wp->wi_mf.hpix = 2*Y0 + ysiz*usefont->inc_y;
- wp->wi_mf.wwords = (wp->wi_mf.wpix>>4) +1;
- wp->wi_mf.planes = 1;
- wp->font = usefont;
- wp->fgbg[1] = 0; /* foreground color for vrt_copyfm */
- wp->fgbg[0] = 1; /* background color for vrt_copyfm */
-
- /* allocate a screen image for this window before wind_create */
- wp->wi_mf.ptr = (short *)getmem(
- ((long)wp->wi_mf.hpix + wp->font->inc_y*MAXSCROLLED) *
- wp->wi_mf.wwords*2);
-
- if (wp->wi_mf.ptr == NULL) {
- free(wp);
- return -1;
- }
-
- wdes = wind_create(wtyp, scr_x, scr_y, tmp_w, tmp_h);
- if (wdes < 0) {
- form_alert(1, "[1][Sorry, GEM has|no more windows|for us...][Ok]");
- free(wp->wi_mf.ptr);
- free(wp);
- return -1;
- }
-
- /* install at head of wlist list (which is sorted by window depth) */
- if (wlist == NULL) {
- wp->next = wp->prev = wp;
- }
- else {
- wp->next = wlist;
- wp->prev = wlist->prev;
- wlist->prev->next = wp;
- wlist->prev = wp;
- }
- wlist = wp;
-
- wp->sliders = sliders;
- wp->titles = titles;
- wp->aes_handle = wdes;
- wp->wi_w = X0*2 + usefont->inc_x*xsiz;
- wp->wi_h = Y0*2 + usefont->inc_y*ysiz;
- wp->wi_style = wtyp;
- wp->wi_mainstyle = wtyp;
-
- w_rename(wp, name);
-
- if (!fast)
- graf_growbox(0, 0, 20, 10, xpos, ypos, tmp_w, tmp_h);
- wind_open(wdes, xpos, ypos, tmp_w, tmp_h);
- wind_get(wdes, WF_WORKXYWH, &wp->x, &wp->y, &wp->w, &wp->h);
-
- wp->fulled = 0;
- wp->x_off = 0;
- wp->y_off = 0;
- wp->px_off = 0;
- wp->py_off = 0;
- wp->m_off = wp->x & 15; /* when is this used? */
- wp->cur_x = X0;
- wp->cur_y = Y0;
- wp->top_y = Y0;
- wp->x_chrs = xsiz;
- wp->y_chrs = ysiz;
-
- setvslide(wp);
- sethslide(wp);
-
- return 0;
- }
-
- /*
- * w_closei removes a window but does not release its storage. This is used
- * if the window contents must be saved for later use.
- */
- void
- w_closei(wp)
- struct wi_str *wp;
- {
- int xx, yy, ww, hh;
- int wdes = wp->aes_handle;
-
- 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.
- */
- void
- w_close(wp)
- struct wi_str *wp;
- {
- /* unlink me */
- wp->prev->next = wp->next;
- wp->next->prev = wp->prev;
- if (wp->next == wp) wlist = NULL; /* singleton list */
- else if (wlist == wp) wlist = wp->next;
-
- w_closei(wp);
- free(wp->wi_mf.ptr);
- free(wp);
- }
-
- /* w_resize resizes an existing window. Also lets you pass in the
- * sliders & titles arguments for the newly-sized window.
- *
- * This used to relocate the window; now it copies the xy.
- * This used to change the font in the window; now it doesn't unless
- * chfont == 1.
- */
- int
- w_resize(wp1, xsiz, ysiz, sliders, titles, chfont)
- struct wi_str *wp1;
- int xsiz, ysiz;
- int sliders, titles;
- int chfont; /* flag: when 0 don't change font */
- {
- struct wi_str *wp2;
- static int c[8];
- int tmp_x, tmp_y, tmp_w, tmp_h, wtyp;
- int curstate;
- int retcode;
-
- curstate = wp1->curstate;
- if (curstate) {
- w_flash(wp1,0);
- }
-
- w_closei(wp1); /* close it (closes AES window) */
-
- /*
- * what's happening here is that the overlap of screen images between
- * the old & new sizes gets copied into the new window. This is done by
- * deleting the old window, creating a new one of the new size, and
- * copying the appropriate rectangle of screen image over.
- */
-
- /* unlink me */
- wp1->prev->next = wp1->next;
- wp1->next->prev = wp1->prev;
- if (wp1->next == wp1) wlist = NULL;
- else if (wlist == wp1) wlist = wp1->next;
-
- wtyp = (sliders ? WI_WITHSLD : 0) | (titles ? WI_WITHTITLE : 0);
- wind_calc(0,wtyp,wp1->x,wp1->y,wp1->w,wp1->h,
- &tmp_x, &tmp_y, &tmp_w, &tmp_h);
-
- /* open this window with the same workxy as the previous */
- if (w_open(wp1->name, tmp_x, tmp_y, xsiz, ysiz,
- sliders, titles, (chfont ? curfont : wp1->font))) {
- /* error opening the new copy of the window */
- retcode = -1;
- goto freeold;
- }
-
- wp2 = wlist;
- c[0] = wp1->m_off;
- c[1] = wp1->top_y + max(0, wp1->wi_mf.hpix - wp2->wi_mf.hpix);
- c[2] = c[0] + min(wp1->wi_mf.wpix, wp2->wi_mf.wpix);
- c[3] = c[1] + min(wp1->wi_mf.hpix, wp2->wi_mf.hpix);
- c[4] = wp2->m_off;
- c[5] = wp2->top_y;
- c[6] = c[4] + min(wp1->wi_mf.wpix, wp2->wi_mf.wpix);
- c[7] = c[5] + min(wp1->wi_mf.hpix, wp2->wi_mf.hpix);
-
- /* copy screen */
- vro_cpyfm(screen_handle, FM_COPY, c, &wp1->wi_mf, &wp2->wi_mf);
- /* copy parameters */
- wp2->fgbg[0] = wp1->fgbg[0];
- wp2->fgbg[1] = wp1->fgbg[1];
- wp2->insmode = wp1->insmode;
-
- wp2->fd = wp1->fd;
- wp2->pid = wp1->pid;
-
- if (wtyp != wp1->wi_mainstyle) {
- /* you're changing the style... copy mainstyle from the original */
- wp2->wi_mainstyle = wp1->wi_mainstyle;
- }
-
- /*
- * if font changed, put cursor at bottom left. Else put it at old X
- * offset (or right edge if narrower than that), and I can't figure out
- * the calculation for Y.
- */
- if (wp2->font != wp1->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 (wp1->cur_x < wp2->cur_x)
- wp2->cur_x = wp1->cur_x;
- wp2->cur_y = max(0, wp1->cur_y - c[1]) + Y0;
- }
- wp2->state = wp1->state;
- strcpy(wp2->nuname,wp1->nuname);
-
- wp2->nuptr = wp1->nuptr;
-
- w_flash(wp2,curstate);
- retcode = 0;
-
- freeold:
- free(wp1->wi_mf.ptr);
- free(wp1);
- return retcode; /* old window is GONE if this is -1 */
- }
-
- /* w_rename changes the title bar of a window
- */
- void
- w_rename(wp, name)
- struct wi_str *wp;
- char *name;
- {
- if (name)
- strcpy(wp->name, name);
- if (wp->wi_style & NAME) {
- wind_set(wp->aes_handle, WF_NAME, wp->name, 0, 0);
- }
- }
-
- /* w_redraw redraws part of the screen from window contents.
- * The coordinates are screen relative.
- */
- void
- w_redraw(wp, logic, xx, yy, ww, hh)
- struct wi_str *wp;
- int logic,xx,yy,ww,hh;
- {
- int c[8];
- GRECT t1, t2;
- int wdes = wp->aes_handle;
-
- /* turn vro_cpyfm logic ops into vrt_cpyfm ones */
- if (logic == FM_INVERT) logic = 3;
- else logic = 1;
-
- 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... */
- }
- *(long *)0x003ffffc = 1;
- wind_update(TRUE);
- *(long *)0x003ffffc = 2;
- 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...
- * (If mouseflicker is ON, we'll turn it on again below)
- */
- mouse = 0;
- graf_mouse(M_OFF, NULL);
- }
- 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;
- vrt_cpyfm(screen_handle, logic, c,
- &wp->wi_mf, &screen_mf, wp->fgbg);
- }
- *(long *)0x003ffffc = 3;
- wind_get(wdes, WF_NEXTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
- }
- *(long *)0x003ffffc = 4;
- wind_update(FALSE);
- /* mouse stays hidden -- we'll make it visible next time it moves */
- /* except if mouseflicker is on, in which case we'll do it NOW */
- if (!mouse && mouseflicker) {
- mouse = 1;
- graf_mouse(M_ON,NULL);
- }
- }
-
- /* w_update copies a portion of the window to the screen. Coordinates
- * are window-relative
- */
- void
- w_update(wp, logic, xx, yy, ww, hh)
- struct wi_str *wp;
- int logic, xx,yy,ww,hh;
- {
- w_redraw(wp, 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
- */
-
- void
- w_move(wp, xx, yy, ww, hh)
- struct wi_str *wp;
- int xx, yy, ww, hh;
- {
- int wdes = wp->aes_handle;
- int flag = 0;
- int m_w, m_h;
- int x1, x2;
- int tmp;
- int c[8];
- int inc_x, inc_y;
-
- wind_calc(1, wp->wi_style, xx, yy, ww, hh, &sdummy, &sdummy, &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) {
- 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) {
- 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) {
- 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(screen_handle, FM_COPY, c, &wp->wi_mf, &wp->wi_mf);
- wp->m_off = x2;
- }
- if (flag)
- w_redraw(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
- setvslide(wp);
- sethslide(wp);
- }
-
- /*
- * w_top makes win the top window.
- */
-
- void
- w_top(wp)
- struct wi_str *wp;
- {
- wind_set(wp->aes_handle, WF_TOP, 0, 0, 0, 0);
-
- if (wlist == wp) return; /* already top of list */
-
- /* unlink from its current place */
- wp->next->prev = wp->prev;
- wp->prev->next = wp->next;
-
- /* link into top */
- wp->next = wlist;
- wp->prev = wlist->prev;
- wlist->prev->next = wp;
- wlist->prev = wp;
- wlist = wp;
- }
-
- /*
- * w_bottom finds the bottom window and puts it on top
- */
-
- void
- w_bottom()
- {
- struct wi_str *wp;
-
- if (!wlist || wlist->next == wlist) return;
- for (wp = wlist->next; wp->next != wlist; wp = wp->next) /* do nothing */ ;
- w_top(wp);
- }
-
- /*
- * w_hide puts the top window on the bottom.
- * (a.k.a. "bury")
- */
-
- void
- w_hide()
- {
- struct wi_str *wp, *oldtop;
-
- /* top all the windows, in order, from back to front, except the first. */
- if (!wlist || wlist->next == wlist) return; /* empty or singleton list */
- oldtop = wlist; /* window NOT to top */
- for (wp = wlist->prev; wp != oldtop; wp = wp->prev)
- wind_set(wp->aes_handle,WF_TOP, 0,0,0,0);
-
- /* move the top element from wlist to the end of wlist (easy!) */
- wlist = wlist->next;
- }
-
- #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.
- */
-
- void
- w_shrink(wp)
- struct wi_str *wp;
- {
- int wdes = wp->aes_handle;
- int curx, cury, curw, curh;
- static int slotcount;
-
- /*
- * Don't shrink a window that is currently shrunk
- */
- wind_get(wdes, WF_CURRXYWH, &curx, &cury, &curw, &curh);
- if (curw <= TINYX && cury <= TINYY)
- return;
-
- if (wp->slotno == 0) wp->slotno = ++slotcount;
-
- /*
- * By setting wp->fulled to one and the "previous" size to tiny,
- * we're saying that the current size is the "full" size, and we
- * want to "toggle to" the tiny size.
- */
- wp->fulled = 1;
- wp->px = scr_x + (scr_w - TINYX + 2);
- wp->py = scr_y + ((wp->slotno-1) * (TINYY + 2));
- wp->pw = TINYX;
- wp->ph = TINYY;
-
- /* ensure at least 10 dots of title bar on screen */
- if (wp->py + 10 > scr_y + scr_h) {
- wp->py = wp->py - scr_h + 10;
- wp->px = scr_x + scr_w - TINYY * 2;
- }
- w_full(wp);
-
- /* now top the topmost window which isn't already tiny */
-
- wp = wlist;
- do {
- wdes = wp->aes_handle;
- wind_get(wdes, WF_CURRXYWH, &curx, &cury, &curw, &curh);
- if (curw > TINYX || curh > TINYY) {
- w_full(wp);
- w_top(wp);
- return;
- }
- wp = wp->next;
- } while (wp != wlist);
-
- /* no windows are not shrunk; just leave 'em */
- }
-
- /* w_full toggles size and location between the current size and
- * the "previous" size.
- */
-
- void
- w_full(wp)
- struct wi_str *wp;
- {
- int x1, y1, w1, h1;
- int x2, y2, w2, h2;
- int full;
- int wdes = wp->aes_handle;
-
- full = wp->fulled;
-
- /* if already full, set to "previous" size, else to full size */
- 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)
- graf_growbox(x1, y1, w1, h1, x2, y2, w2, h2);
- else
- 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(wp, x1, y1, w1, h1);
- w_redraw(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
- wp->fulled = 1;
- }
-
- void
- w_arrow(wp, arrow)
- struct wi_str *wp;
- int arrow;
- {
- 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(wp);
- 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(wp);
-
- upd:
- w_redraw(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
- }
-
- void
- w_slide(wp, hor, val)
- struct wi_str *wp;
- int hor, val;
- {
- int tmp;
-
- if (hor) {
- tmp = wp->font->inc_x;
- wp->x_off = ((long)val*(wp->wi_w-wp->w)/1000)/tmp*tmp;
- sethslide(wp);
- }
- else {
- tmp = wp->font->inc_y;
- wp->y_off = ((long)val*(wp->wi_h-wp->h)/1000)/tmp*tmp;
- setvslide(wp);
- }
- w_redraw(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
- }
-
- void
- sethslide(wp)
- struct wi_str *wp;
- {
- int tmp;
- int wdes = wp->aes_handle;
-
- if (wp->wi_style & HSLIDE) {
- if (wp->wi_w == wp->w) tmp = 0;
- else tmp = (long)1000*wp->x_off/(wp->wi_w-wp->w);
- if (tmp != wp->hspos) {
- wind_set(wdes, WF_HSLIDE, tmp, 0, 0, 0);
- wp->hspos = tmp;
- }
-
- tmp = (long)1000*wp->w/wp->wi_w;
- if (tmp != wp->hssiz) {
- wind_set(wdes, WF_HSLSIZE, tmp, 0, 0, 0);
- wp->hssiz = tmp;
- }
- }
- }
-
- void
- setvslide(wp)
- struct wi_str *wp;
- {
- int tmp;
- int wdes = wp->aes_handle;
-
- if (wp->wi_style & VSLIDE) {
- if (wp->wi_h == wp->h) tmp = 0;
- else tmp = (long)1000*wp->y_off/(wp->wi_h-wp->h);
- if (tmp != wp->vspos) {
- wind_set(wdes, WF_VSLIDE, tmp, 0, 0, 0);
- wp->vspos = tmp;
- }
-
- tmp = (long)1000*wp->h/wp->wi_h;
- if (tmp != wp->vssiz) {
- wind_set(wdes, WF_VSLSIZE, tmp, 0, 0, 0);
- wp->vssiz = tmp;
- }
- }
- }
-
- /*
- * flash the cursor in a window; if it's not the last one we flashed,
- * un_flash that one
- */
- void
- w_flash(wp, state)
- struct wi_str *wp;
- int state;
- {
- static struct wi_str *wp_last = NULL;
- int wdes;
- int t[8];
-
- wdes = wp->aes_handle;
- if (wp_last && wp != wp_last) w_flash(wp_last, 1);
- wp_last = wp;
- if (wp->curstate == state) return;
- if (state == 2)
- wp->curstate = !wp->curstate;
- else
- wp->curstate = state;
- 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(screen_handle, FM_INVERT, t, &wp->wi_mf, &wp->wi_mf);
- w_update(wp, 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. Its length is given,
- * so you can even output NULs.
- */
- void
- w_output(wp, ptr, charcount)
- struct wi_str *wp;
- unsigned char *ptr;
- short charcount;
- {
- int w_handle;
- unsigned char ch;
- int inc_x, cur_x;
- int state;
- int inc_y, cur_y;
- int t[8];
- int f_x, f_y, f_mod;
- int scrolled; /* Number of scrolling operations delayed */
- 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;
- int count = 0;
- char * fdata;
- long width;
- char * wimfptr;
- int moffincx;
- unsigned char * savptr;
-
- 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;
-
- /*
- * This sets "hard update" any time the bottom N lines of the buffer are
- * being used -- that is, the overflow below the visible screen. This is
- * seven lines in 8 when you're doing glass-tty scrolling things. This
- * is wrong & slow.
- */
-
- 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;
- w_handle = wp->aes_handle;
-
- if (wp->curstate) {
- w_flash(wp, 0);
- }
-
- while (charcount--) {
- ch = *ptr++;
- switch (state) {
- case S_NORMAL:
- if (ch >= ' ') {
- if (wp->insmode) { /* open space for character */
- 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(screen_handle, FM_COPY, t, &wp->wi_mf, &wp->wi_mf);
- }
-
- /* paint the character (only if it's in range for this font) */
- if (ch < wp->font->nchars) {
- sptr = (unsigned char *)(fdata+ch*16);
- dptr = (unsigned long *)(wimfptr + cur_y*width
- + (((moffincx + cur_x)>>4)<<1));
- shift = 15 - ((moffincx + cur_x)&15);
-
- /* to get overstrike, set mask to -1 */
- 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 */
- if (wp->discard) {
- cur_x -= inc_x; /* back to last char position */
- }
- else {
- cur_y += inc_y;
- if (cur_y >= wp->top_y + inc_y * ysiz) {
- wp->top_y += inc_y;
- ++ scrolled;
- }
- if (! scrolled) {
- w_update(wp, 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 you've modified the screen in this incarnation and you aren't
- * "scrolled", update before any non-printing character. This
- * appears to call w_update for the line you're on, from the X you
- * started from to the X you're at now. I think this is
- * inefficient, but I'm not sure yet. If you're in insert mode,
- * update the whole line from the starting X to the end of the
- * line.
- *
- * I changed this to set "scrolled" if you get here and f_mod is
- * TRUE. That means simple updates on one line (no non-printing
- * chars) don't happen in "scrolled" mode, but anything more
- * complicated does. This is also conditional on jerky_updates,
- * which is the visual result.
- */
- if (f_mod && !scrolled) {
- if (jerky_updates) scrolled = 1;
- else {
- if (wp->insmode)
- w_update(wp, FM_COPY, f_x, f_y, xsiz * inc_x-f_x, inc_y);
- else
- w_update(wp, FM_COPY, f_x, f_y, cur_x - f_x, inc_y);
- f_mod = 0;
- }
- }
- switch (ch) {
- case '\007': /* Bell */
- if (audibell)
- (void)Bconout(2, '\007');
- if (visibell) {
- w_redraw(wp, FM_INVERT, wp->x, wp->y, wp->w, wp->h);
- w_redraw(wp, 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)
- {
- wp->top_y += inc_y;
- ++ 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:
- switch (ch) {
- case 'H': /* Home */
- cur_x = X0;
- cur_y = wp->top_y;
- state = S_NORMAL;
- break;
-
- case 'A': /* Cursor Up */
- case 'I': /* Reverse Index (doesn't reverse scroll yet) */
- if (cur_y!=wp->top_y) {
- cur_y -= inc_y;
- }
- state = S_NORMAL;
- break;
-
- case 'B': /* Cursor Down */
- if ((cur_y + inc_y) < (wp->top_y + (inc_y * ysiz))) {
- cur_y += inc_y;
- }
- state = S_NORMAL;
- break;
-
- case 'C': /* Cursor Right */
- if (cur_x < (xsiz - 1) * inc_x) cur_x += inc_x;
- state = S_NORMAL;
- break;
-
- case 'D': /* Cursor Left */
- if (cur_x > X0) cur_x -= inc_x;
- state = S_NORMAL;
- break;
-
- case 'b': /* ST52 color change (foreground) */
- state = S_FG;
- break;
- case 'c': /* ST52 color change (background) */
- state = S_BG;
- break;
-
- case 'E': /* Clear Screen */
- f_x = cur_x = X0;
- wp->top_y = f_y = cur_y = Y0;
- wp->inverse = 0;
- wp->insmode = 0;
-
- lineerase(wp, 0, ysiz - 1 + MAXSCROLLED);
- ++ scrolled;
- state = S_NORMAL;
- break;
-
- case 'j': /* AKP: save cursor location */
- wp->save_x = cur_x;
- wp->save_y = cur_y;
- state = S_NORMAL;
- break;
- case 'k': /* AKP: restore saved location */
- f_x = cur_x = wp->save_x;
- f_x = cur_y = wp->save_y;
- state = S_NORMAL;
- break;
-
- case 'd': /* Clear from beginning of screen */
- lineerase(wp, 0,cur_y/inc_y); /* clear top to this line */
- ++scrolled;
- /* fall through */
- case 'o': /* Clear from beginning of line */
- t[0] = t[4] = wp->m_off; /* init X */
- t[1] = t[5] = cur_y; /* init Y */
- t[2] = t[6] = cur_x + wp->m_off; /* final X */
- t[3] = t[7] = cur_y+inc_y-1;
- vro_cpyfm(screen_handle, FM_CLEAR, t, &wp->wi_mf, &wp->wi_mf);
- ++scrolled;
- state = S_NORMAL;
- break;
-
- case 'l': /* erase entire line, cursor to left */
- t[0] = t[4] = 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(screen_handle, FM_CLEAR, t, &wp->wi_mf, &wp->wi_mf);
- ++scrolled;
- cur_x = X0;
- state = S_NORMAL;
- break;
-
- case 'e': /* enable cursor */
- wp->cursor_hidden = 0;
- state = S_NORMAL;
- break;
-
- case 'f': /* disable cursor */
- wp->cursor_hidden = 1;
- state = S_NORMAL;
- break;
-
- case 'J': /* Clear to End of Screen */
- lineerase(wp, cur_y / inc_y + 1, ysiz - 1 + wp->top_y / inc_y);
- if (! scrolled)
- w_update(wp, FM_COPY, X0, cur_y + inc_y, xsiz*inc_x, ysiz*inc_y);
- /* fall through */
- case 'K': /* Clear to End of Line */
- 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(screen_handle, FM_CLEAR, t, &wp->wi_mf, &wp->wi_mf);
- if (! scrolled)
- w_update(wp, FM_COPY, cur_x, cur_y, xsiz * inc_x - cur_x, inc_y);
- state = S_NORMAL;
- break;
-
- case 'L': /* Insert Line */
- case 'M': /* 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 == 'L')
- 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(wp, FM_COPY, X0, cur_y, xsiz * inc_x,
- ysiz * inc_y - cur_y + wp->top_y - Y0);
- state = S_NORMAL;
- break;
-
- case 'h': /* Insert Mode */
- wp->insmode = 1;
- state = S_NORMAL;
- break;
-
- case 'i': /* End Insert */
- wp->insmode = 0;
- state = S_NORMAL;
- break;
-
- case 'a': /* Delete Character */
- 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(screen_handle, FM_COPY, 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(screen_handle, FM_CLEAR, t, &wp->wi_mf, &wp->wi_mf);
- if (! scrolled)
- w_update(wp, FM_COPY, cur_x, cur_y, xsiz * inc_x - (cur_x - X0),
- inc_y);
- state = S_NORMAL;
- break;
-
- case 'v': /* clear discard mode */
- wp->discard = 0;
- state = S_NORMAL;
- break;
-
- case 'w': /* set discard mode */
- wp->discard = 1;
- state = S_NORMAL;
- break;
-
- case 'Y': /* Cursor Movement */
- state = S_ESC1;
- break;
-
- case 'p': /* Enter Inverse */
- wp->inverse = 1;
- state = S_NORMAL;
- break;
-
- case 'q': /* Exit Inverse */
- wp->inverse = 0;
- state = S_NORMAL;
- break;
-
- case 'S': /* Change Status Line */
- state = S_STATUS;
- wp->nuptr = 0;
- break;
-
- default: /* Unknown escape sequence */
- state = S_NORMAL;
- break;
- }
- break;
-
- case S_FG:
- wp->fgbg[0] = ch & (ncolors-1);
- state = S_NORMAL;
- scrolled = 1; /* force a hard update */
- break;
-
- case S_BG:
- wp->fgbg[1] = ch & (ncolors-1);
- state = S_NORMAL;
- scrolled = 1; /* force a hard update */
- 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_STATUS:
- if (ch == '\r') {
- wp->nuname[wp->nuptr] = '\0';
- w_rename(wp, wp->nuname);
- state = S_NORMAL;
- }
- else if (wp->nuptr < 72) {
- wp->nuname[wp->nuptr++] = ch;
- }
- 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(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
- scrolled = 0;
- }
- } /* end while loop for each character */
-
- /*
- * "scrolled" is true if you need to do a hard update, where multiple
- * lines may have changed. This used to actually align the virtual
- * screen with the physical screen only when scrolled >= MAXSCROLLED, but
- * this meant that seven lines out of eight got hard updates for every
- * char when typing on a scrolling TTY. So I align them every time.
- */
- if (scrolled) {
- 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(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
- }
- else {
- if (f_mod) {
- if (!wp->insmode)
- w_update(wp, FM_COPY, f_x, f_y, cur_x - f_x, inc_y);
- else
- w_update(wp, 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;
- w_flash(wp, 1);
- }
-
- void
- lineerase(wp, first, last)
- register struct wi_str *wp;
- int first, last;
- {
- register short *p;
- register long *lp;
- 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;
- lp = (long *)p;
- while (count > 7)
- {
- *lp++ = 0;
- *lp++ = 0;
- *lp++ = 0;
- *lp++ = 0;
- count -= 8;
- }
- p = (short *)lp;
- while (--count >= 0)
- *++p = 0;
- }
-
- void
- scrollup(wp, first, nlines, amount)
- register struct wi_str *wp;
- int first, nlines, amount;
- {
- register short *p1, *p2;
- register long *lp1, *lp2;
- 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;
- lp1 = (long *)p1;
- lp2 = (long *)p2;
- while (count > 15)
- {
- *lp1++ = *lp2++;
- *lp1++ = *lp2++;
- *lp1++ = *lp2++;
- *lp1++ = *lp2++;
- *lp1++ = *lp2++;
- *lp1++ = *lp2++;
- *lp1++ = *lp2++;
- *lp1++ = *lp2++;
- count -= 16;
- }
- p1 = (short *)lp1;
- p2 = (short *)lp2;
- while (--count >= 0)
- *(p1++) = *(p2++);
- count = linespace * amount;
- lp1 = (long *)p1;
- while (count > 7)
- {
- *lp1++ = 0;
- *lp1++ = 0;
- *lp1++ = 0;
- *lp1++ = 0;
- count -= 8;
- }
- p1 = (short *)lp1;
- while (--count >= 0)
- *(p1++) = 0;
- }
-
- void
- scrolldn(wp, first, nlines, amount)
- register struct wi_str *wp;
- int first, nlines, amount;
- {
- register short *p1, *p2;
- register long *lp1, *lp2;
- 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;
- lp2 = (long *)p2;
- lp1 = (long *)p1;
- while (count > 15)
- {
- *--lp1 = *--lp2;
- *--lp1 = *--lp2;
- *--lp1 = *--lp2;
- *--lp1 = *--lp2;
- *--lp1 = *--lp2;
- *--lp1 = *--lp2;
- *--lp1 = *--lp2;
- *--lp1 = *--lp2;
- count -= 16;
- }
- p1 = (short *)lp1;
- p2 = (short *)lp2;
- while (--count >= 0)
- *--p1 = *--p2;
- count = linespace * amount;
- lp1 = (long *)p1;
- while (count > 7)
- {
- *--lp1 = 0L;
- *--lp1 = 0L;
- *--lp1 = 0L;
- *--lp1 = 0L;
- count -= 8;
- }
- p1 = (short *)lp1;
- while (--count >= 0)
- *--p1 = 0;
- }
-