home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / fermiVogle.tar.Z / fermiVogle.tar / devel / drivers / sun.c < prev    next >
C/C++ Source or Header  |  1996-02-07  |  17KB  |  967 lines

  1.  
  2. /*
  3.  * Vogl/Vogle driver for Sun using sunview.
  4.  *
  5.  */
  6. /*
  7.  * define VOGLE for VOGLE library or leave blank for VOGL library
  8.  */
  9. #define VOGLE 1
  10.  
  11. #include <stdio.h>
  12.  
  13. #include <suntool/sunview.h>
  14. #include <suntool/canvas.h>
  15. #include <fcntl.h>
  16. #include <errno.h>
  17.  
  18. #ifdef SUN_3_5
  19. #define event_action    event_id
  20. #endif
  21.  
  22. #ifdef VOGLE
  23. #include "vogle.h"
  24. #else
  25. #include "vogl.h"
  26. #endif
  27.  
  28. #define    CMAPSIZE    256
  29. #define    STDFONTDIR    "/usr/lib/fonts/fixedwidthfonts/"
  30.  
  31. #define MIN(x,y)    ((x) < (y) ? (x) : (y))
  32.  
  33. #define OP_WHITE    (PIX_SRC | PIX_COLOR(7) | PIX_DONTCLIP)
  34. #define OP_BLACK    (PIX_SRC | PIX_COLOR(0) | PIX_DONTCLIP)
  35. #define COL_WHITE    7
  36. #define COL_BLACK    0
  37.  
  38. static Pixwin    *pw_tmp, *pw;
  39.  
  40. #ifdef BASE_COL_SET
  41. static Pixwin    *pw0;
  42. #endif
  43.  
  44. static Pixrect    *backb;
  45. static Pixfont    *font_id;
  46. static int    wfd, blanket_win;
  47. static int    oldflags;
  48. static int    pwfd, h, w;
  49. static int    colour;
  50. static Rect    wrect;
  51.  
  52. static char    use_sunview_canvas = 0;
  53.  
  54. #define    DASHED        1
  55. #define    FATLINES    2
  56. static unsigned char    lineflags = 0;
  57.  
  58. static Pr_brush    brush = {1};
  59. static Pr_texture    *t = (Pr_texture *)NULL;
  60. static Pr_texture    tex = {
  61.                 (short *)NULL,    
  62.                 0,
  63.                 {1, 1, 1, 0},
  64.                 0,
  65.             };
  66.  
  67. /*
  68.  * default colour map
  69.  */
  70.  
  71. static int    colnum = 8;
  72. static u_char   red[CMAPSIZE] = {
  73.             0, 255, 0, 255, 0, 255, 0, 255, 0,
  74.         },
  75.         green[CMAPSIZE] = {
  76.             0, 0, 255, 255, 0, 0, 255, 255, 0,
  77.         },
  78.         blue[CMAPSIZE] = {
  79.             0, 0, 0, 0, 255, 255, 255, 255, 0,
  80.         };
  81.  
  82. static void redisplay(void);
  83. static int vo_sunview_canvas(Canvas canvas, int cw, int ch);
  84. static int SUN_init(void);
  85. static int SUN_exit(void);
  86. static void SUN_draw(int x, int y);
  87. static int SUN_getkey(void);
  88. static int SUN_checkkey(void);
  89. static int SUN_locator(int *wx, int *wy);
  90. #ifdef VOGLE
  91. static void SUN_clear(void);
  92. #else
  93. static void SUN_clear(void);
  94. #endif
  95. static void SUN_color(int ind);
  96. static void SUN_mapcolor(int i, int r, int g, int b);
  97. static int SUN_font(char *fontfile);
  98. static void SUN_char(char c);
  99. static void SUN_string(char s[]);
  100. static void SUN_fill(int n, int x[], int y[]);
  101. static int SUN_backb(void);
  102. static int SUN_swapb(void);
  103. static void SUN_frontb(void);
  104. static void SUN_sync(void);
  105. static void SUN_setls(int lss);
  106. #ifndef VOGLE
  107. static void SUN_setlw(int lw);
  108. #else
  109. static void SUN_setlw(int lw);
  110. #endif
  111.  
  112. /*
  113.  * redisplay
  114.  *
  115.  *    redisplay the window.
  116.  */
  117. static void
  118. redisplay(void)
  119. {
  120.     pw_damaged(pw);
  121.  
  122.     pw_repairretained(pw);
  123.  
  124.     pw_donedamaged(pw);
  125. }
  126.  
  127. /*
  128.  * To be called from a resize procedure from withing sunview
  129.  */
  130. void
  131. vo_sunview_canvas_size(int sw, int sh)
  132. {
  133.     w = sw;
  134.         h = sh;
  135.  
  136.         vdevice.sizeX = vdevice.sizeY = MIN(h, w);
  137.         vdevice.sizeSx = w;
  138.         vdevice.sizeSy = h;
  139.  
  140.     if (pw->pw_prretained) {
  141.         mem_destroy(pw->pw_prretained);
  142.         backb = pw->pw_prretained = mem_create(w, h, vdevice.depth);
  143.     }
  144. }
  145.  
  146. /*
  147.  * vo_sunview_canvas
  148.  *
  149.  *     Tells VOGLE/VOGL to use a supplied sunview pixwin
  150.  */
  151. static int
  152. vo_sunview_canvas(Canvas canvas, int cw, int ch)
  153.     Canvas    canvas;
  154.     int    cw, ch;
  155. {
  156.     pw = canvas_pixwin(canvas);
  157.     use_sunview_canvas = 1;
  158.  
  159.     w = cw;
  160.     h = ch;
  161.  
  162.     vdevice.sizeX = vdevice.sizeY = MIN(h, w);
  163.     vdevice.sizeSx = w;
  164.     vdevice.sizeSy = h;
  165.  
  166.     vdevice.depth = pw->pw_pixrect->pr_depth;
  167.     if (!pw->pw_prretained)    /* Make us retained */
  168.         backb = pw->pw_prretained = mem_create(w, h, vdevice.depth);
  169.  
  170.     /* 
  171.      *  Set up the color map.  
  172.      */
  173.  
  174.     if (vdevice.depth > 1) {
  175.         pw_setcmsname(pw, "vogle");
  176.         pw_putcolormap(pw, 0, colnum, red, green, blue);
  177.     }
  178.  
  179.     wfd = (int)window_get(canvas, WIN_FD);
  180.  
  181.     /*
  182.      * Set non-blocking input for window.
  183.     oldflags = fcntl(wfd, F_GETFL, 0);
  184.     if (fcntl(wfd, F_SETFL, FNDELAY) < 0) {
  185.         perror("F_SETFL");
  186.         exit(1);
  187.     }
  188.      */
  189.  
  190.  
  191.     pw_batch_on(pw);
  192.  
  193. #ifndef VOGLE
  194.     vdevice.devname = "sun";
  195. #endif
  196.  
  197.     return(1);
  198. }
  199.  
  200. /*
  201.  * SUN_init
  202.  *
  203.  *    initialises drawing canvas to occupy current window
  204.  */
  205. static int
  206. SUN_init(void)
  207. {
  208.     int        i, prefx, prefy, prefxs, prefys, bw;
  209.     char        name[WIN_NAMESIZE];
  210.     Inputmask    imk, imp;
  211.     int        rootfd;
  212.  
  213.     if (use_sunview_canvas)
  214.         return(1);
  215.  
  216.     pw = (Pixwin *)NULL;
  217.  
  218. #ifdef BASE_COL_SET
  219.     pw0 = pw;
  220. #endif
  221.  
  222.     /*
  223.      * get the gfx win so we have some default sizes to use
  224.      */
  225.     we_getgfxwindow(name);
  226.     pwfd = open(name, 2);
  227.     win_getrect(pwfd, &wrect);
  228.     
  229.         /*
  230.          * Get the input masks of the base window...
  231.          */
  232.         win_get_pick_mask(pwfd, &imp);
  233.         win_get_kbd_mask(pwfd, &imk);
  234.  
  235.  
  236.     /*
  237.      * get a new window (either going to be a blanket window or
  238.      * a window in it's own right)
  239.      */
  240.     if ((wfd = win_getnewwindow()) == -1) {
  241.         fprintf(stderr, "No new windows!\n");
  242.         exit(1);
  243.     }
  244.  
  245.     getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
  246.  
  247.     if (prefx > -1) {
  248.         wrect.r_left = prefx;
  249.         wrect.r_top = prefy;
  250.     }
  251.  
  252.     if (prefxs > -1) {
  253.         wrect.r_width = prefxs;
  254.         wrect.r_height = prefys;
  255.     }
  256.  
  257.     w = wrect.r_width;
  258.     h = wrect.r_height;
  259.  
  260.     bw = 3;
  261.     if (prefx > -1 || prefxs > -1) {
  262.         /*
  263.          * Make room for a 3 pixel border
  264.          */
  265.         if (wrect.r_left <= 2)
  266.             wrect.r_left = 0;
  267.         else
  268.             wrect.r_left -= bw;
  269.  
  270.         if (wrect.r_top <= 2)
  271.             wrect.r_top = 0;
  272.         else
  273.             wrect.r_top -= bw;
  274.  
  275.         wrect.r_width += 2 * bw;
  276.         wrect.r_height += 2 * bw;
  277.  
  278.         win_setrect(wfd, &wrect);
  279.  
  280.         /*
  281.          * get the parent (probably full screen window)
  282.          * so we can size our window to any size we like
  283.          * on the screen.
  284.          */
  285.         we_getparentwindow(name);
  286.         rootfd = open(name, 2);
  287.  
  288.         win_setlink(wfd, WL_PARENT, win_fdtonumber(rootfd));
  289.         win_setlink(wfd, WL_COVERED, WIN_NULLLINK);
  290.         win_insert(wfd);
  291.  
  292.         wmgr_top(wfd, rootfd);
  293.  
  294.         pw = pw_open(wfd);
  295.  
  296. #ifdef BASE_COL_SET
  297.         /*
  298.          * Get the pixrect for the window that we started in
  299.          * so we can set it's colourmap as well
  300.          */
  301.         pw0 = pw_open(pwfd);
  302. #endif
  303.  
  304.         close(rootfd);
  305.         blanket_win = 0;
  306.     } else {
  307.         win_insertblanket(wfd, pwfd);
  308.         pw = pw_region(pw_open(wfd), 0, 0, w, h);
  309.         blanket_win = 1;
  310.     }
  311.  
  312.     /*
  313.      * Set non-blocking input for window.
  314.      */
  315.     oldflags = fcntl(wfd, F_GETFL, 0);
  316.     if (fcntl(wfd, F_SETFL, FNDELAY) < 0) {
  317.         perror("F_SETFL");
  318.         exit(1);
  319.     }
  320.  
  321.     /*
  322.      * Setup the input masks for window.
  323.      */
  324.  
  325.     win_set_kbd_mask(wfd, &imk);
  326.         win_set_pick_mask(wfd, &imp);
  327.  
  328.     vdevice.depth = pw->pw_pixrect->pr_depth;
  329.  
  330.     /* 
  331.      *  Set up the color map.  
  332.      */
  333.  
  334.     if (vdevice.depth > 1) {
  335.         pw_setcmsname(pw, "vogle");
  336.         pw_putcolormap(pw, 0, colnum, red, green, blue);
  337. #ifdef BASE_COL_SET
  338.         if (pw0 != (Pixwin *)NULL) {
  339.             pw_setcmsname(pw0, "vogle");
  340.             pw_putcolormap(pw0, 0, colnum, red, green, blue);
  341.         }
  342. #endif
  343.     }
  344.  
  345.     if (prefx > -1 || prefxs > -1) {
  346.         /*
  347.          * Draw the border...
  348.          */
  349.         int    x0, y0, x1, y1;
  350.  
  351.         x0 = y0 = 0;
  352.         x1 = wrect.r_width - 1;
  353.         y1 = 0;
  354.         pw_vector(pw, x0, y0, x1, y1, OP_WHITE, COL_WHITE);
  355.         pw_vector(pw, x0 + 2, y0 + 2, x1 - 2, y1 + 2, OP_WHITE, COL_WHITE);
  356.         pw_vector(pw, x0 + 1, y0 + 1, x1 - 1, y1 + 1, OP_BLACK, COL_BLACK);
  357.         x0 = x1;
  358.         y0 = y1;
  359.         x1 = x0;
  360.         y1 = wrect.r_height - 1;
  361.         pw_vector(pw, x0, y0, x1, y1, OP_WHITE, COL_WHITE);
  362.         pw_vector(pw, x0 - 2, y0 + 2, x1 - 2, y1 - 2, OP_WHITE, COL_WHITE);
  363.         pw_vector(pw, x0 - 1, y0 + 1, x1 - 1, y1 - 1, OP_BLACK, COL_BLACK);
  364.         x0 = x1;
  365.         y0 = y1;
  366.         x1 = 0;
  367.         y1 = wrect.r_height - 1;
  368.         pw_vector(pw, x0, y0, x1, y1, OP_WHITE, COL_WHITE);
  369.         pw_vector(pw, x0 - 2, y0 - 2, x1 + 2, y1 - 2, OP_WHITE, COL_WHITE);
  370.         pw_vector(pw, x0 - 1, y0 - 1, x1 + 1, y1 - 1, OP_BLACK, COL_BLACK);
  371.         x0 = x1;
  372.         y0 = y1;
  373.         x1 = 0;
  374.         y1 = 0;
  375.         pw_vector(pw, x0, y0, x1, y1, OP_WHITE, COL_WHITE);
  376.         pw_vector(pw, x0 + 2, y0 - 2, x1 + 2, y1 + 2, OP_WHITE, COL_WHITE);
  377.         pw_vector(pw, x0 + 1, y0 - 1, x1 + 1, y1 + 1, OP_BLACK, COL_BLACK);
  378.         pw_tmp = pw;
  379.         pw = pw_region(pw_tmp, 3, 3, w, h);
  380.         pw_close(pw_tmp);
  381.     }
  382.  
  383.  
  384.     backb = pw->pw_prretained = mem_create(w, h, vdevice.depth);
  385.  
  386.     signal(SIGWINCH, redisplay);
  387.  
  388.     /*
  389.      *  Let VOGLE/VOGL know about the window size.
  390.      */
  391.         vdevice.sizeX = vdevice.sizeY = MIN(w, h);
  392.     vdevice.sizeSx = w;
  393.     vdevice.sizeSy = h;
  394.  
  395.     /*
  396.      * Set up batching.....(for speed and "pseudo" double buffering)
  397.      */
  398.     pw_batch_on(pw);
  399.  
  400.     return(1);
  401. }
  402.  
  403. /*
  404.  * SUN_exit
  405.  *
  406.  *    cleans up before returning the window to normal.
  407.  */
  408. static int
  409. SUN_exit(void)
  410. {
  411.     long    nbytes;
  412.     int    i;
  413.     Event    event;
  414.  
  415.     if (use_sunview_canvas)
  416.         return(1);
  417.  
  418.     /*
  419.      * Flush all events for this window.
  420.      *
  421.      * While doing non-blocking input input_readevent returns -1 and
  422.      * errno == EWOULDBLOCK when everything has been read, so if 
  423.      * errno != EWOULDBLOCK then something naughty happened...
  424.      */
  425.     while (input_readevent(wfd, &event) >= 0)
  426.         ;
  427.  
  428.     if (errno != EWOULDBLOCK) {
  429.         perror("SUN_exit(flushing), input_readevent");
  430.         exit();
  431.     }
  432.  
  433.     /*
  434.      * reset wfd to blocking input.
  435.      */
  436.     if (fcntl(wfd, F_SETFL, oldflags) < 0) {
  437.         perror("oldflags, F_SETFL");
  438.         exit(1);
  439.     }
  440.  
  441.     if (blanket_win)
  442.         win_removeblanket(wfd);
  443.     else 
  444.         win_remove(wfd);
  445.  
  446.     signal(SIGWINCH, SIG_DFL);
  447.  
  448.     return(1);
  449. }
  450.  
  451. /*
  452.  * SUN_draw
  453.  *
  454.  *    draws a line from the current graphics position to (x, y).
  455.  *
  456.  * Note: (0, 0) is defined as the top left of the window on a sun (easy
  457.  * to forget).
  458.  */
  459. static void
  460. SUN_draw(int x, int y)
  461. {
  462.     if (!lineflags)    /* If thin and solid */
  463.         pw_vector(pw, vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy, x, vdevice.sizeSy - y, PIX_SRC | PIX_COLOR(colour), colour);
  464.     else    /* Fat and/or dashed */
  465.         pw_line(pw, vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy, x, vdevice.sizeSy - y, &brush, t, PIX_SRC | PIX_COLOR(colour));
  466.  
  467.     if (vdevice.sync)
  468.         pw_show(pw);
  469. }
  470.  
  471. /*
  472.  * SUN_getkey
  473.  *
  474.  *    grab a character from the keyboard.
  475.  */
  476. static int
  477. SUN_getkey(void)
  478. {
  479.     Event    event;
  480.  
  481.     pw_show(pw);
  482.  
  483.     do {
  484.         while ((input_readevent(wfd, &event) < 0) && (errno == EWOULDBLOCK))
  485.         ;    /* Nothing to read - wait for something */
  486.         
  487.     } while (!event_is_ascii(&event));    /* Wait for a key press */
  488.  
  489.     return(event_action(&event));
  490. }
  491.  
  492. /*
  493.  * SUN_checkkey
  494.  *
  495.  *    Check if a keyboard key has been hit. If so return it.
  496.  */
  497. static Event *saved_event;
  498.  
  499. static int
  500. SUN_checkkey(void)
  501. {
  502.     static Event    event;
  503.     
  504.     if(saved_event == &event)
  505.         saved_event = NULL;
  506.  
  507.     if (saved_event && event_is_ascii(saved_event)) {
  508.         Event *tmp = saved_event;
  509.  
  510.         saved_event = NULL;
  511.         return(event_action(tmp));
  512.     }
  513.  
  514.     saved_event = NULL;
  515.  
  516.     if (input_readevent(wfd, &event) < 0) {
  517.         if (errno == EWOULDBLOCK) {
  518.             return(0);
  519.         } else {
  520.             perror("SUN_checkkey, input_readevent");
  521.             exit(1);
  522.         }
  523.     } else if (event_is_ascii(&event))
  524.         return(event_action(&event));
  525.     else
  526.         saved_event = &event;
  527.  
  528.     return(0);
  529. }
  530.         
  531.  
  532. /*
  533.  * SUN_locator
  534.  *
  535.  *    return the window location of the cursor, plus which mouse button,
  536.  * if any, is been pressed.
  537.  */
  538. static int
  539. SUN_locator(int *wx, int *wy)
  540. {
  541.     int    but;
  542.     static Event    event;
  543.     
  544.     if (vdevice.sync)
  545.         pw_show(pw);
  546.  
  547.     but = 0;
  548.  
  549.     *wx = win_get_vuid_value(wfd, LOC_X_ABSOLUTE);
  550.     *wy = (int)vdevice.sizeSy - win_get_vuid_value(wfd, LOC_Y_ABSOLUTE);
  551.  
  552.     /* This used to work under 4.0 but not longer ..... Maybe
  553.      * SUN don't want us to use sunview anymore?
  554.      */
  555.     if (win_get_vuid_value(wfd, BUT(1)))
  556.         but |= 1;
  557.  
  558.     if (win_get_vuid_value(wfd, BUT(2)))
  559.         but |= 2;
  560.  
  561.     if (win_get_vuid_value(wfd, BUT(3)))
  562.         but |= 3;
  563.  
  564.     
  565.     if (use_sunview_canvas)
  566.         return(but);
  567.  
  568.     if (saved_event == &event) /*Don't Re-use a previously rejected event*/
  569.         saved_event = NULL;
  570.  
  571.     if (saved_event && event_is_button(saved_event) && event_is_down(saved_event)) {
  572.         if (event_action(saved_event) == MS_LEFT)
  573.             but |= 1;
  574.         if (event_action(saved_event) == MS_MIDDLE)
  575.             but |= 2;
  576.         if (event_action(saved_event) == MS_RIGHT)
  577.             but |= 4;
  578.  
  579.         saved_event = NULL;
  580.         return(but);
  581.     }
  582.  
  583.  
  584.     if (input_readevent(wfd, &event) < 0) {
  585.         if (errno == EWOULDBLOCK) {
  586.             return(0);
  587.         } else {
  588.             perror("SUN_locator, input_readevent");
  589.             exit(1);
  590.         }
  591.     } else if (event_is_button(&event) && event_is_down(&event)) {
  592.             if (event_action(&event) == MS_LEFT)
  593.                 but |= 1;
  594.             if (event_action(&event) == MS_MIDDLE)
  595.                 but |= 2;
  596.             if (event_action(&event) == MS_RIGHT)
  597.                 but |= 4;
  598.     } else
  599.         saved_event = &event;
  600.  
  601.     return(but);
  602. }
  603.  
  604. #ifdef VOGLE
  605. /*
  606.  * SUN_clear
  607.  *
  608.  *    Clear the screen to current colour
  609.  */
  610. static void
  611. SUN_clear(void)
  612. {
  613.     pw_writebackground(pw, 0, 0, w, h, PIX_SRC | PIX_COLOR(colour) | PIX_DONTCLIP);
  614.  
  615.     if (vdevice.sync)
  616.         pw_show(pw);
  617. }
  618.  
  619. #else
  620.  
  621. /*
  622.  * SUN_clear
  623.  *
  624.  *    Clear the viewport to current colour
  625.  */
  626. static void
  627. SUN_clear(void)
  628. {
  629.         unsigned int    vw = vdevice.maxVx - vdevice.minVx;
  630.         unsigned int    vh = vdevice.maxVy - vdevice.minVy;
  631.  
  632.     pw_writebackground(pw, 
  633.         vdevice.minVx, vdevice.sizeSy - vdevice.maxVy, 
  634.         vw, vh,
  635.         PIX_SRC | PIX_COLOR(colour) | PIX_DONTCLIP
  636.     );
  637.  
  638.     if (vdevice.sync)
  639.         pw_show(pw);
  640. }
  641.  
  642. #endif
  643.  
  644. /*
  645.  * SUN_color
  646.  *
  647.  *    set the current drawing color index.
  648.  */
  649. static void
  650. SUN_color(int ind)
  651. {
  652.     colour = ind;
  653. }
  654.  
  655. /*
  656.  * SUN_mapcolor
  657.  *
  658.  *    change index i in the color map to the appropriate r, g, b, value.
  659.  */
  660. static void
  661. SUN_mapcolor(int i, int r, int g, int b)
  662. {
  663.     int    j;
  664.  
  665.     if (i >= 255 || vdevice.depth == 1)
  666.         return(-1);
  667.  
  668.     if (i >= colnum)
  669.         colnum = i;
  670.  
  671.     red[i] = r;
  672.     green[i] = g;
  673.     blue[i] = b;
  674.  
  675.     red[255] = (u_char)~red[0];
  676.     green[255] = (u_char)~green[0];
  677.     blue[255] = (u_char)~blue[0];
  678.  
  679.     pw_putcolormap(pw, 0, colnum, red, green, blue);
  680. #ifdef BASE_COL_SET
  681.     pw_putcolormap(pw0, 0, colnum, red, green, blue);
  682. #endif
  683. }
  684.     
  685. /*
  686.  * SUN_font
  687.  *
  688.  *   Set up a hardware font. Return 1 on success 0 otherwise.
  689.  *
  690.  */
  691. static int
  692. SUN_font(char *fontfile)
  693. {
  694.     char    name[BUFSIZ];
  695.  
  696.     if (font_id != (Pixfont *)NULL)
  697.         pf_close(font_id);
  698.  
  699.     if ((font_id = pf_open(fontfile)) == NULL)
  700.         if (*fontfile != '/') {
  701.             strcpy(name, STDFONTDIR);
  702.             strcat(name, fontfile);
  703.             if ((font_id = pf_open(name)) == NULL)
  704.                 return(0);
  705.         } else 
  706.             return(0);
  707.  
  708.     vdevice.hheight = font_id->pf_defaultsize.y;
  709.     vdevice.hwidth = font_id->pf_defaultsize.x;
  710.  
  711.     return(1);
  712. }
  713.  
  714. /* 
  715.  * SUN_char
  716.  *
  717.  *     outputs one char - is more complicated for other devices
  718.  */
  719. static void
  720. SUN_char(char c)
  721. {
  722.     char    *s = " ";
  723.  
  724.     s[0] = c;
  725.     pw_ttext(pw, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), PIX_SRC | PIX_COLOR(colour), font_id, s);
  726.  
  727.     if (vdevice.sync)
  728.         pw_show(pw);
  729. }
  730.  
  731. /*
  732.  * SUN_string
  733.  *
  734.  *    Display a string at the current drawing position.
  735.  */
  736. static void
  737. SUN_string(char s[])
  738. {
  739.     pw_ttext(pw, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), PIX_SRC | PIX_COLOR(colour), font_id, s);
  740.  
  741.     if (vdevice.sync)
  742.         pw_show(pw);
  743. }
  744.  
  745. /*
  746.  * SUN_fill
  747.  *
  748.  *    fill a polygon
  749.  */
  750. static void
  751. SUN_fill(int n, int x[], int y[])
  752. {
  753.     struct    pr_pos    vlist[128];
  754.     int    i, npnts;
  755.  
  756.     if (n > 128)
  757.         verror("vogle: more than 128 points in a polygon");
  758.  
  759.     npnts = n;
  760.  
  761.     for (i = 0; i < n; i++) {
  762.         vlist[i].x = x[i];
  763.         vlist[i].y = vdevice.sizeSy - y[i];
  764.     }
  765.  
  766.     pw_polygon_2(pw, 0, 0, 1, &npnts, vlist, PIX_SRC | PIX_COLOR(colour) | PIX_DONTCLIP, (Pixwin *)NULL, 0, 0);
  767.  
  768.     vdevice.cpVx = x[n-1];
  769.     vdevice.cpVy = y[n-1];
  770.  
  771. /*
  772.     if (vdevice.sync)
  773.         pw_show(pw);
  774. */
  775. }
  776.  
  777. /*
  778.  * SUN_backb
  779.  *
  780.  *    swap to memory only drawing (backbuffer) - a little slow but it
  781.  * works on everything. 
  782.  */
  783. static int
  784. SUN_backb(void)
  785. {
  786.     /*
  787.      * Batching is already on....
  788.      */
  789.     return(0);
  790. }
  791.  
  792. /*
  793.  * SUN_swapb
  794.  *
  795.  *    swap the front and back buffers.
  796.  */
  797. static int
  798. SUN_swapb(void)
  799. {
  800.     if (vdevice.inbackbuffer)
  801.         pw_show(pw);
  802.  
  803.     return(0);
  804. }
  805.  
  806. /*
  807.  * SUN_frontb
  808.  *
  809.  *    draw in the front buffer
  810.  */
  811. static void
  812. SUN_frontb(void)
  813. {
  814.     /*
  815.      * Make it visible anyway....
  816.      */
  817.     pw_show(pw);
  818. }
  819.  
  820. /*
  821.  * SUN_sync
  822.  *
  823.  *    Syncronise the display with what we thing has been output
  824.  */
  825. static void
  826. SUN_sync(void)
  827. {
  828.     pw_show(pw);
  829. }
  830.  
  831. /*
  832.  * SUN_setls
  833.  *
  834.  *    Set the line style....
  835.  */
  836. static void
  837. SUN_setls(int lss)
  838. {
  839.     
  840.     unsigned ls = lss;
  841.     static short    dashes[17];
  842.  
  843.     int    i, n, a, b, offset;
  844.  
  845.     if (ls == 0xffff) {
  846.         lineflags &= ~DASHED;
  847.         t = (Pr_texture *)NULL;
  848.         return;
  849.     }
  850.  
  851.     lineflags |= DASHED;
  852.  
  853.     for (i = 0; i < 16; i++)
  854.         dashes[i] = 0;
  855.  
  856.     for (i = 0; i < 16; i++)    /* Over 16 bits */
  857.         if ((ls & (1 << i)))
  858.             break;
  859.  
  860.     offset = i;
  861.  
  862. #define    ON    1
  863. #define    OFF    0
  864.         
  865.     a = b = OFF;
  866.     if (ls & (1 << 0))
  867.         a = b = ON;
  868.  
  869.     n = 0;
  870.     for (i = 0; i < 16; i++) {    /* Over 16 bits */
  871.         if (ls & (1 << i))
  872.             a = ON;
  873.         else
  874.             a = OFF;
  875.  
  876.         if (a != b) {
  877.             b = a;
  878.             n++;
  879.         }
  880.         dashes[n]++;
  881.     }
  882.     n++;
  883.     dashes[n] = 0;
  884.  
  885.     tex.pattern = &dashes[0];
  886.     tex.offset = offset;
  887.     t = &tex;
  888. }
  889.  
  890. #ifndef VOGLE
  891. /*
  892.  * SUN_setlw
  893.  *
  894.  *    Set the line style....
  895.  */
  896. static void
  897. SUN_setlw(int lw)
  898. {
  899.     if (lw > 1) {
  900.         lineflags |= FATLINES;
  901.         brush.width = lw;
  902.     } else
  903.         lineflags &= ~FATLINES;
  904. }
  905.  
  906. #else
  907. /*
  908.  * SUN_setlw
  909.  *
  910.  *    Set the line style....
  911.  */
  912. static void
  913. SUN_setlw(int lw)
  914. {
  915.     if (lw == 1) {
  916.         lineflags |= FATLINES;
  917.         brush.width = 3;
  918.     } else {
  919.         lineflags &= ~FATLINES;
  920.         brush.width = 1;
  921.     }
  922. }
  923.  
  924. #endif
  925.  
  926. /*
  927.  * the device entry
  928.  */
  929. static DevEntry sundev = {
  930.     "sun",
  931.     "screen.b.16",
  932.     "screen.b.12",
  933.     SUN_backb,
  934.     SUN_char,
  935.     SUN_checkkey,
  936.     SUN_clear,
  937.     SUN_color,
  938.     SUN_draw,
  939.     SUN_exit,
  940.     SUN_fill,
  941.     SUN_font,
  942.     SUN_frontb,
  943.     SUN_getkey,
  944.     SUN_init,
  945.     SUN_locator,
  946.     SUN_mapcolor,
  947. #ifndef VOGLE
  948.     SUN_setls,
  949. #endif
  950.     SUN_setlw,
  951.     SUN_string,
  952.     SUN_swapb,
  953.     SUN_sync
  954. };
  955.  
  956. /*
  957.  * _SUN_devcpy
  958.  *
  959.  *    copy the sun device into vdevice.dev.
  960.  */
  961. void
  962. _SUN_devcpy(void)
  963. {
  964.     vdevice.dev = sundev;
  965. }
  966.  
  967.