home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / mint / mint095s / fasttext.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-03  |  21.2 KB  |  1,154 lines

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