home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mint104s.zoo / mint.src / fasttext.c < prev    next >
C/C++ Source or Header  |  1993-03-08  |  26KB  |  1,363 lines

  1. /*
  2. Copyright 1992,1992 Eric R. Smith.
  3. Copyright 1992 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. #include "mint.h"
  8. #include "fasttext.h"
  9.  
  10. #ifdef FASTTEXT
  11.  
  12. #ifdef __GNUC__
  13. #define INLINE inline
  14. #define ITYPE long    /* gcc's optimizer likes 32 bit integers */
  15. #else
  16. #define INLINE
  17. #define ITYPE int
  18. #endif
  19.  
  20. #define CONDEV    (2)
  21.  
  22. static SCREEN *current;
  23.  
  24. static void paint P_((SCREEN *, int, char *)),
  25.      paint8c P_((SCREEN *, int, char *)),
  26.      paint816m P_((SCREEN *, int, char *));
  27.  
  28. INLINE static void curs_off P_((SCREEN *)), curs_on P_((SCREEN *));
  29. INLINE static void flash P_((SCREEN *));
  30. static void normal_putch P_((SCREEN *, int));
  31. static void escy_putch P_((SCREEN *, int));
  32. static void quote_putch P_((SCREEN *, int));
  33.  
  34. static    char *chartab[256];
  35.  
  36. #define MAX_PLANES 8
  37. static int fgmask[MAX_PLANES], bgmask[MAX_PLANES];
  38.  
  39. static long scrnsize;
  40.  
  41. short hardscroll;
  42. static char *hardbase, *oldbase;
  43.  
  44. typedef void (*Vfunc) P_((SCREEN *, int));
  45.  
  46. #define base *((char **)0x44eL)
  47. #define escy1 *((short *)0x4acL)
  48.  
  49. static Vfunc state;
  50.  
  51. static short hardline;
  52. static void (*vpaint) P_((SCREEN *, int, char *));
  53. static char *rowoff;
  54.  
  55. void init P_((void));
  56. void hardware_scroll P_((SCREEN *));
  57. INLINE static char *PLACE P_((SCREEN *, int, int));
  58. INLINE static void gotoxy P_((SCREEN *, int, int));
  59. INLINE static void clrline P_((SCREEN *, int));
  60. INLINE static void clear P_((SCREEN *));
  61. INLINE static void clrchar P_((SCREEN *, int, int));
  62. INLINE static void clrfrom P_((SCREEN *, int, int, int, int));
  63. INLINE static void delete_line P_((SCREEN *, int));
  64. INLINE static void insert_line P_((SCREEN *, int));
  65. static void setbgcol P_((SCREEN *, int));
  66. static void setfgcol P_((SCREEN *, int));
  67. static void putesc P_((SCREEN *, int));
  68. static void escy1_putch P_((SCREEN *, int));
  69. INLINE static void put_ch P_((SCREEN *, int));
  70.  
  71. /* routines for flashing the cursor for screen v */
  72. /* flash(v): invert the character currently under the cursor */
  73.  
  74. INLINE static void
  75. flash(v)
  76.     SCREEN *v;
  77. {
  78.     char *place;
  79.     ITYPE i, j, vplanes;
  80.  
  81.     vplanes = v->planes + v->planes;
  82.     place = v->cursaddr;
  83.  
  84.     for (j = v->cheight; j > 0; --j) {
  85.         for (i = 0; i < vplanes; i+=2)
  86.             place[i] = ~place[i];
  87.  
  88.         place += v->planesiz;
  89.     }
  90.     v->curstimer = v->period;
  91. }
  92.  
  93. /* make sure the cursor is off */
  94.  
  95. INLINE
  96. static void
  97. curs_off(v)
  98.     SCREEN *v;
  99. {
  100.     if (v->flags & CURS_ON) {
  101.         if (v->flags & CURS_FSTATE) {
  102.             flash(v);
  103.             v->flags &= ~CURS_FSTATE;
  104.         }
  105.     }
  106. }
  107.  
  108. /* OK, show the cursor again (if appropriate) */
  109.  
  110. INLINE static void
  111. curs_on(v)
  112.     SCREEN *v;
  113. {
  114.     if (v->hidecnt) return;
  115.  
  116.     if (v->flags & CURS_ON) {
  117. #if 0
  118.     /* if the cursor is flashing, we cheat a little and leave it off
  119.      * to be turned on again (if necessary) by the VBL routine
  120.      */
  121.         if (v->flags & CURS_FLASH) {
  122.             v->curstimer = 2;
  123.             return;
  124.         }
  125. #endif
  126.         if (!(v->flags & CURS_FSTATE)) {
  127.             v->flags |= CURS_FSTATE;
  128.             flash(v);
  129.         }
  130.     }
  131. }
  132.  
  133. void
  134. init()
  135. {
  136.     SCREEN *v;
  137.     int i, j;
  138.     char *data, *foo;
  139.     static char chardata[256*16];
  140.     register int linelen;
  141.  
  142.     foo = lineA0();
  143.     v = (SCREEN *)(foo - 346);
  144.     
  145.     /* Ehem... The screen might be bigger than 32767 bytes.
  146.        Let's do some casting... 
  147.        Erling
  148.     */
  149.     linelen = v->linelen;
  150.     scrnsize = (v->maxy+1)*(long)linelen;
  151.     rowoff = (char *)kmalloc((long)((v->maxy+1) * sizeof(long)));
  152.     if (rowoff == 0) {
  153.         FATAL("Insufficient memory for screen offset table!");
  154.     } else {
  155.         long off, *lptr = (long *)rowoff;
  156.         for (i=0, off=0; i<=v->maxy; i++) {
  157.             *lptr++ = off;
  158.             off += linelen;
  159.         }
  160.     }
  161.     if (hardscroll == -1) {
  162.     /* request for auto-setting */
  163.         hardscroll = v->maxy+1;
  164.     }
  165.     if (hardscroll > 0) {
  166.         if (!hardbase)
  167.             hardbase = (char *)(((long)kcore(SCNSIZE(v)+256L)+255L)
  168.                        & 0xffffff00L);
  169.  
  170.         if (hardbase == 0) {
  171.             ALERT("Insufficient memory for hardware scrolling!");
  172.         } else {
  173.             quickmove(hardbase, base, scrnsize);
  174.             v->cursaddr = v->cursaddr + (hardbase - base);
  175.             oldbase = base;
  176.             base = hardbase;
  177.             Setscreen(hardbase, hardbase, -1);
  178.         }
  179.     }
  180.     hardline = 0;
  181.     if (v->cheight == 8 && v->planes == 2) {
  182.         foo = &chardata[0];
  183.         vpaint = paint8c;
  184.         for (i = 0; i < 256; i++) {
  185.             chartab[i] = foo;
  186.             data = v->fontdata + i;
  187.             for (j = 0; j < 8; j++) {
  188.                 *foo++ = *data;
  189.                 data += v->form_width;
  190.             }
  191.         }
  192.     } else if ((v->cheight == 16 || v->cheight == 8) && v->planes == 1) {
  193.         foo = &chardata[0];
  194.         vpaint = paint816m;
  195.         for (i = 0; i < 256; i++) {
  196.             chartab[i] = foo;
  197.             data = v->fontdata + i;
  198.             for (j = 0; j < v->cheight; j++) {
  199.                 *foo++ = *data;
  200.                 data += v->form_width;
  201.             }
  202.         }
  203.     }
  204.     else
  205.         vpaint = paint;
  206.  
  207.     if (v->hidecnt == 0) {
  208.     /*
  209.      * make sure the cursor is set up correctly and turned on
  210.      */
  211.         (void)Cursconf(0,0);    /* turn cursor off */
  212.  
  213.         v->flags &= ~CURS_FSTATE;
  214.  
  215.     /* now turn the cursor on the way we like it */
  216.         v->hidecnt = 0;
  217.         curs_on(v);
  218.     } else {
  219.         (void)Cursconf(0,0);
  220.         v->flags &= ~CURS_ON;
  221.         v->hidecnt = 1;
  222.     }
  223.  
  224.     current = v;
  225.     /* setup bgmask and fgmask */
  226.     setbgcol(v, v->bgcol);
  227.     setfgcol(v, v->fgcol);
  228.     state = normal_putch;
  229. }
  230.  
  231. /*
  232.  * PLACE(v, x, y): the address corresponding to the upper left hand corner of
  233.  * the character at position (x,y) on screen v
  234.  */
  235. INLINE static
  236. char *PLACE(v, x, y)
  237.     SCREEN *v;
  238.     int x, y;
  239. {
  240.     char *place;
  241.     int i, j;
  242.  
  243.     place = base + x;
  244.     if (y == v->maxy)
  245.         place += scrnsize - v->linelen;
  246.     else if (y) {
  247.         y+=y;    /* Make Y into index for longword array. */
  248.         y+=y;    /* Two word-size adds are faster than a 2-bit shift. */
  249.         place += *(long *)(rowoff + y);
  250.     }
  251.     if ((j = v->planes-1)) {
  252.         i = (x & 0xfffe);
  253.         do place += i;
  254.         while (--j);
  255.     }
  256.     return place;
  257. }
  258.  
  259. /*
  260.  * paint(v, c, place): put character 'c' at position 'place' on screen
  261.  * v. It is assumed that x, y are proper coordinates!
  262.  * Specialized versions (paint8c and paint816m) of this routine follow;
  263.  * they assume 8 line high characters, medium res. and 8 or 16 line/mono,
  264.  * respectively.
  265.  */
  266.  
  267. static void
  268. paint(v, c, place)
  269.     SCREEN *v;
  270.     int c;
  271.     char *place;
  272. {
  273.     char *data, d, doinverse;
  274.     ITYPE j, planecount;
  275.     int vplanes;
  276.     long vform_width, vplanesiz;
  277.  
  278.     vplanes = v->planes;
  279.  
  280.     data = v->fontdata + c;
  281.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  282.     vform_width = v->form_width;
  283.     vplanesiz = v->planesiz;
  284.  
  285.     for (j = v->cheight; j > 0; --j) {
  286.         d = *data ^ doinverse;
  287.         for (planecount = 0; planecount < vplanes; planecount++)
  288.           place[planecount << 1]
  289.             = ((d & (char) fgmask[planecount])
  290.                | (~d & (char) bgmask[planecount]));
  291.         place += vplanesiz;
  292.         data += vform_width;
  293.     }
  294. }
  295.  
  296. static void
  297. paint8c(v, c, place)
  298.     SCREEN *v;
  299.     int c;
  300.     char *place;
  301. {
  302.     char *data;
  303.     char d, doinverse;
  304.     char bg0, bg1, fg0, fg1;
  305.     long vplanesiz;
  306.  
  307.     data = chartab[c];
  308.  
  309.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  310.     vplanesiz = v->planesiz;
  311.     bg0 = bgmask[0];
  312.     bg1 = bgmask[1];
  313.     fg0 = fgmask[0];
  314.     fg1 = fgmask[1];
  315.  
  316.     if (!doinverse && !bg0 && !bg1 && fg0 && fg1) {
  317.         /* line 1 */
  318.         d = *data++;
  319.         *place = d;
  320.         place[2] = d;
  321.         place += vplanesiz;
  322.  
  323.         /* line 2 */
  324.         d = *data++;
  325.         *place = d;
  326.         place[2] = d;
  327.         place += vplanesiz;
  328.  
  329.         /* line 3 */
  330.         d = *data++;
  331.         *place = d;
  332.         place[2] = d;
  333.         place += vplanesiz;
  334.  
  335.         /* line 4 */
  336.         d = *data++;
  337.         *place = d;
  338.         place[2] = d;
  339.         place += vplanesiz;
  340.  
  341.         /* line 5 */
  342.         d = *data++;
  343.         *place = d;
  344.         place[2] = d;
  345.         place += vplanesiz;
  346.  
  347.         /* line 6 */
  348.         d = *data++;
  349.         *place = d;
  350.         place[2] = d;
  351.         place += vplanesiz;
  352.  
  353.         /* line 7 */
  354.         d = *data++;
  355.         *place = d;
  356.         place[2] = d;
  357.         place += vplanesiz;
  358.  
  359.         /* line 8 */
  360.         d = *data;
  361.         *place = d;
  362.         place[2] = d;
  363.     } else {
  364.         /* line 1 */
  365.         d = *data++ ^ doinverse;
  366.         *place = ((d & fg0) | (~d & bg0));
  367.         place[2] = ((d & fg1) | (~d & bg1));
  368.         place += vplanesiz;
  369.  
  370.         /* line 2 */
  371.         d = *data++ ^ doinverse;
  372.         *place = ((d & fg0) | (~d & bg0));
  373.         place[2] = ((d & fg1) | (~d & bg1));
  374.         place += vplanesiz;
  375.  
  376.         /* line 3 */
  377.         d = *data++ ^ doinverse;
  378.         *place = ((d & fg0) | (~d & bg0));
  379.         place[2] = ((d & fg1) | (~d & bg1));
  380.         place += vplanesiz;
  381.  
  382.         /* line 4 */
  383.         d = *data++ ^ doinverse;
  384.         *place = ((d & fg0) | (~d & bg0));
  385.         place[2] = ((d & fg1) | (~d & bg1));
  386.         place += vplanesiz;
  387.  
  388.         /* line 5 */
  389.         d = *data++ ^ doinverse;
  390.         *place = ((d & fg0) | (~d & bg0));
  391.         place[2] = ((d & fg1) | (~d & bg1));
  392.         place += vplanesiz;
  393.  
  394.         /* line 6 */
  395.         d = *data++ ^ doinverse;
  396.         *place = ((d & fg0) | (~d & bg0));
  397.         place[2] = ((d & fg1) | (~d & bg1));
  398.         place += vplanesiz;
  399.  
  400.         /* line 7 */
  401.         d = *data++ ^ doinverse;
  402.         *place = ((d & fg0) | (~d & bg0));
  403.         place[2] = ((d & fg1) | (~d & bg1));
  404.         place += vplanesiz;
  405.  
  406.         /* line 8 */
  407.         d = *data ^ doinverse;
  408.         *place = ((d & fg0) | (~d & bg0));
  409.         place[2] = ((d & fg1) | (~d & bg1));
  410.     }
  411. }
  412.  
  413. static void
  414. paint816m(v, c, place)
  415.     SCREEN *v;
  416.     int c;
  417.     char *place;
  418. {
  419.     char *data;
  420.     char d, doinverse;
  421.     long vplanesiz;
  422.  
  423.     data = chartab[c];
  424.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  425.     doinverse ^= bgmask[0];
  426.     vplanesiz = v->planesiz;
  427.  
  428.     if (bgmask[0] == fgmask[0])
  429.       {
  430.         /* fgcol and bgcol are the same -- easy */
  431.         d = (char) bgmask[0];
  432.         *place = d;
  433.         place += vplanesiz;
  434.         *place = d;
  435.         place += vplanesiz;
  436.         *place = d;
  437.         place += vplanesiz;
  438.         *place = d;
  439.         place += vplanesiz;
  440.         *place = d;
  441.         place += vplanesiz;
  442.         *place = d;
  443.         place += vplanesiz;
  444.         *place = d;
  445.         place += vplanesiz;
  446.         *place = d;
  447.         if (v->cheight == 8)
  448.         return;
  449.         place += vplanesiz;
  450.         *place = d;
  451.         place += vplanesiz;
  452.         *place = d;
  453.         place += vplanesiz;
  454.         *place = d;
  455.         place += vplanesiz;
  456.         *place = d;
  457.         place += vplanesiz;
  458.         *place = d;
  459.         place += vplanesiz;
  460.         *place = d;
  461.         place += vplanesiz;
  462.         *place = d;
  463.         place += vplanesiz;
  464.         *place = d;
  465.       }
  466.     else if (!doinverse) {
  467.         /* line 1 */
  468.         d = *data++;
  469.         *place = d;
  470.         place += vplanesiz;
  471.  
  472.         /* line 2 */
  473.         d = *data++;
  474.         *place = d;
  475.         place += vplanesiz;
  476.  
  477.         /* line 3 */
  478.         d = *data++;
  479.         *place = d;
  480.         place += vplanesiz;
  481.  
  482.         /* line 4 */
  483.         d = *data++;
  484.         *place = d;
  485.         place += vplanesiz;
  486.  
  487.         /* line 5 */
  488.         d = *data++;
  489.         *place = d;
  490.         place += vplanesiz;
  491.  
  492.         /* line 6 */
  493.         d = *data++;
  494.         *place = d;
  495.         place += vplanesiz;
  496.  
  497.         /* line 7 */
  498.         d = *data++;
  499.         *place = d;
  500.         place += vplanesiz;
  501.  
  502.         /* line 8 */
  503.         d = *data++;
  504.         *place = d;
  505.  
  506.         if (v->cheight == 8)
  507.             return;
  508.  
  509.         place += vplanesiz;
  510.  
  511.         /* line 9 */
  512.         d = *data++;
  513.         *place = d;
  514.         place += vplanesiz;
  515.  
  516.         /* line 10 */
  517.         d = *data++;
  518.         *place = d;
  519.         place += vplanesiz;
  520.  
  521.         /* line 11 */
  522.         d = *data++;
  523.         *place = d;
  524.         place += vplanesiz;
  525.  
  526.         /* line 12 */
  527.         d = *data++;
  528.         *place = d;
  529.         place += vplanesiz;
  530.  
  531.         /* line 13 */
  532.         d = *data++;
  533.         *place = d;
  534.         place += vplanesiz;
  535.  
  536.         /* line 14 */
  537.         d = *data++;
  538.         *place = d;
  539.         place += vplanesiz;
  540.  
  541.         /* line 15 */
  542.         d = *data++;
  543.         *place = d;
  544.         place += vplanesiz;
  545.  
  546.         /* line 16 */
  547.         d = *data;
  548.         *place = d;
  549.     } else {
  550.         /* line 1 */
  551.         d = ~*data++;
  552.         *place = d;
  553.         place += vplanesiz;
  554.  
  555.         /* line 2 */
  556.         d = ~*data++;
  557.         *place = d;
  558.         place += vplanesiz;
  559.  
  560.         /* line 3 */
  561.         d = ~*data++;
  562.         *place = d;
  563.         place += vplanesiz;
  564.  
  565.         /* line 4 */
  566.         d = ~*data++;
  567.         *place = d;
  568.         place += vplanesiz;
  569.  
  570.         /* line 5 */
  571.         d = ~*data++;
  572.         *place = d;
  573.         place += vplanesiz;
  574.  
  575.         /* line 6 */
  576.         d = ~*data++;
  577.         *place = d;
  578.         place += vplanesiz;
  579.  
  580.         /* line 7 */
  581.         d = ~*data++;
  582.         *place = d;
  583.         place += vplanesiz;
  584.  
  585.         /* line 8 */
  586.         d = ~*data++;
  587.         *place = d;
  588.  
  589.         if (v->cheight == 8)
  590.             return;
  591.  
  592.         place += vplanesiz;
  593.  
  594.         /* line 9 */
  595.         d = ~*data++;
  596.         *place = d;
  597.         place += vplanesiz;
  598.  
  599.         /* line 10 */
  600.         d = ~*data++;
  601.         *place = d;
  602.         place += vplanesiz;
  603.  
  604.         /* line 11 */
  605.         d = ~*data++;
  606.         *place = d;
  607.         place += vplanesiz;
  608.  
  609.         /* line 12 */
  610.         d = ~*data++;
  611.         *place = d;
  612.         place += vplanesiz;
  613.  
  614.         /* line 13 */
  615.         d = ~*data++;
  616.         *place = d;
  617.         place += vplanesiz;
  618.  
  619.         /* line 14 */
  620.         d = ~*data++;
  621.         *place = d;
  622.         place += vplanesiz;
  623.  
  624.         /* line 15 */
  625.         d = ~*data++;
  626.         *place = d;
  627.         place += vplanesiz;
  628.  
  629.         /* line 16 */
  630.         d = ~*data;
  631.         *place = d;
  632.     }
  633. }
  634.  
  635. /*
  636.  * gotoxy (v, x, y): move current cursor address of screen v to (x, y)
  637.  * makes sure that (x, y) will be legal
  638.  */
  639.  
  640. INLINE static void
  641. gotoxy(v, x, y)
  642.     SCREEN *v;
  643.     int x, y;
  644. {
  645.     if (x > v->maxx) x = v->maxx;
  646.     else if (x < 0) x = 0;
  647.     if (y > v->maxy) y = v->maxy;
  648.     else if (y < 0) y = 0;
  649.  
  650.     v->cx = x;
  651.     v->cy = y;
  652.     v->cursaddr = PLACE(v, x, y);
  653. }
  654.  
  655. /*
  656.  * clrline(v, r): clear line r of screen v
  657.  */
  658.  
  659. INLINE static void
  660. clrline(v, r)
  661.     SCREEN *v;
  662.     int r;
  663. {
  664.     int *dst, *m;
  665.     long nwords;
  666.     int i, vplanes;
  667.  
  668.     /* Hey, again the screen might be bigger than 32767 bytes.
  669.        Do another cast... */
  670.     r += r;
  671.     r += r;
  672.     dst = (int *)(base + *(long *)(rowoff+r));
  673.     if (v->bgcol == 0)
  674.       zero((char *)dst, v->linelen);
  675.     else
  676.       {
  677.         /* do it the hard way */
  678.         vplanes = v->planes;
  679.         for (nwords = v->linelen >> 1; nwords > 0; nwords -= vplanes)
  680.           {
  681.         m = bgmask;
  682.         for (i = 0; i < vplanes; i++)
  683.           *dst++ = *m++;
  684.           }
  685.       }
  686. }
  687.     
  688. /*
  689.  * clear(v): clear the whole screen v
  690.  */
  691.  
  692. INLINE static void
  693. clear(v)
  694.     SCREEN *v;
  695. {
  696.     int i, vplanes;
  697.     int *dst, *m;
  698.     long nwords;
  699.  
  700.     if (v->bgcol == 0)
  701.       zero(base, scrnsize);
  702.     else
  703.       {
  704.         /* do it the hard way */
  705.         dst = (int *) base;
  706.         vplanes = v->planes;
  707.         for (nwords = scrnsize >> 1; nwords > 0; nwords -= vplanes)
  708.           {
  709.         m = bgmask;
  710.         for (i = 0; i < vplanes; i++)
  711.           *dst++ = *m++;
  712.           }
  713.       }
  714. }
  715.  
  716. /*
  717.  * clrchar(v, x, y): clear the (x,y) position on screen v
  718.  */
  719.  
  720. INLINE static void
  721. clrchar(v, x, y)
  722.     SCREEN *v;
  723.     int x, y;
  724. {
  725.     int i, j, vplanes;
  726.     char *place;
  727.     int *m;
  728.  
  729.     vplanes = v->planes + v->planes;
  730.  
  731.     place = PLACE(v, x, y);
  732.  
  733.     for (j = v->cheight; j > 0; --j) {
  734.         m = bgmask;
  735.         for (i = 0; i < vplanes; i += 2)
  736.             place[i] = (char) *m++;
  737.         place += v->planesiz;
  738.     }
  739. }
  740.  
  741. /*
  742.  * clrfrom(v, x1, y1, x2, y2): clear screen v from position (x1,y1) to
  743.  * position (x2, y2) inclusive. It is assumed that y2 >= y1.
  744.  */
  745.  
  746. INLINE static void
  747. clrfrom(v, x1, y1, x2, y2)
  748.     SCREEN *v;
  749.     int x1,y1,x2,y2;
  750. {
  751.     int i;
  752.  
  753.     for (i = x1; i <= v->maxx; i++)
  754.         clrchar(v, i, y1);
  755.     if (y2 > y1) {
  756.         for (i = 0; i <= x2; i++)
  757.             clrchar(v, i, y2);
  758.         for (i = y1+1; i < y2; i++)
  759.             clrline(v, i);
  760.     }
  761. }
  762.  
  763. /*
  764.  * scroll a screen in hardware; if we still have hardware scrolling lines left,
  765.  * just move the physical screen base, otherwise copy the screen back to the
  766.  * hardware base and start over
  767.  */
  768. void
  769. hardware_scroll(v)
  770.     SCREEN *v;
  771. {
  772.  
  773.     ++hardline;
  774.     if (hardline < hardscroll) { /* just move the screen */
  775.         base += v->linelen;
  776.     } else {
  777.         hardline = 0;
  778.         quickmove(hardbase, base + v->linelen, scrnsize - v->linelen);
  779.         base = hardbase;
  780.     }
  781.     v->cursaddr = PLACE(v, v->cx, v->cy);
  782.     Setscreen(base, base, -1);
  783. }
  784.  
  785. /*
  786.  * delete_line(v, r): delete line r of screen v. The screen below this
  787.  * line is scrolled up, and the bottom line is cleared.
  788.  */
  789.  
  790. #define scroll(v) delete_line(v, 0)
  791.  
  792. INLINE static void
  793. delete_line(v, r)
  794.     SCREEN *v;
  795.     int r;
  796. {
  797.     long *src, *dst, nbytes;
  798.  
  799.     if (r == 0) {
  800.         if (hardbase) {
  801.             hardware_scroll(v);
  802.             clrline(v, v->maxy);
  803.             return;
  804.         }
  805.         nbytes = scrnsize - v->linelen;
  806.     } else {
  807.         register int i = v->maxy - r;
  808.         i += i;
  809.         i += i;
  810.         nbytes = *(long *)(rowoff+i);
  811.     }
  812.  
  813.     /* Sheeze, how many times do we really have to cast... 
  814.        Erling.    
  815.     */
  816.  
  817.     r += r;
  818.     r += r;
  819.     dst = (long *)(base + *(long *)(rowoff + r));
  820.     src = (long *)( ((long)dst) + v->linelen);
  821.  
  822.     quickmove(dst, src, nbytes);
  823.  
  824. /* clear the last line */
  825.     clrline(v, v->maxy);
  826. }
  827.  
  828. /*
  829.  * insert_line(v, r): scroll all of the screen starting at line r down,
  830.  * and then clear line r.
  831.  */
  832.  
  833. INLINE static void
  834. insert_line(v, r)
  835.     SCREEN *v;
  836.     int r;
  837. {
  838.     long *src, *dst;
  839.     int i, j, linelen;
  840.  
  841.     i = v->maxy - 1;
  842.     i += i;
  843.     i += i;
  844.     j = r+r;
  845.     j += j;
  846.     linelen = v->linelen;
  847.     src = (long *)(base + *(long *)(rowoff + i));
  848.     dst = (long *)((long)src + linelen);
  849.     for (; i >= j ; i -= 4) {
  850.     /* move line i to line i+1 */
  851.         quickmove(dst, src, linelen);
  852.         dst = src;
  853.         src = (long *)((long) src - linelen);
  854.     }
  855.  
  856. /* clear line r */
  857.     clrline(v, r);
  858. }
  859.  
  860. /*
  861.  * special states for handling ESC b x and ESC c x. Note that for now,
  862.  * color is ignored.
  863.  */
  864.  
  865. static void
  866. setbgcol(v, c)
  867.     SCREEN *v;
  868.     int c;
  869. {
  870.     int i;
  871.  
  872.     v->bgcol = c & ((1 << v->planes)-1);
  873.     for (i = 0; i < v->planes; i++)
  874.         bgmask[i] = (v->bgcol & (1 << i)) ? -1 : 0;
  875.     state = normal_putch;
  876. }
  877.  
  878. static void
  879. setfgcol(v, c)
  880.     SCREEN *v;
  881.     int c;
  882. {
  883.     int i;
  884.  
  885.     v->fgcol = c & ((1 << v->planes)-1);
  886.     for (i = 0; i < v->planes; i++)
  887.         fgmask[i] = (v->fgcol & (1 << i)) ? -1 : 0;
  888.     state = normal_putch;
  889. }
  890.  
  891. static void
  892. quote_putch(v, c)
  893.     SCREEN *v;
  894.     int c;
  895. {
  896.     (*vpaint)(v, c, v->cursaddr);
  897.     state = normal_putch;
  898. }
  899.  
  900. /*
  901.  * putesc(v, c): handle the control sequence ESC c
  902.  */
  903.  
  904. static void
  905. putesc(v, c)
  906.     SCREEN *v;
  907.     int c;
  908. {
  909.     int i;
  910.     int cx, cy;
  911.  
  912.     cx = v->cx; cy = v->cy;
  913.  
  914.     switch (c) {
  915.     case 'A':        /* cursor up */
  916.         if (cy) {
  917. moveup:            v->cy = --cy;
  918.             v->cursaddr -= v->linelen;
  919.         }
  920.         break;
  921.     case 'B':        /* cursor down */
  922.         if (cy < v->maxy) {
  923.             v->cy = ++cy;
  924.             v->cursaddr += v->linelen;
  925.         }
  926.         break;
  927.     case 'C':        /* cursor right */
  928.         if (cx < v->maxx) {
  929.             if ((i = v->planes-1) && (cx & 1))
  930.                 v->cursaddr += i + i;
  931.             v->cx = ++cx;
  932.             v->cursaddr++;
  933.         }
  934.         break;
  935.     case 'D':        /* cursor left */
  936.         if (cx) {
  937.             v->cx = --cx;
  938.             v->cursaddr--;
  939.             if ((i = v->planes-1) && (cx & 1))
  940.                 v->cursaddr -= i + i;
  941.         }
  942.         break;
  943.     case 'E':        /* clear home */
  944.         clear(v);
  945.         /* fall through... */
  946.     case 'H':        /* cursor home */
  947.         v->cx = 0; v->cy = 0;
  948.         v->cursaddr = base;
  949.         break;
  950.     case 'I':        /* cursor up, insert line */
  951.         if (cy == 0) {
  952.             insert_line(v, 0);
  953.         }
  954.         else
  955.             goto moveup;
  956.         break;
  957.     case 'J':        /* clear below cursor */
  958.         clrfrom(v, cx, cy, v->maxx, v->maxy);
  959.         break;
  960.     case 'K':        /* clear remainder of line */
  961.         clrfrom(v, cx, cy, v->maxx, cy);
  962.         break;
  963.     case 'L':        /* insert a line */
  964.         v->cx = 0;
  965.         i = cy + cy;
  966.         i += i;
  967.         v->cursaddr = base + *(long *)(rowoff + i);
  968.         insert_line(v, cy);
  969.         break;
  970.     case 'M':        /* delete line */
  971.         v->cx = 0;
  972.         i = cy + cy;
  973.         i += i;
  974.         v->cursaddr = base + *(long *)(rowoff + i);
  975.         delete_line(v, cy);
  976.         break;
  977.     case 'Q':        /* quote-next-char */
  978.         state = quote_putch;
  979.         return;
  980.     case 'Y':
  981.         state = escy_putch;
  982.         return;        /* YES, this should be 'return' */
  983.  
  984.     case 'b':
  985.         state = setfgcol;
  986.         return;
  987.     case 'c':
  988.         state = setbgcol;
  989.         return;
  990.     case 'd':        /* clear to cursor position */
  991.         clrfrom(v, 0, 0, cx, cy);
  992.         break;
  993.     case 'e':        /* enable cursor */
  994.         v->flags |= CURS_ON;
  995.         v->hidecnt = 1;    /* so --v->hidecnt shows the cursor */
  996.         break;
  997.     case 'f':        /* cursor off */
  998.         v->hidecnt++;
  999.         v->flags &= ~CURS_ON;
  1000.         break;
  1001.     case 'j':        /* save cursor position */
  1002.         v->savex = v->cx;
  1003.         v->savey = v->cy;
  1004.         break;
  1005.     case 'k':        /* restore saved position */
  1006.         gotoxy(v, v->savex, v->savey);
  1007.         break;
  1008.     case 'l':        /* clear line */
  1009.         v->cx = 0;
  1010.         i = cy + cy;
  1011.         i += i;
  1012.         v->cursaddr = base + *(long *)(rowoff + i);
  1013.         clrline(v, cy);
  1014.         break;
  1015.     case 'o':        /* clear from start of line to cursor */
  1016.         clrfrom(v, 0, cy, cx, cy);
  1017.         break;
  1018.     case 'p':        /* reverse video on */
  1019.         v->flags |= FINVERSE;
  1020.         break;
  1021.     case 'q':        /* reverse video off */
  1022.         v->flags &= ~FINVERSE;
  1023.         break;
  1024.     case 'v':        /* wrap on */
  1025.         v->flags |= FWRAP;
  1026.         break;
  1027.     case 'w':
  1028.         v->flags &= ~FWRAP;
  1029.         break;
  1030.     }
  1031.     state = normal_putch;
  1032. }
  1033.  
  1034. /*
  1035.  * escy1_putch(v, c): for when an ESC Y + char has been seen
  1036.  */
  1037. static void
  1038. escy1_putch(v, c)
  1039.     SCREEN *v;
  1040.     int c;
  1041. {
  1042.     gotoxy(v, c - ' ', escy1 - ' ');
  1043.     state = normal_putch;
  1044. }
  1045.  
  1046. /*
  1047.  * escy_putch(v, c): for when an ESC Y has been seen
  1048.  */
  1049. static void
  1050. escy_putch(v, c)
  1051.     SCREEN *v;
  1052.     int c;
  1053. {
  1054.     UNUSED(v);
  1055.     escy1 = c;
  1056.     state = escy1_putch;
  1057. }
  1058.  
  1059. /*
  1060.  * normal_putch(v, c): put character 'c' on screen 'v'. This is the default
  1061.  * for when no escape, etc. is active
  1062.  */
  1063.  
  1064. static void
  1065. normal_putch(v, c)
  1066.     SCREEN *v;
  1067.     int c;
  1068. {
  1069.     register int i;
  1070.  
  1071. /* control characters */
  1072.     if (c < ' ') {
  1073.         switch (c) {
  1074.         case '\r':
  1075. col0:            v->cx = 0;
  1076.             i = v->cy + v->cy;
  1077.             i += i;
  1078.             v->cursaddr = base + *(long *)(rowoff + i);
  1079.             return;
  1080.         case '\n':
  1081.             if (v->cy == v->maxy) {
  1082.                 scroll(v);
  1083.             } else {
  1084.                 v->cy++;
  1085.                 v->cursaddr += v->linelen;
  1086.             }
  1087.             return;
  1088.         case '\b':
  1089.             if (v->cx) {
  1090.                 v->cx--;
  1091.                 v->cursaddr--;
  1092.                 if ((i = v->planes-1) && (v->cx & 1))
  1093.                     v->cursaddr -= i+i;
  1094.             }
  1095.             return;
  1096.         case '\007':        /* BELL */
  1097.             (void)bconout(CONDEV, 7);
  1098.             return;
  1099.         case '\033':        /* ESC */
  1100.             state = putesc;
  1101.             return;
  1102.         case '\t':
  1103.             if (v->cx < v->maxx) {
  1104.                 register union {
  1105.                     long l;
  1106.                     short i[2];
  1107.                 } j;
  1108.                 j.l = 0;
  1109.                 j.i[1] = 8 - (v->cx & 7);
  1110.                 v->cx += j.i[1];
  1111.                 if (v->cx - v->maxx > 0) {
  1112.                     j.i[1] = v->cx - v->maxx;
  1113.                     v->cx = v->maxx;
  1114.                 }
  1115.                 v->cursaddr += j.l;
  1116.                 if ((i = v->planes-1)) {
  1117.                     if (j.l & 1)
  1118.                         j.i[1]++;
  1119.                     do v->cursaddr += j.l;
  1120.                     while (--i);
  1121.                 }
  1122.             }
  1123.             return;
  1124.         default:
  1125.             return;
  1126.         }
  1127.     }
  1128.  
  1129.     (*vpaint)(v, c, v->cursaddr);
  1130.     v->cx++;
  1131.     if (v->cx > v->maxx) {
  1132.         if (v->flags & FWRAP) {
  1133.             normal_putch(v, '\n');
  1134.             goto col0;
  1135.         } else {
  1136.             v->cx = v->maxx;
  1137.         }
  1138.     } else {
  1139.         v->cursaddr++;
  1140.         if ((i = v->planes-1) && !(v->cx & 1))    /* new word */
  1141.             v->cursaddr += i + i;
  1142.     }
  1143. }
  1144.  
  1145. INLINE static void
  1146. put_ch(v, c)
  1147.     SCREEN *v;
  1148.     int c;
  1149. {
  1150.     (*state)(v, c & 0x00ff);
  1151. }
  1152.  
  1153. static long ARGS_ON_STACK screen_open    P_((FILEPTR *f));
  1154. static long ARGS_ON_STACK screen_read    P_((FILEPTR *f, char *buf, long nbytes));
  1155. static long ARGS_ON_STACK screen_write P_((FILEPTR *f, const char *buf, long nbytes));
  1156. static long ARGS_ON_STACK screen_lseek P_((FILEPTR *f, long where, int whence));
  1157. static long ARGS_ON_STACK screen_ioctl P_((FILEPTR *f, int mode, void *buf));
  1158. static long ARGS_ON_STACK screen_close P_((FILEPTR *f, int pid));
  1159. static long ARGS_ON_STACK screen_select P_((FILEPTR *f, long p, int mode));
  1160. static void ARGS_ON_STACK screen_unselect P_((FILEPTR *f, long p, int mode));
  1161.  
  1162. extern long    ARGS_ON_STACK null_datime    P_((FILEPTR *f, short *time, int rwflag));
  1163.  
  1164. DEVDRV screen_device = {
  1165.     screen_open, screen_write, screen_read, screen_lseek, screen_ioctl,
  1166.     null_datime, screen_close, screen_select, screen_unselect
  1167. };
  1168.  
  1169. static long ARGS_ON_STACK 
  1170. screen_open(f)
  1171.     FILEPTR *f;
  1172. {
  1173.  
  1174.     if (!current) {
  1175.         init();
  1176.     } else
  1177.         return EACCDN;        /* screen in use */
  1178.  
  1179.     f->flags |= O_TTY;
  1180.     return 0;
  1181. }
  1182.  
  1183. static long ARGS_ON_STACK 
  1184. screen_close(f, pid)
  1185.     FILEPTR *f;
  1186.     int pid;
  1187. {
  1188.     UNUSED(pid);
  1189.  
  1190.     if (f->links <= 0) {
  1191.         if (hardbase) {
  1192.             quickmove(oldbase, base, scrnsize);
  1193.             base = oldbase;
  1194.             Setscreen(oldbase, oldbase, -1);
  1195.         }
  1196.         current = 0;
  1197.     }
  1198.     return 0;
  1199. }
  1200.  
  1201. static long ARGS_ON_STACK 
  1202. screen_write(f, buf, bytes)
  1203.     FILEPTR *f; const char *buf; long bytes;
  1204. {
  1205.     SCREEN *v = current;
  1206.     long *r;
  1207.     long ret = 0;
  1208.     int c;
  1209.  
  1210.     UNUSED(f);
  1211.  
  1212.     (void)checkkeys();
  1213.     v->hidecnt++;
  1214.     v->flags |= CURS_UPD;        /* for TOS 1.0 */
  1215.     curs_off(v);
  1216.     r = (long *)buf;
  1217.     while (bytes > 0) {
  1218.         c = (int) *r++;
  1219.         put_ch(v, c);
  1220.         bytes -= 4; ret+= 4;
  1221.     }
  1222.     if (v->hidecnt > 0)
  1223.         --v->hidecnt;
  1224.     else
  1225.         v->hidecnt = 0;
  1226.     curs_on(v);
  1227.     v->flags &= ~CURS_UPD;
  1228.     return ret;
  1229. }
  1230.  
  1231. static long ARGS_ON_STACK 
  1232. screen_read(f, buf, bytes)
  1233.     FILEPTR *f; char *buf; long bytes;
  1234. {
  1235.     long *r, ret = 0;
  1236.  
  1237.     r = (long *)buf;
  1238.  
  1239.     while (bytes > 0) {
  1240.         if ( (f->flags & O_NDELAY) && !bconstat(CONDEV) )
  1241.             break;
  1242.         *r++ = bconin(CONDEV) & 0x7fffffffL;
  1243.         bytes -= 4; ret += 4;
  1244.     }
  1245.     return ret;
  1246. }
  1247.  
  1248. static long ARGS_ON_STACK 
  1249. screen_lseek(f, where, whence)
  1250.     FILEPTR *f;
  1251.     long where;
  1252.     int whence;
  1253. {
  1254. /* terminals always are at position 0 */
  1255.     UNUSED(f); UNUSED(where);
  1256.     UNUSED(whence);
  1257.     return 0;
  1258. }
  1259.  
  1260. static long ARGS_ON_STACK 
  1261. screen_ioctl(f, mode, buf)
  1262.     FILEPTR *f; int mode; void *buf;
  1263. {
  1264.     long *r = (long *)buf;
  1265.     struct winsize *w;
  1266.  
  1267.     UNUSED(f);
  1268.  
  1269.     if (mode == FIONREAD) {
  1270.         if (bconstat(CONDEV))
  1271.             *r = 1;
  1272.         else
  1273.             *r = 0;
  1274.     }
  1275.     else if (mode == FIONWRITE) {
  1276.             *r = 1;
  1277.     }
  1278.     else if (mode == TIOCFLUSH) {
  1279. /* BUG: this should flush the input/output buffers */
  1280.         return 0;
  1281.     }
  1282.     else if (mode == TIOCGWINSZ) {
  1283.         w = (struct winsize *)buf;
  1284.         w->ws_row = current->maxy+1;
  1285.         w->ws_col = current->maxx+1;
  1286.     }
  1287.     else if (mode >= TCURSOFF && mode <= TCURSGRATE) {
  1288.         SCREEN *v = current;
  1289.         switch(mode) {
  1290.         case TCURSOFF:
  1291.             curs_off(v);
  1292.             v->hidecnt++;
  1293.             v->flags &= ~CURS_ON;
  1294.             break;
  1295.         case TCURSON:
  1296.             v->flags |= CURS_ON;
  1297.             v->hidecnt = 0;
  1298.             curs_on(v);
  1299.             break;
  1300.         case TCURSBLINK:
  1301.             curs_off(v);
  1302.             v->flags |= CURS_FLASH;
  1303.             curs_on(v);
  1304.             break;
  1305.         case TCURSSTEADY:
  1306.             curs_off(v);
  1307.             v->flags &= ~CURS_FLASH;
  1308.             curs_on(v);
  1309.             break;
  1310.         case TCURSSRATE:
  1311.             v->period = *((short *)buf);
  1312.             break;
  1313.         case TCURSGRATE:
  1314.             return v->period;
  1315.         }
  1316.     } else
  1317.         return EINVFN;
  1318.  
  1319.     return 0;
  1320. }
  1321.  
  1322. static long ARGS_ON_STACK 
  1323. screen_select(f, p, mode)
  1324.     FILEPTR *f; long p; int mode;
  1325. {
  1326.     struct tty *tty = (struct tty *)f->devinfo;
  1327.     int dev = CONDEV;
  1328.  
  1329.     if (mode == O_RDONLY) {
  1330.         if (bconstat(dev)) {
  1331.             return 1;
  1332.         }
  1333.         if (tty) {
  1334.         /* avoid collisions with other processes */
  1335.             if (!tty->rsel)
  1336.                 tty->rsel = p;
  1337.         }
  1338.         return 0;
  1339.     } else if (mode == O_WRONLY) {
  1340.         return 1;
  1341.     }
  1342.     /* default -- we don't know this mode, return 0 */
  1343.     return 0;
  1344. }
  1345.  
  1346. static void ARGS_ON_STACK 
  1347. screen_unselect(f, p, mode)
  1348.     FILEPTR *f;
  1349.     long p;
  1350.     int mode;
  1351. {
  1352.     struct tty *tty = (struct tty *)f->devinfo;
  1353.  
  1354.     if (tty) {
  1355.         if (mode == O_RDONLY && tty->rsel == p)
  1356.             tty->rsel = 0;
  1357.         else if (mode == O_WRONLY && tty->wsel == p)
  1358.             tty->wsel = 0;
  1359.     }
  1360. }
  1361.  
  1362. #endif /* FASTTEXT */
  1363.