home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / fermiVogle.tar.Z / fermiVogle.tar / devel / drivers / NeXT.c < prev    next >
Text File  |  1996-02-07  |  12KB  |  608 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. static int NeXT_init(void);
  77. static int NeXT_exit(void);
  78. static void NeXT_draw(int x, int y);
  79. static int NeXT_getkey(void);
  80. static int NeXT_checkkey(void);
  81. static int NeXT_locator(int *wx, int *wy);
  82. #ifdef VOGLE
  83. static void NeXT_clear(void);
  84. #else
  85. static void NeXT_clear(void);
  86. #endif
  87. static void NeXT_color(int ind);
  88. static void NeXT_mapcolor(int i, int r, int g, int b);
  89. static char *strdup(const char *c);
  90. static char *_getFontNameNSize(const char *ns,float *s);
  91. static int NeXT_font(char *fontfile);
  92. static void NeXT_char(char c);
  93. static void NeXT_string(char s[]);
  94. static void NeXT_fill(int n, int x[], int y[]);
  95. static int NeXT_backbuf(void);
  96. static void NeXT_swapbuf(void);
  97. static void NeXT_frontbuf(void);
  98. static void NeXT_sync(void);
  99. static void NeXT_setlw(int w);
  100.  
  101.  
  102. /*
  103.  * NeXT_init()
  104.  * initializes the NeXT display.
  105.  */
  106. static int
  107. NeXT_init(void)
  108. {
  109.   int x0,y0,xs,ys;
  110.   NXRect r;
  111.   char name[80];
  112.   const char *ptr;
  113.  
  114.   NXApp = [Application new];
  115.   getprefposandsize(&x0,&y0,&xs,&ys);
  116.  
  117.   if (x0<0) {
  118. #ifdef VOGLE
  119.     ptr=NXReadDefault("VOGLE","WindowX");
  120. #else
  121.     ptr=NXReadDefault("VOGL","WindowX");
  122. #endif
  123.     if (!ptr)
  124.       x0=10;
  125.     else
  126.       if (sscanf(ptr,"%d",&x0) != 1) x0=10;
  127.     };
  128.  
  129.   if (y0<0) {
  130. #ifdef VOGLE
  131.     ptr=NXReadDefault("VOGLE","WindowY");
  132. #else
  133.     ptr=NXReadDefault("VOGL","WindowY");
  134. #endif
  135.     if (!ptr)
  136.       y0=10;
  137.     else 
  138.       if (sscanf(ptr,"%d",&y0) != 1) y0=10;
  139.     };
  140.   
  141.   if (xs<0) {
  142. #ifdef VOGLE
  143.     ptr=NXReadDefault("VOGLE","WindowW");
  144. #else
  145.     ptr=NXReadDefault("VOGL","WindowW");
  146. #endif
  147.     if (!ptr)
  148.       xs=792;
  149.     else
  150.       if (sscanf(ptr,"%d",&xs) != 1) xs=792;
  151.     };
  152.   
  153.   if (ys<0) {
  154. #ifdef VOGLE
  155.     ptr=NXReadDefault("VOGLE","WindowH");
  156. #else
  157.     ptr=NXReadDefault("VOGL","WindowH");
  158. #endif
  159.     if (!ptr)
  160.       ys=792;
  161.     else
  162.       if (sscanf(ptr,"%d",&ys) != 1) ys=792;
  163.     };
  164.   
  165.   NXSetRect(&r,x0,y0,xs,ys);
  166.   winder = [[Window alloc] initContent:&r
  167.                                  style:NX_TITLEDSTYLE
  168.                                backing:NX_RETAINED
  169.                             buttonMask:0
  170.                                  defer:NO
  171.                                 screen:[NXApp colorScreen]];
  172.   [winder setDepthLimit:NX_TwentyFourBitRGBDepth];
  173.   vdevice.depth = 24;
  174.   colormap[0]=NX_COLORBLACK;
  175.   colormap[1]=NX_COLORRED;
  176.   colormap[2]=NX_COLORGREEN;
  177.   colormap[3]=NX_COLORYELLOW;
  178.   colormap[4]=NX_COLORBLUE;
  179.   colormap[5]=NX_COLORMAGENTA;
  180.   colormap[6]=NX_COLORCYAN;
  181.   colormap[7]=NX_COLORWHITE;
  182.  
  183. #ifdef VOGLE
  184.     sprintf(name, "vogle %d", getpid());
  185.     [winder setTitle:name];
  186. #else
  187.   if (!vdevice.wintitle) {
  188.     sprintf(name, "vogl %d", getpid());
  189.     [winder setTitle:name];
  190.     }
  191.   else {
  192.     [winder setTitle:vdevice.wintitle];
  193.     };
  194. #endif
  195.  
  196.   drawable = view = [winder contentView];
  197.  
  198.   phont = nil;
  199.  
  200.   vdevice.sizeX = vdevice.sizeY = MIN(xs,ys) - 1;
  201.   vdevice.sizeSx = xs;
  202.   vdevice.sizeSy = ys;
  203.   back_used = 0;
  204.   [[winder makeKeyAndOrderFront:0] display];
  205.   [drawable lockFocus];
  206.   return(1);
  207. }
  208.  
  209. /*
  210.  * NeXT_exit
  211.  *
  212.  *    cleans up before returning the window to normal.
  213.  */
  214. static int
  215. NeXT_exit(void)
  216. {
  217.   [winder free];
  218.   if (backbuf) [backbuf free];
  219.   [NXApp free];
  220.   return(1);
  221. }
  222.  
  223. /*
  224.  * NeXT_draw
  225.  *
  226.  *    draws a line from the current graphics position to (x, y).
  227.  *
  228.  */
  229. static void
  230. NeXT_draw(int x, int y)
  231. {
  232.   PSsetlinewidth(0.0);
  233.   PSnewpath();
  234.   PSmoveto(vdevice.cpVx,vdevice.cpVy);
  235.   PSlineto(x,y);
  236.   PSstroke();
  237.   if (vdevice.sync)
  238.       NXPing();
  239. }
  240.  
  241. /*
  242.  * NeXT_getkey
  243.  *
  244.  *    grab a character from the keyboard - blocks until one is there.
  245.  */
  246. static int
  247. NeXT_getkey(void)
  248. {
  249.   NXEvent e;
  250.   NXEvent *ee = NXGetOrPeekEvent(DPSGetCurrentContext(),&e,
  251.                                  NX_KEYDOWNMASK,NX_FOREVER,NX_BASETHRESHOLD,0);
  252.   if (ee == NULL) fprintf(stderr,"error: NeXT_getKey failed.\n");
  253.   return ee->data.key.charCode;
  254. }
  255.  
  256. /*
  257.  * NeXT_checkkey
  258.  *
  259.  *    Check if there has been a keyboard key pressed.
  260.  *    and return it if so.
  261.  */
  262. static int
  263. NeXT_checkkey(void)
  264. {
  265.   NXEvent e;
  266.   NXEvent *ee = NXGetOrPeekEvent(DPSGetCurrentContext(),&e,
  267.                                  NX_KEYDOWNMASK,0.0,NX_BASETHRESHOLD,0);
  268.   if (ee == NULL) return 0;
  269.   return ee->data.key.charCode;
  270. }
  271.  
  272. /*
  273.  * NeXT_locator
  274.  *
  275.  * return the window location of the cursor, plus which mouse button,
  276.  * if any, is been pressed.
  277.  * 
  278.  * the right mouse button is the LSB.  There is no middle button on a NeXT
  279.  * so the 2LSB is always 0.  The left mouse button is the 3LSB.
  280.  */
  281. static int
  282. NeXT_locator(int *wx, int *wy)
  283. {
  284.   int msk=0,flg;
  285.   NXPoint p;
  286.   [winder getMouseLocation:&p];
  287.   [view convertPoint:&p fromView:nil];
  288.   *wx = p.x;
  289.   *wy = p.y;
  290.   PSbuttondown(&flg);
  291.   if (flg) msk=4;
  292.   PSrightbuttondown(&flg);
  293.   if (flg) msk+=1;
  294.   return msk;
  295. }
  296.  
  297. #ifdef VOGLE
  298. /*
  299.  * NeXT_clear
  300.  *
  301.  * Clear the screen (or current buffer )to current colour
  302.  */
  303. static void
  304. NeXT_clear(void)
  305. {
  306.   NXRect r;
  307.   [view getBounds:&r];
  308.   NXRectFill(&r);
  309.   if (vdevice.sync)
  310.       NXPing();
  311. }
  312.  
  313. #else
  314.  
  315. /*
  316.  * NeXT_clear
  317.  *
  318.  * Clear the viewport (or current buffer )to current colour
  319.  */
  320. static void
  321. NeXT_clear(void)
  322. {
  323.   NXRect r;
  324.   float w=vdevice.maxVx - vdevice.minVx;
  325.   float h=vdevice.maxVy - vdevice.minVy;
  326.   NXSetRect(&r,vdevice.minVx,vdevice.minVy,w,h);
  327.   [view getBounds:&r];
  328.   NXRectFill(&r);
  329.   if (vdevice.sync)
  330.       NXPing();
  331. }
  332.  
  333. #endif
  334.  
  335. /*
  336.  * NeXT_color
  337.  *
  338.  *    set the current drawing color index.
  339.  */
  340. static void
  341. NeXT_color(int ind)
  342. {
  343.   NXSetColor(colormap[ind]);
  344. }
  345.  
  346. /*
  347.  * NeXT_mapcolor
  348.  *
  349.  *    change index i in the color map to the appropriate r, g, b, value.
  350.  */
  351. static void
  352. NeXT_mapcolor(int i, int r, int g, int b)
  353. {
  354.   if (i >= CMAPSIZE) return(-1);
  355.   colormap[i]=NXConvertRGBToColor(1.0*r/255.0,1.0*g/255.0,1.0*b/255.0);
  356. }
  357.  
  358. /*
  359.  * NeXT_font
  360.  *
  361.  *   Set up a hardware font. Return 1 on success 0 otherwise.
  362.  *
  363.  * This is system-dependent.  I assume that the fontfile parameter
  364.  * has the font family name followed by a blank, followed by the size 
  365.  * in points, e.g. "Ohlfs 384.7", "Helvetica-BoldOblique 1.0".
  366.  * Note that the size can be floating-point.
  367.  *
  368.  */
  369. static char *
  370. strdup(const char *c)  /* ugly blech yech */
  371. {
  372.   char *d=malloc(1+strlen(c));
  373.   bcopy(c,d,1+strlen(c));
  374.   return d;
  375. }
  376.  
  377. /* input: NS = "Name size", i.e. "Ohlfs 32.9".
  378.  * output: *s = 32.9, return value = "Ohlfs";
  379.  * returns NULL if string doesn't have both name and size.
  380.  */
  381. static char *
  382. _getFontNameNSize(const char *ns,float *s)
  383. {
  384.   char *p,*q;
  385.   if (!ns) return 0;
  386.   p=strdup(ns); /* barf */
  387.   q=index(p,' ');
  388.   if (!q) return 0;
  389.   *q++ = '\0'; /* null-terminate name */
  390.   if (sscanf(q,"%f",s) != 1) { free(p); return 0;};
  391.   return p;
  392. }
  393.   
  394. static int
  395. NeXT_font(char *fontfile)
  396. {
  397.   char *name;
  398.   float size;
  399.   Font *newfont;
  400.   if (!strcmp(fontfile,"small")) {
  401. #ifdef VOGLE
  402.     name=_getFontNameNSize(NXReadDefault("VOGLE","SmallFont"),&size);
  403. #else
  404.     name=_getFontNameNSize(NXReadDefault("VOGL","SmallFont"),&size);
  405. #endif
  406.     if (!name) { name=strdup("Ohlfs"); size=9.0; };
  407.     }
  408.   else if (!strcmp(fontfile,"large")) {
  409. #ifdef VOGLE
  410.     name=_getFontNameNSize(NXReadDefault("VOGLE","LargeFont"),&size);
  411. #else
  412.     name=_getFontNameNSize(NXReadDefault("VOGL","LargeFont"),&size);
  413. #endif
  414.     if (!name) { name=strdup("Ohlfs"); size=18.0; };
  415.     }
  416.   else {
  417.     name=_getFontNameNSize((const char *)fontfile,&size);
  418.     if (!name) { name=strdup("Ohlfs"); size=9.0; };
  419.     };
  420.   newfont = [Font newFont:name size:size matrix:NX_IDENTITYMATRIX];
  421.   free(name);
  422.   if (newfont) {
  423.     NXFontMetrics *fm = [newfont metrics];
  424.     int i;
  425.     float wmax=0.0;
  426.     [phont free];
  427.     phont = newfont;
  428.     [phont set];
  429.  
  430.     /* set hheight and hwidth for hardware fonts.  The scale factor
  431.        is apparently equal to the point size.  It isn't well-documented. */
  432.  
  433.     vdevice.hheight=size*(fm->ascender-fm->descender);
  434.  
  435.     /* with this li'l loop we can handle var-width fonts but they look
  436.        ugly. Stick to Courier & Ohlfs if you can. */
  437.     for(i=0;i<MIN(fm->widthsLength,256);i++) {
  438.       float w=fm->widths[i];
  439.       if (w>wmax) wmax=w;
  440.       };
  441.     vdevice.hwidth=size*wmax;
  442.     return 1;
  443.     }
  444.   else
  445.     return 0;
  446. }
  447.  
  448. /* 
  449.  * NeXT_char (outputs one char)
  450.  */
  451. static void
  452. NeXT_char(char c)
  453. {
  454.   char    s[2];
  455.  
  456.   s[0] = c; s[1]='\0';
  457.   PSmoveto(vdevice.cpVx,vdevice.cpVy);
  458.   PSshow(s);
  459.   if (vdevice.sync)
  460.       NXPing();
  461. }
  462.  
  463. /*
  464.  * NeXT_string
  465.  *
  466.  *    Display a string at the current drawing position.
  467.  */
  468. static void
  469. NeXT_string(char s[])
  470. {
  471.   PSmoveto(vdevice.cpVx,vdevice.cpVy);
  472.   PSshow(s);
  473.   NXPing();
  474. }
  475.  
  476. /*
  477.  * NeXT_fill
  478.  *
  479.  *    fill a polygon
  480.  */
  481. static void
  482. NeXT_fill(int n, int x[], int y[])
  483. {
  484.   int    i;
  485.   PSnewpath();
  486.   PSmoveto(x[0],y[0]);
  487.   for(i=1;i<n;i++) PSlineto(x[i],y[i]);
  488.   PSclosepath();
  489.   PSfill();
  490.   if (vdevice.sync)
  491.       NXPing();
  492. }
  493.  
  494. /*
  495.  * NeXT_backbuf
  496.  *
  497.  *    Set up double buffering by allocating the back buffer and
  498.  *    setting drawing into it.
  499.  */
  500. static int
  501. NeXT_backbuf(void)
  502. {
  503.   NXRect r;
  504.   [drawable unlockFocus];
  505.   [view getBounds:&r];
  506.   backbuf = [[NXImage alloc] initSize:&r.size];
  507.   if (![backbuf useCacheWithDepth:NX_TwentyFourBitRGBDepth]) {
  508.     fprintf(stderr,"couldn't create backing buffer.\n");
  509.     return 0;
  510.     };
  511.   drawable = backbuf;
  512.   [drawable lockFocus];
  513.   back_used = 1;
  514.   return(1);
  515. }
  516.  
  517. /*
  518.  * NeXT_swapbuf
  519.  *
  520.  *    Swap the back and front buffers. (Really, just copy the
  521.  *    back buffer to the screen).
  522.  */
  523. static void
  524. NeXT_swapbuf(void)
  525. {
  526.   NXPoint origin = {0,0};
  527.   [drawable unlockFocus];
  528.   [view lockFocus];
  529.   [backbuf composite:NX_COPY toPoint:&origin];
  530.   [winder flushWindow];
  531.   [view unlockFocus];
  532.   [drawable lockFocus];
  533. }
  534.  
  535. /*
  536.  * NeXT_frontbuf
  537.  *
  538.  *    Make sure we draw to the screen.
  539.  */
  540. static void
  541. NeXT_frontbuf(void)
  542. {
  543.   [drawable unlockFocus];
  544.   drawable = view;
  545.   [drawable lockFocus];
  546. }
  547.  
  548. /*
  549.  * Syncronise the display with what we think has been sent to it...
  550.  */
  551. static void
  552. NeXT_sync(void)
  553. {
  554.     NXPing();
  555. }
  556.  
  557. static void
  558. NeXT_setlw(int w)
  559. {
  560.     if (w == 1)
  561.         PSsetlinewidth(2.0);
  562.     else
  563.         PSsetlinewidth(0.0);
  564. }
  565.  
  566. /*
  567.  * the device entry
  568.  */
  569. static DevEntry NeXTdev = {
  570.     "NeXT",
  571.     "small",
  572.     "large",
  573.     NeXT_backbuf,
  574.     NeXT_char,
  575.     NeXT_checkkey,
  576.     NeXT_clear,
  577.     NeXT_color,
  578.     NeXT_draw,
  579.     NeXT_exit,
  580.     NeXT_fill,
  581.     NeXT_font,
  582.     NeXT_frontbuf,
  583.     NeXT_getkey,
  584.     NeXT_init,
  585.     NeXT_locator,
  586.     NeXT_mapcolor,
  587. #ifndef VOGLE
  588.     noop,
  589. #endif
  590.     NeXT_setlw,
  591.     NeXT_string,
  592.     NeXT_swapbuf, 
  593.     NeXT_sync
  594. };
  595.  
  596. /*
  597.  * _NeXT_devcpy
  598.  *
  599.  *    copy the NeXT device into vdevice.dev.
  600.  */
  601. void
  602. _NeXT_devcpy(void)
  603. {
  604.     vdevice.dev = NeXTdev;
  605. }
  606.  
  607.  
  608.