home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / VOGLE.ZIP / VOGLE / DRIVERS / NEXT.C < prev    next >
Text File  |  2000-02-11  |  12KB  |  572 lines

  1. /*
  2.  * VOGL/VOGLE driver for NeXTStep.
  3.  * shamelessly hacked from X11 driver 9/91 by
  4.  *
  5.  * Patrick J. Flynn
  6.  * School of EECS
  7.  * Washington State University
  8.  * Pullman, WA 99164-2752 USA cha cha cha
  9.  * flynn@eecs.wsu.edu
  10.  *
  11.  * modified 9/22/91 to use NeXToid defaults (owner: "VOGL") for
  12.  *
  13.  * + preferred small & large font names/styles/sizes:
  14.  *    `SmallFont' `LargeFont'
  15.  *
  16.  *   If no defaults are present, SmallFont is "Ohlfs 9.0" and
  17.  *                               LargeFont is "Ohlfs 18.0"
  18.  *
  19.  *   The space in the font string is significant (see NeXT_font below)
  20.  *
  21.  * + window size & placement: `WindowX' `WindowY'
  22.  *                            `WindowW' `WindowH'
  23.  * 
  24.  * If no defaults are present, the window is anchored (LL) at (10,10)
  25.  * and is 792 pixels wide & high.  If the user has set the preferred
  26.  * position & size using the VOGL prefXXX() calls, they override the
  27.  * defaults.
  28.  *
  29.  * THIS CODE HAS ONLY BEEN TESTED ON A DOUBLE-HEADED CUBE (2 bit + ND)
  30.  * There are a couple of color-screen-centrisms and 24-bit-centrisms in
  31.  * the code, but NextStep is pretty good about drawing as good as it
  32.  * can on the available hardware.
  33.  *
  34.  */
  35.  
  36. /*
  37.  * set VOGLE if this is really for the VOGLE library.
  38.  */
  39. #define VOGLE 1
  40.  
  41. #include <stdio.h>
  42. #include <math.h>
  43. #include <strings.h> /* strfoo() */
  44.  
  45. #ifdef VOGLE
  46. #include "vogle.h"
  47. #else
  48. #include "vogl.h"
  49. #endif
  50.  
  51. #import <appkit/Application.h> /* [NXApp colorScreen] */
  52. #import <appkit/Window.h>
  53. #import <appkit/View.h>
  54. #import <appkit/Font.h>
  55. #import <dpsclient/wraps.h>
  56. #import <dpsclient/event.h>
  57. #import <appkit/color.h>
  58. #import <appkit/graphics.h>
  59. #import <appkit/nextstd.h>
  60. #import <appkit/NXImage.h>     /* double buffer */
  61. #import <appkit/afm.h>         /* hack to get metrics */
  62. #import <appkit/defaults.h>
  63.  
  64. #define    CMAPSIZE    4096   /* perhaps we'll go RGBmode someday. */
  65.  
  66. Window *winder;
  67. View *view;
  68. Font *phont;
  69. NXFontMetrics *fm;
  70. NXImage *backbuf = nil;
  71. NXColor colormap[CMAPSIZE]; /* yeah, I know it's ugly. */
  72. int back_used;
  73.  
  74. id drawable; /* the thing we're drawing in (a View or an NXImage) */
  75.  
  76. /*
  77.  * NeXT_init()
  78.  * initializes the NeXT display.
  79.  */
  80. NeXT_init()
  81. {
  82.   int x0,y0,xs,ys;
  83.   NXRect r;
  84.   char name[80];
  85.   const char *ptr;
  86.  
  87.   NXApp = [Application new];
  88.   getprefposandsize(&x0,&y0,&xs,&ys);
  89.  
  90.   if (x0<0) {
  91. #ifdef VOGLE
  92.     ptr=NXReadDefault("VOGLE","WindowX");
  93. #else
  94.     ptr=NXReadDefault("VOGL","WindowX");
  95. #endif
  96.     if (!ptr)
  97.       x0=10;
  98.     else
  99.       if (sscanf(ptr,"%d",&x0) != 1) x0=10;
  100.     };
  101.  
  102.   if (y0<0) {
  103. #ifdef VOGLE
  104.     ptr=NXReadDefault("VOGLE","WindowY");
  105. #else
  106.     ptr=NXReadDefault("VOGL","WindowY");
  107. #endif
  108.     if (!ptr)
  109.       y0=10;
  110.     else 
  111.       if (sscanf(ptr,"%d",&y0) != 1) y0=10;
  112.     };
  113.   
  114.   if (xs<0) {
  115. #ifdef VOGLE
  116.     ptr=NXReadDefault("VOGLE","WindowW");
  117. #else
  118.     ptr=NXReadDefault("VOGL","WindowW");
  119. #endif
  120.     if (!ptr)
  121.       xs=792;
  122.     else
  123.       if (sscanf(ptr,"%d",&xs) != 1) xs=792;
  124.     };
  125.   
  126.   if (ys<0) {
  127. #ifdef VOGLE
  128.     ptr=NXReadDefault("VOGLE","WindowH");
  129. #else
  130.     ptr=NXReadDefault("VOGL","WindowH");
  131. #endif
  132.     if (!ptr)
  133.       ys=792;
  134.     else
  135.       if (sscanf(ptr,"%d",&ys) != 1) ys=792;
  136.     };
  137.   
  138.   NXSetRect(&r,x0,y0,xs,ys);
  139.   winder = [[Window alloc] initContent:&r
  140.                                  style:NX_TITLEDSTYLE
  141.                                backing:NX_RETAINED
  142.                             buttonMask:0
  143.                                  defer:NO
  144.                                 screen:[NXApp colorScreen]];
  145.   [winder setDepthLimit:NX_TwentyFourBitRGBDepth];
  146.   vdevice.depth = 24;
  147.   colormap[0]=NX_COLORBLACK;
  148.   colormap[1]=NX_COLORRED;
  149.   colormap[2]=NX_COLORGREEN;
  150.   colormap[3]=NX_COLORYELLOW;
  151.   colormap[4]=NX_COLORBLUE;
  152.   colormap[5]=NX_COLORMAGENTA;
  153.   colormap[6]=NX_COLORCYAN;
  154.   colormap[7]=NX_COLORWHITE;
  155.  
  156. #ifdef VOGLE
  157.     sprintf(name, "vogle %d", getpid());
  158.     [winder setTitle:name];
  159. #else
  160.   if (!vdevice.wintitle) {
  161.     sprintf(name, "vogl %d", getpid());
  162.     [winder setTitle:name];
  163.     }
  164.   else {
  165.     [winder setTitle:vdevice.wintitle];
  166.     };
  167. #endif
  168.  
  169.   drawable = view = [winder contentView];
  170.  
  171.   phont = nil;
  172.  
  173.   vdevice.sizeX = vdevice.sizeY = MIN(xs,ys) - 1;
  174.   vdevice.sizeSx = xs;
  175.   vdevice.sizeSy = ys;
  176.   back_used = 0;
  177.   [[winder makeKeyAndOrderFront:0] display];
  178.   [drawable lockFocus];
  179.   return(1);
  180. }
  181.  
  182. /*
  183.  * NeXT_exit
  184.  *
  185.  *    cleans up before returning the window to normal.
  186.  */
  187. NeXT_exit()
  188. {
  189.   [winder free];
  190.   if (backbuf) [backbuf free];
  191.   [NXApp free];
  192.   return(1);
  193. }
  194.  
  195. /*
  196.  * NeXT_draw
  197.  *
  198.  *    draws a line from the current graphics position to (x, y).
  199.  *
  200.  */
  201. NeXT_draw(x, y)
  202.   int    x, y;
  203. {
  204.   PSsetlinewidth(0.0);
  205.   PSnewpath();
  206.   PSmoveto(vdevice.cpVx,vdevice.cpVy);
  207.   PSlineto(x,y);
  208.   PSstroke();
  209.   if (vdevice.sync)
  210.       NXPing();
  211. }
  212.  
  213. /*
  214.  * NeXT_getkey
  215.  *
  216.  *    grab a character from the keyboard - blocks until one is there.
  217.  */
  218. int
  219. NeXT_getkey()
  220. {
  221.   NXEvent e;
  222.   NXEvent *ee = NXGetOrPeekEvent(DPSGetCurrentContext(),&e,
  223.                                  NX_KEYDOWNMASK,NX_FOREVER,NX_BASETHRESHOLD,0);
  224.   if (ee == NULL) fprintf(stderr,"error: NeXT_getKey failed.\n");
  225.   return ee->data.key.charCode;
  226. }
  227.  
  228. /*
  229.  * NeXT_checkkey
  230.  *
  231.  *    Check if there has been a keyboard key pressed.
  232.  *    and return it if so.
  233.  */
  234. int
  235. NeXT_checkkey()
  236. {
  237.   NXEvent e;
  238.   NXEvent *ee = NXGetOrPeekEvent(DPSGetCurrentContext(),&e,
  239.                                  NX_KEYDOWNMASK,0.0,NX_BASETHRESHOLD,0);
  240.   if (ee == NULL) return 0;
  241.   return ee->data.key.charCode;
  242. }
  243.  
  244. /*
  245.  * NeXT_locator
  246.  *
  247.  * return the window location of the cursor, plus which mouse button,
  248.  * if any, is been pressed.
  249.  * 
  250.  * the right mouse button is the LSB.  There is no middle button on a NeXT
  251.  * so the 2LSB is always 0.  The left mouse button is the 3LSB.
  252.  */
  253. int
  254. NeXT_locator(wx, wy)
  255.     int    *wx, *wy;
  256. {
  257.   int msk=0,flg;
  258.   NXPoint p;
  259.   [winder getMouseLocation:&p];
  260.   [view convertPoint:&p fromView:nil];
  261.   *wx = p.x;
  262.   *wy = p.y;
  263.   PSbuttondown(&flg);
  264.   if (flg) msk=4;
  265.   PSrightbuttondown(&flg);
  266.   if (flg) msk+=1;
  267.   return msk;
  268. }
  269.  
  270. #ifdef VOGLE
  271. /*
  272.  * NeXT_clear
  273.  *
  274.  * Clear the screen (or current buffer )to current colour
  275.  */
  276. NeXT_clear()
  277. {
  278.   NXRect r;
  279.   [view getBounds:&r];
  280.   NXRectFill(&r);
  281.   if (vdevice.sync)
  282.       NXPing();
  283. }
  284.  
  285. #else
  286.  
  287. /*
  288.  * NeXT_clear
  289.  *
  290.  * Clear the viewport (or current buffer )to current colour
  291.  */
  292. NeXT_clear()
  293. {
  294.   NXRect r;
  295.   float w=vdevice.maxVx - vdevice.minVx;
  296.   float h=vdevice.maxVy - vdevice.minVy;
  297.   NXSetRect(&r,vdevice.minVx,vdevice.minVy,w,h);
  298.   [view getBounds:&r];
  299.   NXRectFill(&r);
  300.   if (vdevice.sync)
  301.       NXPing();
  302. }
  303.  
  304. #endif
  305.  
  306. /*
  307.  * NeXT_color
  308.  *
  309.  *    set the current drawing color index.
  310.  */
  311. NeXT_color(ind)
  312.         int    ind;
  313. {
  314.   NXSetColor(colormap[ind]);
  315. }
  316.  
  317. /*
  318.  * NeXT_mapcolor
  319.  *
  320.  *    change index i in the color map to the appropriate r, g, b, value.
  321.  */
  322. NeXT_mapcolor(i, r, g, b)
  323.     int    i;
  324.     int    r, g, b;
  325. {
  326.   if (i >= CMAPSIZE) return(-1);
  327.   colormap[i]=NXConvertRGBToColor(1.0*r/255.0,1.0*g/255.0,1.0*b/255.0);
  328. }
  329.  
  330. /*
  331.  * NeXT_font
  332.  *
  333.  *   Set up a hardware font. Return 1 on success 0 otherwise.
  334.  *
  335.  * This is system-dependent.  I assume that the fontfile parameter
  336.  * has the font family name followed by a blank, followed by the size 
  337.  * in points, e.g. "Ohlfs 384.7", "Helvetica-BoldOblique 1.0".
  338.  * Note that the size can be floating-point.
  339.  *
  340.  */
  341. char *strdup(const char *c)  /* ugly blech yech */
  342. {
  343.   char *d=malloc(1+strlen(c));
  344.   bcopy(c,d,1+strlen(c));
  345.   return d;
  346. }
  347.  
  348. /* input: NS = "Name size", i.e. "Ohlfs 32.9".
  349.  * output: *s = 32.9, return value = "Ohlfs";
  350.  * returns NULL if string doesn't have both name and size.
  351.  */
  352. char *_getFontNameNSize(const char *ns,float *s)
  353. {
  354.   char *p,*q;
  355.   if (!ns) return 0;
  356.   p=strdup(ns); /* barf */
  357.   q=index(p,' ');
  358.   if (!q) return 0;
  359.   *q++ = '\0'; /* null-terminate name */
  360.   if (sscanf(q,"%f",s) != 1) { free(p); return 0;};
  361.   return p;
  362. }
  363.   
  364.   
  365. NeXT_font(fontfile)
  366.         char    *fontfile;
  367. {
  368.   char *name;
  369.   float size;
  370.   Font *newfont;
  371.   if (!strcmp(fontfile,"small")) {
  372. #ifdef VOGLE
  373.     name=_getFontNameNSize(NXReadDefault("VOGLE","SmallFont"),&size);
  374. #else
  375.     name=_getFontNameNSize(NXReadDefault("VOGL","SmallFont"),&size);
  376. #endif
  377.     if (!name) { name=strdup("Ohlfs"); size=9.0; };
  378.     }
  379.   else if (!strcmp(fontfile,"large")) {
  380. #ifdef VOGLE
  381.     name=_getFontNameNSize(NXReadDefault("VOGLE","LargeFont"),&size);
  382. #else
  383.     name=_getFontNameNSize(NXReadDefault("VOGL","LargeFont"),&size);
  384. #endif
  385.     if (!name) { name=strdup("Ohlfs"); size=18.0; };
  386.     }
  387.   else {
  388.     name=_getFontNameNSize((const char *)fontfile,&size);
  389.     if (!name) { name=strdup("Ohlfs"); size=9.0; };
  390.     };
  391.   newfont = [Font newFont:name size:size matrix:NX_IDENTITYMATRIX];
  392.   free(name);
  393.   if (newfont) {
  394.     NXFontMetrics *fm = [newfont metrics];
  395.     int i;
  396.     float wmax=0.0;
  397.     [phont free];
  398.     phont = newfont;
  399.     [phont set];
  400.  
  401.     /* set hheight and hwidth for hardware fonts.  The scale factor
  402.        is apparently equal to the point size.  It isn't well-documented. */
  403.  
  404.     vdevice.hheight=size*(fm->ascender-fm->descender);
  405.  
  406.     /* with this li'l loop we can handle var-width fonts but they look
  407.        ugly. Stick to Courier & Ohlfs if you can. */
  408.     for(i=0;i<MIN(fm->widthsLength,256);i++) {
  409.       float w=fm->widths[i];
  410.       if (w>wmax) wmax=w;
  411.       };
  412.     vdevice.hwidth=size*wmax;
  413.     return 1;
  414.     }
  415.   else
  416.     return 0;
  417. }
  418.  
  419. /* 
  420.  * NeXT_char (outputs one char)
  421.  */
  422. NeXT_char(c)
  423.     char    c;
  424. {
  425.   char    s[2];
  426.  
  427.   s[0] = c; s[1]='\0';
  428.   PSmoveto(vdevice.cpVx,vdevice.cpVy);
  429.   PSshow(s);
  430.   if (vdevice.sync)
  431.       NXPing();
  432. }
  433.  
  434. /*
  435.  * NeXT_string
  436.  *
  437.  *    Display a string at the current drawing position.
  438.  */
  439. NeXT_string(s)
  440.         char    s[];
  441. {
  442.   PSmoveto(vdevice.cpVx,vdevice.cpVy);
  443.   PSshow(s);
  444.   NXPing();
  445. }
  446.  
  447. /*
  448.  * NeXT_fill
  449.  *
  450.  *    fill a polygon
  451.  */
  452. NeXT_fill(n, x, y)
  453.     int    n, x[], y[];
  454. {
  455.   int    i;
  456.   PSnewpath();
  457.   PSmoveto(x[0],y[0]);
  458.   for(i=1;i<n;i++) PSlineto(x[i],y[i]);
  459.   PSclosepath();
  460.   PSfill();
  461.   if (vdevice.sync)
  462.       NXPing();
  463. }
  464.  
  465. /*
  466.  * NeXT_backbuf
  467.  *
  468.  *    Set up double buffering by allocating the back buffer and
  469.  *    setting drawing into it.
  470.  */
  471. NeXT_backbuf()
  472. {
  473.   NXRect r;
  474.   [drawable unlockFocus];
  475.   [view getBounds:&r];
  476.   backbuf = [[NXImage alloc] initSize:&r.size];
  477.   if (![backbuf useCacheWithDepth:NX_TwentyFourBitRGBDepth]) {
  478.     fprintf(stderr,"couldn't create backing buffer.\n");
  479.     return 0;
  480.     };
  481.   drawable = backbuf;
  482.   [drawable lockFocus];
  483.   back_used = 1;
  484.   return(1);
  485. }
  486.  
  487. /*
  488.  * NeXT_swapbuf
  489.  *
  490.  *    Swap the back and front buffers. (Really, just copy the
  491.  *    back buffer to the screen).
  492.  */
  493. NeXT_swapbuf()
  494. {
  495.   NXPoint origin = {0,0};
  496.   [drawable unlockFocus];
  497.   [view lockFocus];
  498.   [backbuf composite:NX_COPY toPoint:&origin];
  499.   [winder flushWindow];
  500.   [view unlockFocus];
  501.   [drawable lockFocus];
  502. }
  503.  
  504. /*
  505.  * NeXT_frontbuf
  506.  *
  507.  *    Make sure we draw to the screen.
  508.  */
  509. NeXT_frontbuf()
  510. {
  511.   [drawable unlockFocus];
  512.   drawable = view;
  513.   [drawable lockFocus];
  514. }
  515.  
  516. /*
  517.  * Syncronise the display with what we think has been sent to it...
  518.  */
  519. NeXT_sync()
  520. {
  521.     NXPing();
  522. }
  523.  
  524. NeXT_setlw(w)
  525.     int     w;
  526. {
  527.     if (w == 1)
  528.         PSsetlinewidth(2.0);
  529.     else
  530.         PSsetlinewidth(0.0);
  531. }
  532.  
  533. /*
  534.  * the device entry
  535.  */
  536. static DevEntry NeXTdev = {
  537.     "NeXT",
  538.     "small",
  539.     "large",
  540.     NeXT_backbuf,
  541.     NeXT_char,
  542.     NeXT_checkkey,
  543.     NeXT_clear,
  544.     NeXT_color,
  545.     NeXT_draw,
  546.     NeXT_exit,
  547.     NeXT_fill,
  548.     NeXT_font,
  549.     NeXT_frontbuf,
  550.     NeXT_getkey,
  551.     NeXT_init,
  552.     NeXT_locator,
  553.     NeXT_mapcolor,
  554. #ifndef VOGLE
  555.     noop,
  556. #endif
  557.     NeXT_setlw,
  558.     NeXT_string,
  559.     NeXT_swapbuf, 
  560.     NeXT_sync
  561. };
  562.  
  563. /*
  564.  * _NeXT_devcpy
  565.  *
  566.  *    copy the NeXT device into vdevice.dev.
  567.  */
  568. _NeXT_devcpy()
  569. {
  570.     vdevice.dev = NeXTdev;
  571. }
  572.