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   
C/C++ Source or Header  |  1993-07-30  |  29KB  |  1,271 lines

  1. /* subroutines for multi-window terminal emulation
  2.  */
  3.  
  4. #ifdef __GNUC__
  5. #  include <gemfast.h>
  6. #  include <aesbind.h>
  7. #  include <vdibind.h>
  8. #else
  9. #  include <obdefs.h>
  10. #  include <gemdefs.h>
  11. #endif
  12. #include <osbind.h>
  13. #include <stdio.h>
  14. #include "wind.h"
  15. #include "windefs.h"
  16.  
  17. extern int handle;
  18.  
  19. /* variables used by various routines
  20.  */
  21.  
  22. long dummy;                /* dummy return variable */
  23. extern    int    outwind, outport;    /* window selection */
  24. extern    int    scr_x, scr_y;        /* size of the screen */
  25. extern    int    scr_w, scr_h;
  26. extern    int    fast;            /* flag for fast open/close */
  27. extern    int    overstrike;
  28. extern    int    sliders;        /* flag for sliders on new windows */
  29. extern    int    titles;            /* flag for title bars on new windows */
  30. int    tmp;                /* temporary for anything... */
  31. extern    char    alert[300];        /* used for alerts */
  32. extern    FNT    *curfont;        /* current font */
  33. extern    MFDB    screen_mf;        /* screen descriptor */
  34. extern    int    mouse;            /* for mouse on/off */
  35. extern    int    audibell;        /* What happens on BEL? */
  36. extern    int    visibell;
  37. extern    int    toponbel;
  38.  
  39. struct    wi_str    w[MAX_WIND];
  40.  
  41. /* the program code...
  42.  */
  43.  
  44. char *getmem(size)
  45. register long size;
  46. {
  47.   char *got;
  48.  
  49.   got = (char *) Malloc(size);
  50. #ifdef DEBUG
  51.   printf("alloc returned %lx of %ld size\n", got, size);
  52. #endif
  53.   if (got == NULL)
  54.   {
  55.     sprintf(alert, "[1][Could not get %ld bytes][Ok]", size);
  56.     form_alert(1, alert);
  57.   } else
  58.   {
  59.     bzero(got, size);
  60.   }
  61.   return got;
  62. }
  63.  
  64. #ifndef __GNUC__
  65. bzero(ptr, size)
  66. register char *ptr;
  67. register long size;
  68. {
  69.   while (size--)
  70.     *ptr++ = 0;
  71. }
  72. #endif
  73.  
  74. /* find_port maps from window handles to UW port identifiers
  75.  */
  76.  
  77. find_port(wnd)
  78. {
  79.   return w[wnd].port;
  80. }
  81.  
  82. /* find_wind maps from port ids to window handles
  83.  */
  84.  
  85. find_wind(port)
  86. {
  87. int i;
  88.  
  89.   for (i=1; i<MAX_WIND; i++)
  90.     if (w[i].port == port) return i;
  91.   return 0;
  92. }
  93.  
  94. /* w_open opens a window with the supplied name and port and returns a port
  95.  * number.  If port was zero, a free port is chosen.
  96.  */
  97.  
  98. w_open(port, name, xsiz, ysiz)
  99. char *name;
  100. {
  101.   register struct wi_str *wp;
  102.   int wdes;
  103.   int i, cnt, wtyp;
  104.   int tmp_x, tmp_y, tmp_w, tmp_h;
  105.  
  106.   if (port && find_wind(port)) return port;  /* this window is already open */
  107.   if (!port)
  108.   {
  109.     for (i=1; i<MAX_WIND; i++)
  110.     {
  111.       if (!find_wind(i))
  112.       {
  113.         port = i;        /* a free port */
  114.         break;
  115.       }
  116.     }
  117.   }
  118.  
  119.   wtyp = (sliders ? WI_WITHSLD : 0) | (titles ? WI_NOSLD : 0);
  120.   wind_calc(0, wtyp, 0, 0, curfont->inc_x*xsiz+2*X0,
  121.     curfont->inc_y*ysiz+2*Y0, &dummy, &dummy, &tmp_w, &tmp_h);
  122.   if (tmp_w>scr_w)
  123.     tmp_w = scr_w;    /* full size <= screen size */
  124.   tmp_x = 10*(port-1);
  125.   if (tmp_h>scr_h)
  126.     tmp_h = scr_h;
  127.   tmp_y = scr_y+16*(port-1);
  128.  
  129.   wdes = wind_create(wtyp, tmp_x, tmp_y, tmp_w,
  130.     tmp_h);
  131.   if (wdes < 0)
  132.   {
  133.     form_alert(1, "[1][Sorry, GEM has|no more windows|for us...][Ok]");
  134.     return 0;
  135.   }
  136.   wp = &w[wdes];
  137.   wp->wi_w = X0*2 + curfont->inc_x*xsiz;
  138.   wp->wi_h = Y0*2 + curfont->inc_y*ysiz;
  139.   wp->port = port;
  140.   if (!fast)
  141.     graf_growbox(0, 0, 20, 10, tmp_x, tmp_y, tmp_w, tmp_h);
  142.   wind_open(wdes, tmp_x, tmp_y, tmp_w, tmp_h);
  143.   wind_get(wdes, WF_WORKXYWH, &wp->x, &wp->y, &wp->w, &wp->h);
  144.   wp->fulled = 0;
  145.   wp->used = 1;
  146.   wp->x_off = 0;
  147.   wp->y_off = 0;
  148.   wp->px_off = 0;
  149.   wp->py_off = 0;
  150.   wp->m_off = wp->x & 15;
  151.   wp->cur_x = X0;
  152.   wp->cur_y = Y0;
  153.   wp->top_y = Y0;
  154.   wp->font = curfont;
  155.   wp->x_chrs = xsiz;
  156.   wp->y_chrs = ysiz;
  157.   wp->wi_mf.wpix = 2*X0 + xsiz*curfont->inc_x;
  158.   wp->wi_mf.hpix = 2*Y0 + ysiz*curfont->inc_y;
  159. #ifdef    KOPY
  160.   wp->wi_mf.wwords = ((wp->wi_mf.wpix>>5) +1) << 1;
  161. #else
  162.   wp->wi_mf.wwords = (wp->wi_mf.wpix>>4) +1;
  163. #endif
  164.   wp->wi_mf.ptr = getmem(((long)wp->wi_mf.hpix+wp->font->inc_y*MAXSCROLLED)
  165.                 *wp->wi_mf.wwords*2);
  166.   wp->wi_mf.format = 0;
  167.   wp->wi_mf.planes = 1;
  168.   wp->ptr_status = LOG_NONE;
  169.   wp->wi_style = wtyp;
  170.   w_rename(wdes, name);
  171.   strcpy(wp->wi_fpath, ".\\*.*");
  172.   wp->top_age = 1;
  173.   for (cnt = 1; cnt < MAX_WIND; cnt++)
  174.     if (w[cnt].port != 0)
  175.       w[cnt].top_age++;
  176.   
  177.   setvslide(wdes);
  178.   sethslide(wdes);
  179.   
  180.   return wp->port;
  181. }
  182.  
  183. /* w_closei removes a window but does not release its storage.
  184.  * This is used if the window contents must be saved for later use.
  185.  */
  186.  
  187. w_closei(wdes)
  188. {
  189.   int xx, yy, ww, hh;
  190.   register struct wi_str *wp = &w[wdes];
  191.  
  192.   if (!wp->used) return;
  193.   if (wp->wi_lfd)
  194.     fclose(wp->wi_lfd);
  195.   wind_get(wdes, WF_CURRXYWH, &xx, &yy, &ww, &hh);
  196.   wind_close(wdes);
  197.   if (!fast)
  198.     graf_shrinkbox(0, 0, 20, 10, xx, yy, ww, hh);
  199.   wind_delete(wdes);
  200. }
  201.  
  202. /* w_close removes a window.  Most work is done by GEM, although w_close
  203.  * does some cleanup functions, too.
  204.  */
  205.  
  206. w_close(wdes)
  207. {
  208.   register struct wi_str *wp = &w[wdes];
  209.  
  210.   if (!wp->used) return;
  211.   w_closei(wdes);
  212.   Mfree(wp->wi_mf.ptr);
  213.   bzero(wp, (long)sizeof (struct wi_str));
  214. }
  215.  
  216. /* w_resize resizes an existing window.
  217.  */
  218.  
  219. w_resize(wdes, xsiz, ysiz)
  220. {
  221.   register struct wi_str *wp1 = &w[wdes];
  222.   struct wi_str *wp2;
  223.   struct wi_str ws;
  224.   static int c[8];
  225.   int port, wind, i;
  226.  
  227.   if (!wp1->used) return;
  228.   ws = *wp1;
  229.   port = find_port(wdes);
  230.   w_closei(wdes);
  231.   bzero(wp1, (long)sizeof (struct wi_str));
  232.   port = w_open(port, "", xsiz, ysiz);
  233.   wind = find_wind(port);
  234.   wp2 = &w[wind];
  235.   c[0] = ws.m_off;
  236.   c[1] = ws.top_y + max(0, ws.wi_mf.hpix - wp2->wi_mf.hpix);
  237.   c[2] = c[0] + min(ws.wi_mf.wpix, wp2->wi_mf.wpix);
  238.   c[3] = c[1] + min(ws.wi_mf.hpix, wp2->wi_mf.hpix);
  239.   c[4] = wp2->m_off;
  240.   c[5] = wp2->top_y;
  241.   c[6] = c[4] + min(ws.wi_mf.wpix, wp2->wi_mf.wpix);
  242.   c[7] = c[5] + min(ws.wi_mf.hpix, wp2->wi_mf.hpix);
  243.   /* copy screen */
  244.   vro_cpyfm(handle, FM_COPY, c, &ws.wi_mf, &wp2->wi_mf);
  245.   /* copy parameters */
  246.   wp2->inverse = ws.inverse;
  247.   wp2->insmode = ws.insmode;
  248.   if (wp2->font != ws.font)
  249.   {
  250.     wp2->cur_x = X0;
  251.     wp2->cur_y = (wp2->y_chrs - 1) * wp2->font->inc_y + Y0;
  252.   }
  253.   else
  254.   {
  255.     wp2->cur_x = (wp2->x_chrs - 1) * wp2->font->inc_x + X0;
  256.     if (ws.cur_x < wp2->cur_x)
  257.       wp2->cur_x = ws.cur_x;
  258.     wp2->cur_y = max(0, ws.cur_y - c[1]) + Y0;
  259.   }
  260.   wp2->state = ws.state;
  261.   for (i=0; i<80; i++) wp2->nuname[i] = ws.nuname[i];
  262.   for (i=0; i<80; i++) wp2->wi_fpath[i] = ws.wi_fpath[i];
  263.   for (i=0; i<20; i++) wp2->wi_fname[i] = ws.wi_fname[i];
  264.   wp2->nuptr = ws.nuptr;
  265.   wp2->ptr_status = ws.ptr_status;
  266.   wp2->wi_lfd = ws.wi_lfd;
  267.   wp2->kerm_act = ws.kerm_act;
  268.   w_rename(wind, ws.name);
  269.   
  270.   Mfree(ws.wi_mf.ptr);
  271.   return port;
  272. }
  273.  
  274. /* w_rename changes the title bar of a window
  275.  */
  276.  
  277. w_rename(wdes, name)
  278. char *name;
  279. {
  280.   register struct wi_str *wp = &w[wdes];
  281.  
  282.   if (name)
  283.     strcpy(wp->name, name);
  284.   if (wp->wi_style & NAME)
  285.   {
  286.     sprintf(wp->dname, " %s%s %s ", (wp->ptr_status != LOG_NONE)? "\275": "",
  287.       wp->wi_lfd? "\237": "", wp->name);
  288.     wind_set(wdes, WF_NAME, wp->dname + (wp->dname[1] == ' '), 0, 0);
  289.   }
  290. }
  291.  
  292. /* w_redraw redraws part of the screen from window contents.
  293.  * The coordinates are screen relative.
  294.  */
  295.  
  296. w_redraw(wdes, logic, xx, yy, ww, hh)
  297. {
  298.   static int c[8];
  299.   static GRECT t1, t2;
  300.   register struct wi_str *wp = &w[wdes];
  301.  
  302.   if (xx+ww > scr_w)
  303.     ww = scr_w - xx;
  304.   if (yy+hh > scr_h+scr_y)
  305.     hh = scr_h+scr_y - yy;
  306.   t2.g_x = xx; t2.g_y = yy;
  307.   t2.g_w = ww; t2.g_h = hh;
  308.   t1.g_x = wp->x; t1.g_y = wp->y;
  309.   t1.g_w = wp->w; t1.g_h = wp->h;
  310.   if (!rc_intersect(&t2, &t1)) return;    /* nothing to do... */
  311.   wind_update(TRUE);
  312.   wind_get(wdes, WF_FIRSTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
  313.   while (t1.g_w && t1.g_h)
  314.   {
  315.     if (rc_intersect(&t2, &t1))
  316.     {
  317.       if (mouse)
  318.       {
  319.     /* we have to do graphics, so switch the mouse off.
  320.      * mouse will be switched on again in main loop.
  321.      * this is ugly, but it improves speed a bit...
  322.      */
  323.     mouse = 0;
  324.     graf_mouse(M_OFF, NULL);
  325.       }
  326. #ifdef    KCOPY
  327.       tfbmr(wp->wi_mf.ptr, t1.g_x - wp->x + wp->x_off + wp->m_off,
  328.     t1.g_y - wp->y + wp->y_off + wp->top_y - Y0, wp->wi_mf.wwords >> 1,
  329.     screen_mf.ptr, t1.g_x, t1.g_y, screen_mf.wwords >> 1,
  330.     t1.g_w, t1.g_h, logic);
  331. #else
  332.       c[0] = t1.g_x - wp->x + wp->x_off + wp->m_off;
  333.       c[1] = t1.g_y - wp->y + wp->y_off + wp->top_y - Y0;
  334.       c[2] = c[0] + t1.g_w - 1;
  335.       c[3] = c[1] + t1.g_h - 1;
  336.       c[4] = t1.g_x;
  337.       c[5] = t1.g_y;
  338.       c[6] = c[4] + t1.g_w - 1;
  339.       c[7] = c[5] + t1.g_h - 1;
  340.       vro_cpyfm(handle, logic, c, &wp->wi_mf, &screen_mf);
  341. #endif
  342.     }
  343.     wind_get(wdes, WF_NEXTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
  344.   }
  345.   if (!fast && !mouse)
  346.   {
  347.     mouse = 1;
  348.     graf_mouse(M_ON, NULL);
  349.   }
  350.   wind_update(FALSE);
  351. }
  352.  
  353. /* w_update copies a portion of the window to the screen.  Coordinates
  354.  * are window-relative
  355.  */
  356.  
  357. w_update(wdes, logic, xx, yy, ww, hh)
  358. {
  359.   register struct wi_str *wp = &w[wdes];
  360.  
  361.   w_redraw(wdes, logic, xx + wp->x - wp->x_off, 
  362.           yy + wp->y - wp->y_off - wp->top_y + Y0, ww, hh);
  363. }
  364.  
  365. /* w_move sets the window's idea of its own position on the screen
  366.  */
  367.  
  368. w_move(wdes, xx, yy, ww, hh)
  369. {
  370.   register struct wi_str *wp = &w[wdes];
  371.   int flag = 0;
  372.   int m_w, m_h;
  373.   int x1, x2;
  374.   int tmp;
  375.  
  376.   wind_calc(1, wp->wi_style, xx, yy, ww, hh, &dummy, &dummy, &m_w, &m_h);
  377.   if (tmp = (m_w-2*X0)%wp->font->inc_x)
  378.   {
  379.     ww -= tmp;
  380.     m_w -= tmp;
  381.   }
  382.   if (tmp = (m_h-2*Y0)%wp->font->inc_y)
  383.   {
  384.     hh -= tmp;
  385.     m_h -= tmp;
  386.   }
  387.   if (m_w>wp->wi_w) ww = ww-(m_w-wp->wi_w);
  388.   if (m_h>wp->wi_h) hh = hh-(m_h-wp->wi_h);
  389.   wind_set(wdes, WF_CURRXYWH, xx, yy, ww, hh);
  390.   wind_get(wdes, WF_WORKXYWH, &wp->x, &wp->y, &wp->w, &wp->h);
  391.   if (wp->x_off+wp->w > wp->wi_w)
  392.   {
  393.     register int inc_x = wp->font->inc_x;
  394.     flag = 1;
  395.     wp->x_off = (wp->wi_w - wp->w)/inc_x*inc_x;
  396.   }
  397.   if (wp->y_off+wp->h > wp->wi_h)
  398.   {
  399.     register int inc_y = wp->font->inc_y;
  400.     flag = 1;
  401.     wp->y_off = (wp->wi_h - wp->h)/inc_y*inc_y;
  402.   }
  403.   x1 = wp->m_off;
  404.   x2 = (wp->x - wp->x_off) & 15;
  405.   if (x1 != x2)
  406.   {
  407. #ifdef    KOPY
  408.     int top = wp->top_y;
  409.     int cnt = wp->wi_mf.wwords >> 1;
  410.     cpbmr(wp->wi_mf.ptr, x1, top, cnt, wp->wi_mf.ptr, x2, top, cnt,
  411.       wp->wi_w, wp->wi_h);
  412. #else
  413.   int c[8];
  414.     c[0] = x1;
  415.     c[1] = wp->top_y;    /* displayed part of memory form starts here */
  416.     c[2] = x1 + wp->wi_w - 1;
  417.     c[3] = wp->wi_h - 1 + c[1];
  418.     c[4] = x2;
  419.     c[5] = c[1];
  420.     c[6] = x2 + wp->wi_w - 1;
  421.     c[7] = c[3];
  422.     vro_cpyfm(handle, 3, c, &wp->wi_mf, &wp->wi_mf);
  423. #endif
  424.     wp->m_off = x2;
  425.   }
  426.   if (flag)
  427.     w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  428.   setvslide(wdes);
  429.   sethslide(wdes);
  430. }
  431.  
  432. /*
  433.  * w_top makes win the top window.
  434.  */
  435. w_top(win)
  436. int win;
  437. {
  438.   int cnt;
  439.  
  440.   wind_set(win, WF_TOP, 0, 0, 0, 0);
  441.   outport = find_port(win);
  442.   outwind = win;
  443.   w[outwind].top_age = 0;
  444.   for (cnt = 1; cnt < MAX_WIND; cnt++)
  445.     if (find_port(cnt))    /* if window is in use */
  446.       w[cnt].top_age++;
  447.   printer_mark(outwind);
  448. }
  449.  
  450. /*
  451.  * w_bottom finds the bottom window and puts it on top
  452.  */
  453. w_bottom()
  454. {
  455.   int i;
  456.   int highwin, highcnt;
  457.   
  458.   highcnt = 0;
  459.   highwin = 1;
  460.   for (i = 1; i < MAX_WIND; i++)
  461.     if (w[i].top_age > highcnt)
  462.     {
  463.       highcnt = w[i].top_age;
  464.       highwin = i;
  465.     }
  466.   if (w[highwin].used)
  467.     w_top(highwin);
  468. }
  469.  
  470. /*
  471.  * w_hide puts the top window on the bottom.  The new top window is returned.
  472.  */
  473. int w_hide()
  474. {
  475.   int i, j;
  476.   int newtop, botwin, highcnt;
  477.   int oldtop, dum;
  478.   
  479.   wind_get(0, WF_TOP, &oldtop, &dum, &dum, &dum);
  480.   if (!oldtop)
  481.     return (0);
  482.   j = -1;
  483.   botwin = 0;
  484.   for (j = -1; ; j--)
  485.   {
  486.     newtop = botwin;
  487.     botwin = oldtop;
  488.     highcnt = 0;
  489.     for (i = 1; i < MAX_WIND; i++)
  490.     {
  491.       if (w[i].top_age > highcnt)
  492.       {
  493.         highcnt = w[i].top_age;
  494.         botwin = i;
  495.       }
  496.     }
  497.     if (botwin == oldtop)
  498.       break;
  499.     wind_set(botwin, WF_TOP, 0, 0, 0, 0);
  500.     w[botwin].top_age = j; /*top_age less than untouched windows (top_age < 0)*/
  501.   }
  502.   for (j = 1; j < MAX_WIND; j++)
  503.     if (find_port(j)) /* if window is in use */
  504.       w[j].top_age += MAX_WIND + 3; /* correct top_age to reflect new order */
  505.   return(newtop ? newtop : oldtop);
  506. }
  507.  
  508. #define TINYX 80
  509. #define TINYY 70
  510. /*
  511.  * w_shrink saves current size and location and shrinks to standard tiny size.
  512.  * The second from the top non-shrunk window is placed on top.
  513.  */
  514. w_shrink(wdes)
  515. int wdes;
  516. {
  517.   register struct wi_str *wp = &w[wdes];
  518.   int curw, dummy;
  519.   
  520.   /*
  521.    * Don't shrink a window that is currently shrunk
  522.    */
  523.   wind_get(wdes, WF_CURRXYWH, &dummy, &dummy, &curw, &dummy);
  524.   if (curw <= TINYX)
  525.     return;
  526.  
  527.   /*
  528.    * Set up fulled and previous size and location window variables to tiny
  529.    * size.  Then call w_full
  530.    */
  531.   wp->fulled = 1;
  532.   wp->px = scr_x + scr_w - TINYX + 2;
  533.   wp->py = scr_y + (wdes - 1) * (TINYY - 2);
  534.   wp->pw = TINYX;
  535.   wp->ph = TINYY;
  536.   if (wp->py + 10 > scr_y + scr_h)
  537.   {
  538.     wp->py = wp->py - scr_h + 10;
  539.     wp->px = scr_x + scr_w - TINYY * 2;
  540.   }
  541.   
  542.   return (w_full(wdes));
  543. }
  544.  
  545. /* w_full toggles size and location
  546.  */
  547. w_full(wdes)
  548. {
  549.   register struct wi_str *wp = &w[wdes];
  550.   int x1, y1, w1, h1;
  551.   int x2, y2, w2, h2;
  552.   int full, topwin;
  553.  
  554.   full = wp->fulled;
  555.   if (full) {
  556.     x1 = wp->px;
  557.     y1 = wp->py;
  558.     w1 = wp->pw;
  559.     h1 = wp->ph;
  560.   } else
  561.     wind_get(wdes, WF_FULLXYWH, &x1, &y1, &w1, &h1);
  562.  
  563.   wind_get(wdes, WF_CURRXYWH, &x2, &y2, &w2, &h2);
  564.   wp->px = x2;
  565.   wp->py = y2;
  566.   wp->pw = w2;
  567.   wp->ph = h2;
  568.   if (!fast)
  569.   {
  570.     if (w2>=w1 && h2>=h1)
  571.       graf_growbox(x2, y2, w2, h2, x1, y1, w1, h1);
  572.     else if (w2<=w1 && h2<=h1)
  573.       graf_shrinkbox(x1, y1, w1, h1, x2, y2, w2, h2);
  574.   }
  575.  
  576.   x2 = wp->x_off;
  577.   y2 = wp->y_off;
  578.   wp->x_off = wp->px_off;
  579.   wp->y_off = wp->py_off;
  580.   wp->px_off = x2;
  581.   wp->py_off = y2;
  582.  
  583.   w_move(wdes, x1, y1, w1, h1);
  584.   w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  585.   wp->fulled = 1;
  586.   topwin = wdes;
  587.   if (h1 < TINYY + 10)
  588.   {
  589.     int lowcnt, i;
  590.   
  591.     lowcnt = 32000;
  592.     for (i = 1; i< MAX_WIND; i++)
  593.     {
  594.       if (find_port(i))
  595.       {
  596.         wind_get(i, WF_CURRXYWH, &x2, &y2, &w2, &h2);
  597.       
  598.         if (w[i].top_age < lowcnt && h2 > TINYY + 10 )
  599.         { /* find top non-tiny open window */
  600.           lowcnt = w[i].top_age;
  601.           topwin = i;
  602.     }
  603.       }
  604.     }
  605.     wind_set(topwin, WF_TOP, 0, 0, 0, 0);
  606.   }
  607.   return(topwin);
  608. }
  609.  
  610. w_arrow(wdes, arrow)
  611. {
  612.   register struct wi_str *wp = &w[wdes];
  613.   int inc_x = wp->font->inc_x;
  614.   int inc_y = wp->font->inc_y;
  615.  
  616.   switch (arrow)
  617.   {
  618.   case 0:    /* page up */
  619.     wp->y_off -= wp->h/inc_y*inc_y;
  620.     goto y_upd;
  621.  
  622.   case 1:    /* page down */
  623.     wp->y_off += wp->h/inc_y*inc_y;
  624.     goto y_upd;
  625.  
  626.   case 2:    /* row up */
  627.     wp->y_off -= inc_y;
  628.     goto y_upd;
  629.  
  630.   case 3:    /* row down */
  631.     wp->y_off += inc_y;
  632.     goto y_upd;
  633.  
  634.   case 4:    /* page left */
  635.     wp->x_off -= wp->w/inc_x*inc_x;
  636.     goto x_upd;
  637.  
  638.   case 5:    /* page right */
  639.     wp->x_off += wp->w/inc_x*inc_x;
  640.     goto x_upd;
  641.  
  642.   case 6:    /* column left */
  643.     wp->x_off -= inc_x;
  644.     goto x_upd;
  645.  
  646.   case 7:    /* column right */
  647.     wp->x_off += inc_x;
  648.     goto x_upd;
  649.   }
  650.  
  651. x_upd:
  652.   if (wp->x_off<0) wp->x_off = 0; else
  653.   if (wp->x_off+wp->w > wp->wi_w) wp->x_off = (wp->wi_w - wp->w)/inc_x*inc_x;
  654.   sethslide(wdes);
  655.   goto upd;
  656.  
  657. y_upd:
  658.   if (wp->y_off<0) wp->y_off = 0; else
  659.   if (wp->y_off+wp->h > wp->wi_h) wp->y_off = (wp->wi_h - wp->h)/inc_y*inc_y;
  660.   setvslide(wdes);
  661.   
  662. upd:
  663.   w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  664. }
  665.  
  666. w_slide(wdes, hor, val)
  667. {
  668.   register struct wi_str *wp = &w[wdes];
  669.  
  670.   if (hor)
  671.   {
  672.     tmp = wp->font->inc_x;
  673.     wp->x_off = ((long)val*(wp->wi_w-wp->w)/1000)/tmp*tmp;
  674.     sethslide(wdes);
  675.   } else
  676.   {
  677.     tmp = wp->font->inc_y;
  678.     wp->y_off = ((long)val*(wp->wi_h-wp->h)/1000)/tmp*tmp;
  679.     setvslide(wdes);
  680.   }
  681.   w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  682. }
  683.  
  684. sethslide(wdes)
  685. {
  686.   register struct wi_str *wp = &w[wdes];
  687.  
  688.   if (wp->wi_style & HSLIDE)
  689.   {
  690.     tmp = (long)1000*wp->x_off/(wp->wi_w-wp->w);
  691.     wind_set(wdes, WF_HSLIDE, tmp, 0, 0, 0);
  692.     tmp = (long)1000*wp->w/wp->wi_w;
  693.     wind_set(wdes, WF_HSLSIZE, tmp, 0, 0, 0);
  694.   }
  695. }
  696.  
  697. setvslide(wdes)
  698. {
  699.   register struct wi_str *wp = &w[wdes];
  700.  
  701.   if (wp->wi_style & VSLIDE)
  702.   {
  703.     tmp = (long)1000*wp->y_off/(wp->wi_h-wp->h);
  704.     wind_set(wdes, WF_VSLIDE, tmp, 0, 0, 0);
  705.     tmp = (long)1000*wp->h/wp->wi_h;
  706.     wind_set(wdes, WF_VSLSIZE, tmp, 0, 0, 0);
  707.   }
  708. }
  709.  
  710. w_flash(wdes, state)
  711. {
  712.   register struct wi_str *wp = &w[wdes];
  713.   static int wdes_last;
  714. #ifdef    KOPY
  715.   int x, y, cnt;
  716. #else
  717.   int t[8];
  718. #endif
  719.  
  720.   if (wdes != wdes_last) w_flash(wdes_last, 1);
  721.   wdes_last = wdes;
  722.   if (!wp->used || wp->curstate == state) return;
  723.   if (state == 2)
  724.     wp->curstate = !wp->curstate;
  725.   else
  726.     wp->curstate = state;
  727. #ifdef    KOPY
  728.   x = wp->cur_x + wp->m_off;
  729.   y = wp->cur_y;
  730.   cnt = wp->wi_mf.wwords >> 1;
  731.   tfbmr(wp->wi_mf.ptr, x, y, cnt, wp->wi_mf.ptr, x, y, cnt,
  732.     wp->font->inc_x, wp->font->inc_y, 12);
  733. #else
  734.   t[0] = t[4] = wp->cur_x + wp->m_off;
  735.   t[1] = t[5] = wp->cur_y;
  736.   t[2] = t[6] = t[0]+wp->font->inc_x-1;
  737.   t[3] = t[7] = t[1]+wp->font->inc_y-1;
  738.   vro_cpyfm(handle, 12, t, &wp->wi_mf, &wp->wi_mf);
  739. #endif
  740.   w_update(wdes, FM_COPY, wp->cur_x, wp->cur_y, wp->font->inc_x, wp->font->inc_y);
  741. }
  742.   
  743. /* w_output prints a string onto the window.  The string may
  744.  * contain control chars and escape sequences.  It ends with \0.
  745.  */
  746.  
  747. w_output(wdes, ptr)
  748. char *ptr;
  749. {
  750.   register struct wi_str *wp = &w[wdes];
  751.   static char ch;
  752.   static int inc_x, cur_x;
  753.   static int state;
  754.   static int inc_y, cur_y;
  755. #ifdef    KOPY
  756.   int x, w, cnt;
  757. #else
  758.   static int t[8];
  759. #endif
  760.   static int f_x, f_y, f_mod;
  761.   static int scrolled;    /* Number of scrolling operations delayed */
  762.   static int xsiz, ysiz;/* Size in chars of terminal emulation for this window*/
  763.   register unsigned char *sptr;
  764.   register unsigned long *dptr;
  765.   register unsigned long mask;
  766.   register int shift;
  767.   register unsigned long val;
  768.   static int count;
  769.   static char * fdata;
  770.   static long width;
  771.   static char * wimfptr;
  772.   static int moffincx;
  773.   static char * savptr;
  774.   
  775.  
  776. #ifdef DEBUG
  777.   printf("entered w_output\n");
  778. #endif
  779.   if (!wp->font) return;
  780.   state = wp->state;
  781.   inc_x = wp->font->inc_x;
  782.   inc_y = wp->font->inc_y;
  783.   xsiz = wp->x_chrs;
  784.   ysiz = wp->y_chrs;
  785.   f_x = cur_x = wp->cur_x;
  786.   f_y = cur_y = wp->cur_y;
  787.   scrolled = wp->top_y/inc_y;
  788.   fdata = wp->font->f_data;
  789.   width = 2 * wp->wi_mf.wwords;
  790.   wimfptr = ((char *) (wp-> wi_mf.ptr)) - 2;
  791.   moffincx = wp->m_off + inc_x - 1;
  792.   f_mod = 0;
  793.   savptr = ptr;
  794.   
  795.   if (wp->curstate) w_flash(wdes, 0);
  796.  
  797.   while (ch = *ptr++)
  798.   {
  799.     switch (state)
  800.     {
  801.     case S_NORMAL:
  802.       if (ch >= ' ')
  803.       {
  804.     if (wp->insmode) /* open space for character */
  805.     {
  806. #ifdef    KOPY
  807.       x = cur_x + wp->m_off;
  808.       cnt = wp->wi_mf.wwords >> 1;
  809.       cpbmr(wp->wi_mf.ptr, x, cur_y, cnt,
  810.         wp->wi_mf.ptr, x + inc_x, cur_y, cnt,
  811.         (xsiz - 1) * inc_x + wp->m_off - x, inc_y);
  812. #else
  813.       t[0] = cur_x + wp->m_off;
  814.       t[1] = t[5] = cur_y;
  815.       t[2] = (xsiz - 1) * inc_x + wp->m_off - 1;
  816.       t[3] = t[7] = cur_y + inc_y - 1;
  817.       t[4] = t[0] + inc_x;
  818.       t[6] = t[2] + inc_x;
  819.       vro_cpyfm(handle, 3, t, &wp->wi_mf, &wp->wi_mf);
  820. #endif
  821.     }
  822.     /* paint the character */
  823.     sptr = fdata+ch*16;
  824.     dptr = wimfptr + cur_y*width
  825.         + (((moffincx + cur_x)>>4)<<1);
  826.     shift = 15 - ((moffincx + cur_x)&15);
  827.     if (overstrike)
  828.       mask = -1L;
  829.     else
  830.       mask = (-1L<<(shift+inc_x)|(1<<shift)-1);
  831.     if (wp->inverse)
  832.     {
  833.       for (count = inc_y; count; count--)
  834.       {
  835.         val = ((long)(*sptr++))<<shift ^ ~mask;
  836.         *dptr = (*dptr&mask)|val;
  837.         ((char *)dptr) += width;
  838.       }
  839.     } else
  840.     {
  841.       for (count = inc_y; count; count--)
  842.       {
  843.         val = ((long)(*sptr++))<<shift;
  844.         *dptr = (*dptr&mask)|val;
  845.         ((char *)dptr) += width;
  846.       }
  847.     }
  848.         cur_x += inc_x;
  849.     f_mod = 1;
  850.     if (cur_x > inc_x * xsiz) /* autowrap */
  851.     {
  852.       cur_y += inc_y;
  853.       if (cur_y >= wp->top_y + inc_y * ysiz) {
  854.         if (wp->ptr_status & LOG_TOP)
  855.           dump_line(wdes, 0);
  856.         wp->top_y += inc_y;
  857.         ++ scrolled;
  858.       }
  859.       if (! scrolled)
  860.       {
  861.         w_update(wdes, FM_COPY, f_x, f_y, cur_x-f_x, inc_y);
  862.         f_mod = 0;
  863.       }
  864.       cur_x = X0;
  865.  
  866.       f_x = cur_x;
  867.       f_y = cur_y;
  868.     }
  869.       } else /* not printable character */
  870.       {
  871.     if (f_mod && !scrolled)
  872.     {
  873.       if (!wp->insmode)
  874.         w_update(wdes, FM_COPY, f_x, f_y, cur_x - f_x, inc_y);
  875.       else
  876.         w_update(wdes, FM_COPY, f_x, f_y, xsiz * inc_x-f_x, inc_y);
  877.       f_mod = 0;
  878.     }
  879.     switch (ch)
  880.     {
  881.     case '\007':    /* Bell */
  882.       if (audibell)
  883.         Bconout(2, '\007');
  884.       if (toponbel)
  885.         /* put this window on top but don't make it the current window.
  886.          * should we set a flag so that the first input from the current
  887.          * window puts it back on top?
  888.          */
  889.         wind_set(wdes, WF_TOP, wdes, 0, 0, 0);
  890.       if (visibell)
  891.       {
  892.         w_redraw(wdes, FM_INVERT, wp->x, wp->y, wp->w, wp->h);
  893.         w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  894.         /* Should clear flag to prevent need for next update? */
  895.       }
  896.       break;
  897.  
  898.     case '\r':    /* Carriage Return */
  899.       cur_x = X0;
  900.       break;
  901.  
  902.     case '\b':    /* Backspace */
  903.       if (cur_x>X0) cur_x -= inc_x;
  904.       break;
  905.  
  906.     case '\n':    /* Newline */
  907.       cur_y += inc_y;
  908.       if (cur_y >= inc_y * ysiz + wp->top_y)
  909.       {
  910.         if (wp->ptr_status & LOG_TOP)
  911.           dump_line(wdes, 0);
  912.         wp->top_y += inc_y;
  913.         ++ scrolled;
  914.       }
  915.       break;
  916.  
  917.     case '\036':    /* Home */
  918.       cur_x = X0;
  919.       cur_y = wp->top_y;
  920.       break;
  921.  
  922.     case '\013':    /* Cursor Up */
  923.       if (cur_y!=wp->top_y) {
  924.         cur_y -= inc_y;
  925.       }
  926.       break;
  927.  
  928.     case '\014':    /* Cursor Right */
  929.       if (cur_x < (xsiz - 1) * inc_x) cur_x += inc_x;
  930.       break;
  931.  
  932.     case '\032':    /* Clear Screen */
  933.       wp->inverse = wp->insmode = 0;
  934.       cur_x = X0;
  935.       cur_y = Y0;
  936.       wp->top_y = Y0;
  937.       lineerase(wp, 0, ysiz - 1 + MAXSCROLLED);
  938.       ++ scrolled;
  939.       break;
  940.  
  941.     case '\t':    /* Tab */
  942.       cur_x = ((cur_x/inc_x/8+1))*inc_x*8+X0;
  943.       break;
  944.  
  945.     case '\033':    /* ESC */
  946.       state = S_ESC;
  947.       count = 0; /* count is used for insert or delete line */
  948.       break;
  949.     }
  950.     f_x = cur_x;
  951.     f_y = cur_y;
  952.       }
  953.       break;
  954.  
  955.     case S_ESC:
  956.       if (ch >= '0' && ch <= '9') {
  957.         count = count * 10 + ch - '0';
  958.     break;
  959.       }
  960.       switch (ch)
  961.       {
  962.       case '*':        /* Clear Screen */
  963.     f_x = cur_x = X0;
  964.     wp->top_y = f_y = cur_y = Y0;
  965.     wp->inverse = wp->insmode = 0;
  966.     lineerase(wp, 0, ysiz - 1 + MAXSCROLLED);
  967.     ++ scrolled;
  968.     state = S_NORMAL;
  969.     break;
  970.  
  971.       case 'Y':        /* Clear to End of Screen */
  972.     lineerase(wp, cur_y / inc_y + 1, ysiz - 1 + wp->top_y / inc_y);
  973.     if (! scrolled)
  974.       w_update(wdes, FM_COPY, X0, cur_y + inc_y, xsiz*inc_x, ysiz*inc_y);
  975.     /* fall through */
  976.       case 'T':        /* Clear to End of Line */
  977. #ifdef    KOPY
  978.     x = cur_x + wp->m_off;
  979.     cnt = wp->wi_mf.wwords >> 1;
  980.     tfbmr((short *) 0, 0, 0, 0, wp->wi_mf.ptr, x, cur_y, cnt,
  981.       X0 + xsiz * inc_x + wp->m_off - x, inc_y, 0);
  982. #else
  983.     t[0] = t[4] = cur_x + wp->m_off;
  984.     t[1] = t[5] = cur_y;
  985.     t[2] = t[6] = X0-1 + xsiz*inc_x +wp->m_off;
  986.     t[3] = t[7] = cur_y+inc_y-1;
  987.     vro_cpyfm(handle, 0, t, &wp->wi_mf, &wp->wi_mf);
  988. #endif
  989.     if (! scrolled)
  990.       w_update(wdes, FM_COPY, cur_x, cur_y, xsiz * inc_x - cur_x, inc_y);
  991.     state = S_NORMAL;
  992.     break;
  993.  
  994.       case 'E':        /* Add Line */
  995.       case 'R':        /* Delete Line */
  996.         if (count == 0) {
  997.       count = 1;
  998.       /* Look ahead for contiguous insert/delete line operations */
  999.       while (*ptr == '\033' && ptr[1] == ch) {
  1000.         ptr +=2;
  1001.         count ++;
  1002.       }
  1003.     }
  1004.     if (ch == 'E')
  1005.       scrolldn(wp, cur_y/inc_y, ysiz-(cur_y-wp->top_y+Y0)/inc_y-count, count);
  1006.     else
  1007.       scrollup(wp, cur_y / inc_y,
  1008.         ysiz - (cur_y - wp->top_y + Y0)/inc_y - count, count);
  1009.     if (! scrolled)
  1010.       w_update(wdes, FM_COPY, X0, cur_y, xsiz * inc_x,
  1011.         ysiz * inc_y - cur_y + wp->top_y - Y0);
  1012.     state = S_NORMAL;
  1013.     break;
  1014.  
  1015.       case 'q':        /* Insert Mode */
  1016.     wp->insmode = 1;
  1017.     state = S_NORMAL;
  1018.     break;
  1019.  
  1020.       case 'r':        /* End Insert */
  1021.     wp->insmode = 0;
  1022.     state = S_NORMAL;
  1023.     break;
  1024.  
  1025.       case 'W':        /* Delete Character */
  1026. #ifdef    KOPY
  1027.     x = cur_x + wp->m_off;
  1028.     w = X0 + xsiz * inc_x + wp->m_off - x;
  1029.     cnt = wp->wi_mf.wwords >> 1;
  1030.     cpbmr(wp->wi_mf.ptr, x + inc_x, cur_y, cnt,
  1031.       wp->wi_mf.ptr, x, cur_y, cnt, w, inc_y);
  1032.     tfbmr((short *) 0, 0, 0, 0,
  1033.       wp->wi_mf.ptr, X0 + (xsiz - 1) * inc_x + wp->m_off, cur_y, cnt,
  1034.       inc_x, inc_y, 0);
  1035. #else
  1036.     t[0] = cur_x + inc_x + wp->m_off;
  1037.     t[1] = t[5] = cur_y;
  1038.     t[2] = X0 - 1 + xsiz * inc_x + wp->m_off;
  1039.     t[3] = t[7] = cur_y+inc_y - 1;
  1040.     t[4] = t[0] - inc_x;
  1041.     t[6] = t[2] - inc_x;
  1042.     vro_cpyfm(handle, 3, t, &wp->wi_mf, &wp->wi_mf);
  1043.     t[0] = t[4] = X0 + (xsiz - 1) * inc_x + wp->m_off;
  1044.     t[2] = t[6] = t[0] + inc_x - 1;
  1045.     vro_cpyfm(handle, 0, t, &wp->wi_mf, &wp->wi_mf);
  1046. #endif
  1047.     if (! scrolled)
  1048.       w_update(wdes, FM_COPY, cur_x, cur_y, xsiz * inc_x - (cur_x - X0),
  1049.         inc_y);
  1050.     state = S_NORMAL;
  1051.     break;
  1052.  
  1053.       case '=':        /* Cursor Movement */
  1054.     state = S_ESC1;
  1055.     break;
  1056.  
  1057.       case 'G':        /* Switch Inverse/Normal */
  1058.     state = S_ESC2;
  1059.     break;
  1060.  
  1061.       case 'S':        /* Change Status Line */
  1062.     state = S_STATUS;
  1063.     wp->nuptr = 0;
  1064.     break;
  1065.     
  1066.       case '[':        /* ascii escape */
  1067.         state = S_ESCA;
  1068.     wp->nuptr = 0;
  1069.     break;
  1070.  
  1071.       default:        /* Unknown escape sequence */
  1072.     state = S_NORMAL;
  1073.       }
  1074.       break;
  1075.  
  1076.     case S_ESC1:    /* get line number */
  1077.       if (ch < ' ' || ch >= ' ' + ysiz) ch = ' ';
  1078.       f_y = cur_y = (ch-' ')*inc_y + wp->top_y;
  1079.       state = S_ESC3;
  1080.       break;
  1081.  
  1082.     case S_ESC3:    /* get column number */
  1083.       if (ch < ' ' || ch >= ' ' + xsiz) ch = ' ';
  1084.       f_x = cur_x = (ch-' ')*inc_x +X0;
  1085.       state = S_NORMAL;
  1086.       break;
  1087.  
  1088.     case S_ESC2:    /* get normal/inverse state */
  1089.       wp->inverse = ch&1;
  1090.       state = S_NORMAL;
  1091.       break;
  1092.  
  1093.     case S_STATUS:
  1094.       if (ch == '\r')
  1095.       {
  1096.     wp->nuname[wp->nuptr] = '\0';
  1097.     w_rename(wdes, wp->nuname);
  1098.     state = S_NORMAL;
  1099.       } else if (wp->nuptr < 72)
  1100.       {
  1101.     wp->nuname[wp->nuptr++] = ch;
  1102.       }
  1103.       break;
  1104.     case S_ESCA:
  1105.       if (ch >= '0' && ch <= '9')
  1106.         wp->nuptr = ch - '0' + 10 * wp->nuptr;
  1107.       else if (ch == 't')
  1108.       {
  1109.         if (wp-> nuptr == 18)
  1110.     {
  1111.       char posstr[20];
  1112.       
  1113.       sprintf(posstr, "\033[8;%d;%dt", ysiz, xsiz);
  1114.       proto_out(find_port(wdes), posstr, (int)strlen(posstr));
  1115.     }
  1116.     state = S_NORMAL;
  1117.       }
  1118.       else state = S_NORMAL;
  1119.       break;
  1120.     } /* end switch on state */
  1121.  
  1122.     if (scrolled >= MAXSCROLLED)
  1123.     {
  1124.       if (wp->top_y != Y0) {
  1125.         scrollup(wp, 0, ysiz, wp->top_y/inc_y);
  1126.     wp->top_y = Y0;
  1127.         f_y = cur_y = Y0 + (ysiz - 1) * inc_y;
  1128.       }
  1129.       w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  1130.       scrolled = 0;
  1131.     }
  1132.   } /* end while loop for each character */
  1133.  
  1134.   if (wp->ptr_status & LOG_BOTOM) {
  1135.     ptr = savptr;
  1136.     while ((ch = *ptr++) && (wp->ptr_status & LOG_BOTOM))
  1137. #if 0
  1138.       if (Cprnout(ch) == 0) wp->ptr_status = LOG_NONE;
  1139. #else
  1140.     ;
  1141. #endif
  1142.   }
  1143.  
  1144.   if (wp->wi_lfd) {
  1145.     while (ch = *savptr++)
  1146.       putc(ch, wp->wi_lfd);
  1147.   }
  1148.  
  1149.   if (scrolled) {
  1150.     if (scrolled >= MAXSCROLLED) {
  1151.       if (wp->top_y != Y0) {
  1152.         scrollup(wp, 0, ysiz, wp->top_y/inc_y);
  1153.         wp->top_y = Y0;
  1154.         cur_y = Y0 + (ysiz - 1) * inc_y;
  1155.       }
  1156.     }
  1157.     w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  1158.   }
  1159.   else
  1160.     if (f_mod)
  1161.     {
  1162.       if (!wp->insmode)
  1163.         w_update(wdes, FM_COPY, f_x, f_y, cur_x - f_x, inc_y);
  1164.       else
  1165.         w_update(wdes, FM_COPY, f_x, f_y, xsiz * inc_x-f_x, inc_y);
  1166.     }
  1167.   wp->cur_x = cur_x;
  1168.   wp->cur_y = cur_y;
  1169.   wp->state = state;
  1170. #ifdef DEBUG
  1171.   printf ("calling w_flash\n");
  1172. #endif
  1173.   w_flash(wdes, 1);
  1174. }
  1175.  
  1176. lineerase(wp, first, last)
  1177. register struct wi_str *wp;
  1178. {
  1179.   register int *p;
  1180.   long count;
  1181.   long linespace = wp->wi_mf.wwords*wp->font->inc_y;
  1182.  
  1183.   p = wp->wi_mf.ptr + first*linespace + Y0*wp->wi_mf.wwords - 1;
  1184.   count = (last-first+1)*linespace;
  1185.   while (count > 7)
  1186.   {
  1187.     *(((long *)p)++) = 0;
  1188.     *(((long *)p)++) = 0;
  1189.     *(((long *)p)++) = 0;
  1190.     *(((long *)p)++) = 0;
  1191.     count -= 8;
  1192.   }
  1193.   while (--count >= 0)
  1194.     *++p = 0;
  1195. }
  1196.  
  1197. scrollup(wp, first, nlines, amount)
  1198. register struct wi_str *wp;
  1199. {
  1200.   register int *p1, *p2;
  1201.   register long count;
  1202.   int linespace = wp->wi_mf.wwords*wp->font->inc_y;
  1203.  
  1204.   p1 = wp->wi_mf.ptr + first*linespace + Y0*wp->wi_mf.wwords;
  1205.   p2 = p1 + linespace * amount;
  1206.   count = (long)(nlines)*linespace;
  1207.   while (count > 15)
  1208.   {
  1209.     *(((long *)p1)++) = *(((long *)p2)++);
  1210.     *(((long *)p1)++) = *(((long *)p2)++);
  1211.     *(((long *)p1)++) = *(((long *)p2)++);
  1212.     *(((long *)p1)++) = *(((long *)p2)++);
  1213.     *(((long *)p1)++) = *(((long *)p2)++);
  1214.     *(((long *)p1)++) = *(((long *)p2)++);
  1215.     *(((long *)p1)++) = *(((long *)p2)++);
  1216.     *(((long *)p1)++) = *(((long *)p2)++);
  1217.     count -= 16;
  1218.   }
  1219.   while (--count >= 0)
  1220.     *(p1++) = *(p2++);
  1221.   count = linespace * amount;
  1222.   while (count > 7)
  1223.   {
  1224.     *(((long *)p1)++) = 0;
  1225.     *(((long *)p1)++) = 0;
  1226.     *(((long *)p1)++) = 0;
  1227.     *(((long *)p1)++) = 0;
  1228.     count -= 8;
  1229.   }
  1230.   while (--count >= 0)
  1231.     *(p1++) = 0;
  1232. }
  1233.  
  1234. scrolldn(wp, first, nlines, amount)
  1235. register struct wi_str *wp;
  1236. {
  1237.   register int *p1, *p2;
  1238.   register long count;
  1239.   long linespace = wp->wi_mf.wwords*wp->font->inc_y;
  1240.  
  1241.   p1 = wp->wi_mf.ptr + (nlines+first+amount)*linespace + Y0*wp->wi_mf.wwords;
  1242.  
  1243.   p2 = p1 - linespace * amount;
  1244.   count = (long)(nlines)*linespace;
  1245.   while (count > 15)
  1246.   {
  1247.     *--(long *)p1 = *--(long *)p2;
  1248.     *--(long *)p1 = *--(long *)p2;
  1249.     *--(long *)p1 = *--(long *)p2;
  1250.     *--(long *)p1 = *--(long *)p2;
  1251.     *--(long *)p1 = *--(long *)p2;
  1252.     *--(long *)p1 = *--(long *)p2;
  1253.     *--(long *)p1 = *--(long *)p2;
  1254.     *--(long *)p1 = *--(long *)p2;
  1255.     count -= 16;
  1256.   }
  1257.   while (--count >= 0)
  1258.     *--p1 = *--p2;
  1259.   count = linespace * amount;
  1260.   while (count > 7)
  1261.   {
  1262.     *--(long *)p1 = 0L;
  1263.     *--(long *)p1 = 0L;
  1264.     *--(long *)p1 = 0L;
  1265.     *--(long *)p1 = 0L;
  1266.     count -= 8;
  1267.   }
  1268.   while (--count >= 0)
  1269.     *--p1 = 0;
  1270. }
  1271.