00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "plDevs.h"
00028
00029 #define DEBUG
00030
00031 #ifdef PLD_xwin
00032 #define NEED_PLDEBUG
00033 #include "plplotP.h"
00034 #include "plxwd.h"
00035 #include "drivers.h"
00036 #include "plevent.h"
00037
00038 #ifdef PL_HAVE_PTHREAD
00039 #include <pthread.h>
00040 #include <signal.h>
00041 int pthread_mutexattr_settype( pthread_mutexattr_t *attr, int kind );
00042 static void events_thread( void *pls );
00043 static pthread_mutex_t events_mutex;
00044 static int already = 0;
00045 #endif
00046
00047
00048 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_xwin = "xwin:X-Window (Xlib):1:xwin:5:xw\n";
00049
00050 static int synchronize = 0;
00051
00052
00053 static int nobuffered = 0;
00054
00055
00056 static int noinitcolors = 0;
00057
00058
00059 static int defaultvisual = 1;
00060
00061 static int usepthreads = 1;
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 #define MAX_INSTR 20
00073
00074
00075
00076
00077
00078
00079 #define PHYSICAL 1
00080
00081
00082
00083 #define LOCATE_INVOKED_VIA_API 1
00084 #define LOCATE_INVOKED_VIA_DRIVER 2
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 #define CCMAP_XWM_COLORS 70
00108
00109 #define RWMAP_CMAP1_COLORS 50
00110 #define RWMAP_MAX_COLORS 256
00111
00112 #define ROMAP_CMAP1_COLORS 50
00113 #define TC_CMAP1_COLORS 200
00114
00115
00116
00117
00118 static int sxwm_colors_set;
00119 static XColor sxwm_colors[RWMAP_MAX_COLORS];
00120
00121
00122
00123 static XwDisplay *xwDisplay[PLXDISPLAYS];
00124
00125
00126
00127
00128
00129 void plD_dispatch_init_xw( PLDispatchTable *pdt );
00130
00131 void plD_init_xw( PLStream * );
00132 void plD_line_xw( PLStream *, short, short, short, short );
00133 void plD_polyline_xw( PLStream *, short *, short *, PLINT );
00134 void plD_eop_xw( PLStream * );
00135 void plD_bop_xw( PLStream * );
00136 void plD_tidy_xw( PLStream * );
00137 void plD_state_xw( PLStream *, PLINT );
00138 void plD_esc_xw( PLStream *, PLINT, void * );
00139
00140
00141
00142 static void OpenXwin( PLStream *pls );
00143 static void Init( PLStream *pls );
00144 static void InitMain( PLStream *pls );
00145 static void InitColors( PLStream *pls );
00146 static void AllocCustomMap( PLStream *pls );
00147 static void AllocCmap0( PLStream *pls );
00148 static void AllocCmap1( PLStream *pls );
00149 static void MapMain( PLStream *pls );
00150 static void CreatePixmap( PLStream *pls );
00151 static void GetVisual( PLStream *pls );
00152 static void AllocBGFG( PLStream *pls );
00153 static int AreWeGrayscale( Display *display );
00154
00155
00156
00157 static void WaitForPage( PLStream *pls );
00158 static void CheckForEvents( PLStream *pls );
00159 static void HandleEvents( PLStream *pls );
00160
00161
00162
00163 static void MasterEH( PLStream *pls, XEvent *event );
00164 static void ClientEH( PLStream *pls, XEvent *event );
00165 static void ExposeEH( PLStream *pls, XEvent *event );
00166 static void ResizeEH( PLStream *pls, XEvent *event );
00167 static void MotionEH( PLStream *pls, XEvent *event );
00168 static void EnterEH( PLStream *pls, XEvent *event );
00169 static void LeaveEH( PLStream *pls, XEvent *event );
00170 static void KeyEH( PLStream *pls, XEvent *event );
00171 static void ButtonEH( PLStream *pls, XEvent *event );
00172 static void LookupXKeyEvent( PLStream *pls, XEvent *event );
00173 static void LookupXButtonEvent( PLStream *pls, XEvent *event );
00174
00175 static void ProcessKey( PLStream *pls );
00176 static void LocateKey( PLStream *pls );
00177 static void ProcessButton( PLStream *pls );
00178 static void LocateButton( PLStream *pls );
00179 static void Locate( PLStream *pls );
00180
00181
00182
00183 static void CreateXhairs( PLStream *pls );
00184 static void DestroyXhairs( PLStream *pls );
00185 static void DrawXhairs( PLStream *pls, int x0, int y0 );
00186 static void UpdateXhairs( PLStream *pls );
00187
00188
00189
00190 static void ExposeCmd( PLStream *pls, PLDisplay *ptr );
00191 static void RedrawCmd( PLStream *pls );
00192 static void ResizeCmd( PLStream *pls, PLDisplay *ptr );
00193 static void ConfigBufferingCmd( PLStream *pls, PLBufferingCB *ptr );
00194 static void GetCursorCmd( PLStream *pls, PLGraphicsIn *ptr );
00195 static void FillPolygonCmd( PLStream *pls );
00196 static void XorMod( PLStream *pls, PLINT *mod );
00197 static void DrawImage( PLStream *pls );
00198
00199
00200
00201 static void StoreCmap0( PLStream *pls );
00202 static void StoreCmap1( PLStream *pls );
00203 static void imageops( PLStream *pls, PLINT *ptr );
00204 static void SetBGFG( PLStream *pls );
00205 #ifdef DUMMY
00206 static void SaveColormap( Display *display, Colormap colormap );
00207 #endif
00208 static void PLColor_to_XColor( PLColor *plcolor, XColor *xcolor );
00209 static void PLColor_from_XColor( PLColor *plcolor, XColor *xcolor );
00210
00211 static DrvOpt xwin_options[] = { { "sync", DRV_INT, &synchronize, "Synchronized X server operation (0|1)" },
00212 { "nobuffered", DRV_INT, &nobuffered, "Sets unbuffered operation (0|1)" },
00213 { "noinitcolors", DRV_INT, &noinitcolors, "Sets cmap0 allocation (0|1)" },
00214 { "defvis", DRV_INT, &defaultvisual, "Use the Default Visual (0|1)" },
00215 { "usepth", DRV_INT, &usepthreads, "Use pthreads (0|1)" },
00216 { NULL, DRV_INT, NULL, NULL } };
00217
00218 void plD_dispatch_init_xw( PLDispatchTable *pdt )
00219 {
00220 #ifndef ENABLE_DYNDRIVERS
00221 pdt->pl_MenuStr = "X-Window (Xlib)";
00222 pdt->pl_DevName = "xwin";
00223 #endif
00224 pdt->pl_type = plDevType_Interactive;
00225 pdt->pl_seq = 5;
00226 pdt->pl_init = (plD_init_fp) plD_init_xw;
00227 pdt->pl_line = (plD_line_fp) plD_line_xw;
00228 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_xw;
00229 pdt->pl_eop = (plD_eop_fp) plD_eop_xw;
00230 pdt->pl_bop = (plD_bop_fp) plD_bop_xw;
00231 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_xw;
00232 pdt->pl_state = (plD_state_fp) plD_state_xw;
00233 pdt->pl_esc = (plD_esc_fp) plD_esc_xw;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243 void
00244 plD_init_xw( PLStream *pls )
00245 {
00246 XwDev *dev;
00247 PLFLT pxlx, pxly;
00248 int xmin = 0;
00249 int xmax = PIXELS_X - 1;
00250 int ymin = 0;
00251 int ymax = PIXELS_Y - 1;
00252
00253 dbug_enter( "plD_init_xw" );
00254
00255 pls->termin = 1;
00256 pls->dev_flush = 1;
00257 pls->dev_fill0 = 1;
00258 pls->plbuf_write = 1;
00259 pls->dev_fastimg = 1;
00260 pls->dev_xor = 1;
00261
00262 #ifndef PL_HAVE_PTHREAD
00263 usepthreads = 0;
00264 #endif
00265
00266 plParseDrvOpts( xwin_options );
00267
00268 #ifndef PL_HAVE_PTHREAD
00269 if ( usepthreads )
00270 plwarn( "You said you want pthreads, but they are not available." );
00271 #endif
00272
00273 if ( nobuffered )
00274 pls->plbuf_write = 0;
00275
00276
00277
00278 if ( pls->dev == NULL )
00279 OpenXwin( pls );
00280
00281 dev = (XwDev *) pls->dev;
00282
00283 Init( pls );
00284
00285
00286
00287 dev->xlen = xmax - xmin;
00288 dev->ylen = ymax - ymin;
00289
00290 dev->xscale_init = dev->init_width / (double) dev->xlen;
00291 dev->yscale_init = dev->init_height / (double) dev->ylen;
00292
00293 dev->xscale = dev->xscale_init;
00294 dev->yscale = dev->yscale_init;
00295
00296 #if PHYSICAL
00297 pxlx = DPMM / dev->xscale;
00298 pxly = DPMM / dev->yscale;
00299 #else
00300 pxlx = (double) PIXELS_X / LPAGE_X;
00301 pxly = (double) PIXELS_Y / LPAGE_Y;
00302 #endif
00303
00304 plP_setpxl( pxlx, pxly );
00305 plP_setphy( xmin, xmax, ymin, ymax );
00306
00307 #ifdef PL_HAVE_PTHREAD
00308 if ( usepthreads )
00309 {
00310 pthread_mutexattr_t mutexatt;
00311 pthread_attr_t pthattr;
00312
00313 if ( !already )
00314 {
00315 pthread_mutexattr_init( &mutexatt );
00316 if ( pthread_mutexattr_settype( &mutexatt, PLPLOT_MUTEX_RECURSIVE ) )
00317 plexit( "xwin: pthread_mutexattr_settype() failed!\n" );
00318
00319 pthread_mutex_init( &events_mutex, &mutexatt );
00320 already = 1;
00321 }
00322 else
00323 {
00324 pthread_mutex_lock( &events_mutex );
00325 already++;
00326 pthread_mutex_unlock( &events_mutex );
00327 }
00328
00329 pthread_attr_init( &pthattr );
00330 pthread_attr_setdetachstate( &pthattr, PTHREAD_CREATE_JOINABLE );
00331
00332 if ( pthread_create( &( dev->updater ), &pthattr, (void *) &events_thread, (void *) pls ) )
00333 {
00334 pthread_mutex_lock( &events_mutex );
00335 already--;
00336 pthread_mutex_unlock( &events_mutex );
00337
00338 if ( already == 0 )
00339 {
00340 pthread_mutex_destroy( &events_mutex );
00341 plexit( "xwin: pthread_create() failed!\n" );
00342 }
00343 else
00344 plwarn( "xwin: couldn't create thread for this plot window!\n" );
00345 }
00346 }
00347 #endif
00348 }
00349
00350
00351
00352
00353
00354
00355
00356 void
00357 plD_line_xw( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
00358 {
00359 XwDev *dev = (XwDev *) pls->dev;
00360 XwDisplay *xwd = (XwDisplay *) dev->xwd;
00361
00362 int x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a;
00363
00364 dbug_enter( "plD_line_xw" );
00365
00366 #ifdef PL_HAVE_PTHREAD
00367 if ( usepthreads )
00368 pthread_mutex_lock( &events_mutex );
00369 #endif
00370
00371 CheckForEvents( pls );
00372
00373 y1 = dev->ylen - y1;
00374 y2 = dev->ylen - y2;
00375
00376 x1 = x1 * dev->xscale;
00377 x2 = x2 * dev->xscale;
00378 y1 = y1 * dev->yscale;
00379 y2 = y2 * dev->yscale;
00380
00381 if ( dev->write_to_window )
00382 XDrawLine( xwd->display, dev->window, dev->gc, x1, y1, x2, y2 );
00383
00384 if ( dev->write_to_pixmap )
00385 XDrawLine( xwd->display, dev->pixmap, dev->gc, x1, y1, x2, y2 );
00386
00387 #ifdef PL_HAVE_PTHREAD
00388 if ( usepthreads )
00389 pthread_mutex_unlock( &events_mutex );
00390 #endif
00391 }
00392
00393
00394
00395
00396
00397
00398
00399 static void
00400 XorMod( PLStream *pls, PLINT *mod )
00401 {
00402 XwDev *dev = (XwDev *) pls->dev;
00403 XwDisplay *xwd = (XwDisplay *) dev->xwd;
00404
00405 if ( *mod == 0 )
00406 XSetFunction( xwd->display, dev->gc, GXcopy );
00407 else
00408 XSetFunction( xwd->display, dev->gc, GXxor );
00409 }
00410
00411
00412
00413
00414
00415
00416
00417 void
00418 plD_polyline_xw( PLStream *pls, short *xa, short *ya, PLINT npts )
00419 {
00420 XwDev *dev = (XwDev *) pls->dev;
00421 XwDisplay *xwd = (XwDisplay *) dev->xwd;
00422
00423 PLINT i;
00424 XPoint _pts[PL_MAXPOLY];
00425 XPoint *pts;
00426
00427 if ( npts > PL_MAXPOLY )
00428 {
00429 pts = (XPoint *) malloc( sizeof ( XPoint ) * npts );
00430 }
00431 else
00432 {
00433 pts = _pts;
00434 }
00435
00436 dbug_enter( "plD_polyline_xw" );
00437
00438 #ifdef PL_HAVE_PTHREAD
00439 if ( usepthreads )
00440 pthread_mutex_lock( &events_mutex );
00441 #endif
00442
00443 CheckForEvents( pls );
00444
00445 for ( i = 0; i < npts; i++ )
00446 {
00447 pts[i].x = dev->xscale * xa[i];
00448 pts[i].y = dev->yscale * ( dev->ylen - ya[i] );
00449 }
00450
00451 if ( dev->write_to_window )
00452 XDrawLines( xwd->display, dev->window, dev->gc, pts, npts,
00453 CoordModeOrigin );
00454
00455 if ( dev->write_to_pixmap )
00456 XDrawLines( xwd->display, dev->pixmap, dev->gc, pts, npts,
00457 CoordModeOrigin );
00458
00459 #ifdef PL_HAVE_PTHREAD
00460 if ( usepthreads )
00461 pthread_mutex_unlock( &events_mutex );
00462 #endif
00463
00464 if ( npts > PL_MAXPOLY )
00465 {
00466 free( pts );
00467 }
00468 }
00469
00470
00471
00472
00473
00474
00475
00476 void
00477 plD_eop_xw( PLStream *pls )
00478 {
00479 XwDev *dev = (XwDev *) pls->dev;
00480 XwDisplay *xwd = (XwDisplay *) dev->xwd;
00481
00482 dbug_enter( "plD_eop_xw" );
00483
00484 #ifdef PL_HAVE_PTHREAD
00485 if ( usepthreads )
00486 pthread_mutex_lock( &events_mutex );
00487 #endif
00488
00489 XFlush( xwd->display );
00490 if ( pls->db )
00491 ExposeCmd( pls, NULL );
00492
00493 if ( dev->is_main && !pls->nopause )
00494 WaitForPage( pls );
00495
00496 #ifdef PL_HAVE_PTHREAD
00497 if ( usepthreads )
00498 pthread_mutex_unlock( &events_mutex );
00499 #endif
00500 }
00501
00502
00503
00504
00505
00506
00507
00508 void
00509 plD_bop_xw( PLStream *pls )
00510 {
00511 XwDev *dev = (XwDev *) pls->dev;
00512 XwDisplay *xwd = (XwDisplay *) dev->xwd;
00513
00514 dbug_enter( "plD_bop_xw" );
00515
00516 #ifdef PL_HAVE_PTHREAD
00517 if ( usepthreads )
00518 pthread_mutex_lock( &events_mutex );
00519 #endif
00520
00521 dev->bgcolor = xwd->cmap0[0];
00522
00523 if ( dev->write_to_window )
00524 {
00525 XSetWindowBackground( xwd->display, dev->window, dev->bgcolor.pixel );
00526 XSetBackground( xwd->display, dev->gc, dev->bgcolor.pixel );
00527 XClearWindow( xwd->display, dev->window );
00528 }
00529 if ( dev->write_to_pixmap )
00530 {
00531 XSetForeground( xwd->display, dev->gc, dev->bgcolor.pixel );
00532 XFillRectangle( xwd->display, dev->pixmap, dev->gc, 0, 0,
00533 dev->width, dev->height );
00534 XSetForeground( xwd->display, dev->gc, dev->curcolor.pixel );
00535 }
00536 XSync( xwd->display, 0 );
00537 pls->page++;
00538
00539 #ifdef PL_HAVE_PTHREAD
00540 if ( usepthreads )
00541 pthread_mutex_unlock( &events_mutex );
00542 #endif
00543 }
00544
00545
00546
00547
00548
00549
00550
00551 void
00552 plD_tidy_xw( PLStream *pls )
00553 {
00554 XwDev *dev = (XwDev *) pls->dev;
00555 XwDisplay *xwd = (XwDisplay *) dev->xwd;
00556
00557 dbug_enter( "plD_tidy_xw" );
00558
00559 #ifdef PL_HAVE_PTHREAD
00560 if ( usepthreads )
00561 {
00562 pthread_mutex_lock( &events_mutex );
00563 if ( pthread_cancel( dev->updater ) == 0 )
00564 pthread_join( dev->updater, NULL );
00565
00566 pthread_mutex_unlock( &events_mutex );
00567 if ( --already == 0 )
00568 pthread_mutex_destroy( &events_mutex );
00569 }
00570 #endif
00571
00572 if ( dev->is_main )
00573 {
00574 XDestroyWindow( xwd->display, dev->window );
00575 if ( dev->write_to_pixmap )
00576 XFreePixmap( xwd->display, dev->pixmap );
00577 XFlush( xwd->display );
00578 }
00579
00580 xwd->nstreams--;
00581 if ( xwd->nstreams == 0 )
00582 {
00583 int ixwd = xwd->ixwd;
00584 XFreeGC( xwd->display, dev->gc );
00585 XFreeGC( xwd->display, xwd->gcXor );
00586 XCloseDisplay( xwd->display );
00587 free_mem( xwd->cmap0 );
00588 free_mem( xwd->cmap1 );
00589 free_mem( xwDisplay[ixwd] );
00590 }
00591
00592
00593
00594 }
00595
00596
00597
00598
00599
00600
00601
00602 void
00603 plD_state_xw( PLStream *pls, PLINT op )
00604 {
00605 XwDev *dev = (XwDev *) pls->dev;
00606 XwDisplay *xwd = (XwDisplay *) dev->xwd;
00607
00608 dbug_enter( "plD_state_xw" );
00609
00610 #ifdef PL_HAVE_PTHREAD
00611 if ( usepthreads )
00612 pthread_mutex_lock( &events_mutex );
00613 #endif
00614
00615 CheckForEvents( pls );
00616
00617 switch ( op )
00618 {
00619 case PLSTATE_WIDTH:
00620 XSetLineAttributes( xwd->display, dev->gc, pls->width,
00621 LineSolid, CapRound, JoinMiter );
00622 break;
00623
00624 case PLSTATE_COLOR0: {
00625 int icol0 = pls->icol0;
00626 if ( xwd->color )
00627 {
00628 if ( icol0 == PL_RGB_COLOR )
00629 {
00630 PLColor_to_XColor( &pls->curcolor, &dev->curcolor );
00631 if ( !XAllocColor( xwd->display, xwd->map, &dev->curcolor ) )
00632 {
00633 fprintf( stderr, "Warning: could not allocate color\n" );
00634 dev->curcolor.pixel = xwd->fgcolor.pixel;
00635 }
00636 }
00637 else
00638 {
00639 dev->curcolor = xwd->cmap0[icol0];
00640 }
00641 XSetForeground( xwd->display, dev->gc, dev->curcolor.pixel );
00642 }
00643 else
00644 {
00645 dev->curcolor = xwd->fgcolor;
00646 XSetForeground( xwd->display, dev->gc, dev->curcolor.pixel );
00647 }
00648 break;
00649 }
00650
00651 case PLSTATE_COLOR1: {
00652 int icol1;
00653
00654 if ( xwd->ncol1 == 0 )
00655 AllocCmap1( pls );
00656
00657 if ( xwd->ncol1 < 2 )
00658 break;
00659
00660 icol1 = ( pls->icol1 * ( xwd->ncol1 - 1 ) ) / ( pls->ncol1 - 1 );
00661 if ( xwd->color )
00662 dev->curcolor = xwd->cmap1[icol1];
00663 else
00664 dev->curcolor = xwd->fgcolor;
00665
00666 XSetForeground( xwd->display, dev->gc, dev->curcolor.pixel );
00667 break;
00668 }
00669
00670 case PLSTATE_CMAP0:
00671 SetBGFG( pls );
00672
00673 if ( pls->ncol0 != xwd->ncol0 )
00674 AllocCmap0( pls );
00675 StoreCmap0( pls );
00676 break;
00677
00678 case PLSTATE_CMAP1:
00679 StoreCmap1( pls );
00680 break;
00681 }
00682
00683 #ifdef PL_HAVE_PTHREAD
00684 if ( usepthreads )
00685 pthread_mutex_unlock( &events_mutex );
00686 #endif
00687 }
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719 void
00720 plD_esc_xw( PLStream *pls, PLINT op, void *ptr )
00721 {
00722 dbug_enter( "plD_esc_xw" );
00723
00724 #ifdef PL_HAVE_PTHREAD
00725 if ( usepthreads )
00726 pthread_mutex_lock( &events_mutex );
00727 #endif
00728
00729 switch ( op )
00730 {
00731 case PLESC_EH:
00732 HandleEvents( pls );
00733 break;
00734
00735 case PLESC_EXPOSE:
00736 ExposeCmd( pls, (PLDisplay *) ptr );
00737 break;
00738
00739 case PLESC_FILL:
00740 FillPolygonCmd( pls );
00741 break;
00742
00743 case PLESC_FLUSH: {
00744 XwDev *dev = (XwDev *) pls->dev;
00745 XwDisplay *xwd = (XwDisplay *) dev->xwd;
00746 HandleEvents( pls );
00747 XFlush( xwd->display );
00748 break;
00749 }
00750 case PLESC_GETC:
00751 GetCursorCmd( pls, (PLGraphicsIn *) ptr );
00752 break;
00753
00754 case PLESC_REDRAW:
00755 RedrawCmd( pls );
00756 break;
00757
00758 case PLESC_RESIZE:
00759 ResizeCmd( pls, (PLDisplay *) ptr );
00760 break;
00761
00762 case PLESC_XORMOD:
00763 XorMod( pls, (PLINT *) ptr );
00764 break;
00765
00766 case PLESC_DOUBLEBUFFERING:
00767 ConfigBufferingCmd( pls, (PLBufferingCB *) ptr );
00768 break;
00769
00770 case PLESC_IMAGE:
00771 DrawImage( pls );
00772 break;
00773
00774 case PLESC_IMAGEOPS:
00775 imageops( pls, (PLINT *) ptr );
00776 break;
00777
00778 case PLESC_PL2DEVCOL:
00779 PLColor_to_XColor( &pls->tmpcolor, (XColor *) ptr );
00780 break;
00781
00782 case PLESC_DEV2PLCOL:
00783 PLColor_from_XColor( &pls->tmpcolor, (XColor *) ptr );
00784 break;
00785
00786 case PLESC_SETBGFG:
00787 SetBGFG( pls );
00788 break;
00789
00790 case PLESC_DEVINIT:
00791 OpenXwin( pls );
00792 break;
00793 }
00794
00795 #ifdef PL_HAVE_PTHREAD
00796 if ( usepthreads )
00797 pthread_mutex_unlock( &events_mutex );
00798 #endif
00799 }
00800
00801
00802
00803
00804
00805
00806
00807 static void
00808 GetCursorCmd( PLStream *pls, PLGraphicsIn *ptr )
00809 {
00810 XwDev *dev = (XwDev *) pls->dev;
00811 XwDisplay *xwd = (XwDisplay *) dev->xwd;
00812 XEvent event;
00813 PLGraphicsIn *gin = &( dev->gin );
00814
00815
00816
00817 plGinInit( gin );
00818 dev->locate_mode = LOCATE_INVOKED_VIA_API;
00819 CreateXhairs( pls );
00820
00821
00822
00823 while ( gin->pX < 0 && dev->locate_mode )
00824 {
00825
00826 XNextEvent( xwd->display, &event );
00827 MasterEH( pls, &event );
00828 }
00829 *ptr = *gin;
00830 if ( dev->locate_mode )
00831 {
00832 dev->locate_mode = 0;
00833 DestroyXhairs( pls );
00834 }
00835 }
00836
00837
00838
00839
00840
00841
00842
00843
00844 static void
00845 FillPolygonCmd( PLStream *pls )
00846 {
00847 XwDev *dev = (XwDev *) pls->dev;
00848 XwDisplay *xwd = (XwDisplay *) dev->xwd;
00849 XPoint _pts[PL_MAXPOLY];
00850 XPoint *pts;
00851 int i;
00852
00853 if ( pls->dev_npts > PL_MAXPOLY )
00854 {
00855 pts = (XPoint *) malloc( sizeof ( XPoint ) * pls->dev_npts );
00856 }
00857 else
00858 {
00859 pts = _pts;
00860 }
00861
00862 CheckForEvents( pls );
00863
00864 for ( i = 0; i < pls->dev_npts; i++ )
00865 {
00866 pts[i].x = dev->xscale * pls->dev_x[i];
00867 pts[i].y = dev->yscale * ( dev->ylen - pls->dev_y[i] );
00868 }
00869
00870
00871
00872 if ( dev->write_to_window )
00873 XFillPolygon( xwd->display, dev->window, dev->gc,
00874 pts, pls->dev_npts, Complex, CoordModeOrigin );
00875
00876 if ( dev->write_to_pixmap )
00877 XFillPolygon( xwd->display, dev->pixmap, dev->gc,
00878 pts, pls->dev_npts, Complex, CoordModeOrigin );
00879
00880
00881
00882 #ifdef DEBUG
00883 if ( pls->debug )
00884 {
00885 XSetForeground( xwd->display, dev->gc, xwd->fgcolor.pixel );
00886 if ( dev->write_to_window )
00887 XDrawLines( xwd->display, dev->window, dev->gc, pts, pls->dev_npts,
00888 CoordModeOrigin );
00889
00890 if ( dev->write_to_pixmap )
00891 XDrawLines( xwd->display, dev->pixmap, dev->gc, pts, pls->dev_npts,
00892 CoordModeOrigin );
00893
00894 XSetForeground( xwd->display, dev->gc, dev->curcolor.pixel );
00895 }
00896 #endif
00897
00898 if ( pls->dev_npts > PL_MAXPOLY )
00899 {
00900 free( pts );
00901 }
00902 }
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 static void
00914 OpenXwin( PLStream *pls )
00915 {
00916 XwDev *dev;
00917 XwDisplay *xwd;
00918 int i;
00919
00920 dbug_enter( "OpenXwin" );
00921
00922
00923
00924 if ( pls->dev != NULL )
00925 plwarn( "OpenXwin: device pointer is already set" );
00926
00927 pls->dev = calloc( 1, (size_t) sizeof ( XwDev ) );
00928 if ( pls->dev == NULL )
00929 plexit( "plD_init_xw: Out of memory." );
00930
00931 dev = (XwDev *) pls->dev;
00932
00933
00934
00935 dev->instr = 0;
00936 dev->max_instr = MAX_INSTR;
00937
00938
00939
00940 dev->xwd = NULL;
00941 for ( i = 0; i < PLXDISPLAYS; i++ )
00942 {
00943 if ( xwDisplay[i] == NULL )
00944 {
00945 continue;
00946 }
00947 else if ( pls->FileName == NULL && xwDisplay[i]->displayName == NULL )
00948 {
00949 dev->xwd = xwDisplay[i];
00950 break;
00951 }
00952 else if ( pls->FileName == NULL || xwDisplay[i]->displayName == NULL )
00953 {
00954 continue;
00955 }
00956 else if ( strcmp( xwDisplay[i]->displayName, pls->FileName ) == 0 )
00957 {
00958 dev->xwd = xwDisplay[i];
00959 break;
00960 }
00961 }
00962
00963
00964
00965 if ( dev->xwd == NULL )
00966 {
00967 dev->xwd = (XwDisplay *) calloc( 1, (size_t) sizeof ( XwDisplay ) );
00968 if ( dev->xwd == NULL )
00969 plexit( "Init: Out of memory." );
00970
00971 for ( i = 0; i < PLXDISPLAYS; i++ )
00972 {
00973 if ( xwDisplay[i] == NULL )
00974 break;
00975 }
00976 if ( i == PLXDISPLAYS )
00977 plexit( "Init: Out of xwDisplay's." );
00978
00979 xwDisplay[i] = xwd = (XwDisplay *) dev->xwd;
00980 xwd->nstreams = 1;
00981
00982
00983 #ifdef PL_HAVE_PTHREAD
00984 if ( usepthreads )
00985 if ( !XInitThreads() )
00986 plexit( "xwin: XInitThreads() not successful." );
00987 #endif
00988 xwd->display = XOpenDisplay( pls->FileName );
00989 if ( xwd->display == NULL )
00990 {
00991 plexit( "Can't open display" );
00992 }
00993 xwd->displayName = pls->FileName;
00994 xwd->screen = DefaultScreen( xwd->display );
00995 if ( synchronize )
00996 XSynchronize( xwd->display, 1 );
00997
00998
00999 xwd->map = DefaultColormap( xwd->display, xwd->screen );
01000 GetVisual( pls );
01001
01002
01003
01004
01005
01006
01007 if ( pls->colorset )
01008 xwd->color = pls->color;
01009 else
01010 {
01011 pls->color = 1;
01012 xwd->color = !AreWeGrayscale( xwd->display );
01013 }
01014
01015
01016
01017 xwd->ncol0_alloc = pls->ncol0;
01018 xwd->cmap0 = (XColor *) calloc( pls->ncol0, (size_t) sizeof ( XColor ) );
01019 if ( xwd->cmap0 == 0 )
01020 plexit( "couldn't allocate space for cmap0 colors" );
01021
01022
01023 AllocBGFG( pls );
01024 SetBGFG( pls );
01025 }
01026
01027
01028
01029 else
01030 {
01031 xwd = (XwDisplay *) dev->xwd;
01032 xwd->nstreams++;
01033 }
01034 xwd->ixwd = i;
01035 }
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050 static void
01051 Init( PLStream *pls )
01052 {
01053 XwDev *dev = (XwDev *) pls->dev;
01054 XwDisplay *xwd = (XwDisplay *) dev->xwd;
01055
01056 Window root;
01057 int x, y;
01058
01059 dbug_enter( "Init" );
01060
01061
01062
01063 if ( pls->window_id == 0 )
01064 {
01065 dev->is_main = TRUE;
01066 InitMain( pls );
01067 }
01068 else
01069 {
01070 dev->is_main = FALSE;
01071 dev->window = pls->window_id;
01072 }
01073
01074
01075
01076 if ( noinitcolors == 0 )
01077 InitColors( pls );
01078 XSetWindowColormap( xwd->display, dev->window, xwd->map );
01079
01080
01081
01082 if ( !dev->gc )
01083 dev->gc = XCreateGC( xwd->display, dev->window, 0, 0 );
01084
01085
01086
01087 if ( !xwd->gcXor )
01088 {
01089 XGCValues gcValues;
01090 unsigned long mask;
01091
01092 gcValues.background = xwd->cmap0[0].pixel;
01093 gcValues.foreground = 0xFF;
01094 gcValues.function = GXxor;
01095 mask = GCForeground | GCBackground | GCFunction;
01096
01097 xwd->gcXor = XCreateGC( xwd->display, dev->window, mask, &gcValues );
01098 }
01099
01100
01101
01102 (void) XGetGeometry( xwd->display, dev->window, &root, &x, &y,
01103 &dev->width, &dev->height, &dev->border, &xwd->depth );
01104
01105 dev->init_width = dev->width;
01106 dev->init_height = dev->height;
01107
01108
01109
01110
01111 if ( pls->nopixmap )
01112 {
01113 dev->write_to_pixmap = 0;
01114 pls->db = 0;
01115 }
01116 else
01117 {
01118 dev->write_to_pixmap = 1;
01119 }
01120 dev->write_to_window = !pls->db;
01121
01122
01123
01124 if ( dev->write_to_pixmap )
01125 CreatePixmap( pls );
01126
01127
01128
01129 plD_state_xw( pls, PLSTATE_COLOR0 );
01130
01131 XSetWindowBackground( xwd->display, dev->window, xwd->cmap0[0].pixel );
01132 XSetBackground( xwd->display, dev->gc, xwd->cmap0[0].pixel );
01133
01134
01135 if ( pls->dev_eofill )
01136 XSetFillRule( xwd->display, dev->gc, EvenOddRule );
01137 else
01138 XSetFillRule( xwd->display, dev->gc, WindingRule );
01139
01140
01141
01142 if ( dev->is_main )
01143 MapMain( pls );
01144 }
01145
01146
01147
01148
01149
01150
01151
01152 static void
01153 InitMain( PLStream *pls )
01154 {
01155 XwDev *dev = (XwDev *) pls->dev;
01156 XwDisplay *xwd = (XwDisplay *) dev->xwd;
01157
01158 Window root;
01159 XSizeHints hint;
01160 int x, y;
01161 U_INT width, height, border, depth;
01162
01163 dbug_enter( "InitMain" );
01164
01165
01166
01167 (void) XGetGeometry( xwd->display, DefaultRootWindow( xwd->display ),
01168 &root, &x, &y, &width, &height, &border, &depth );
01169
01170
01171
01172
01173 hint.flags = 0;
01174 if ( pls->xlength == 0 && pls->ylength == 0 )
01175 hint.flags |= PSize;
01176 else
01177 hint.flags |= USSize;
01178
01179 if ( pls->xlength == 0 )
01180 pls->xlength = width * 0.75;
01181 if ( pls->ylength == 0 )
01182 pls->ylength = height * 0.75;
01183
01184 if ( pls->xlength > (short) width )
01185 pls->xlength = width - dev->border * 2;
01186 if ( pls->ylength > (short) height )
01187 pls->ylength = height - dev->border * 2;
01188
01189 hint.width = (int) pls->xlength;
01190 hint.height = (int) pls->ylength;
01191 dev->border = 5;
01192
01193
01194
01195
01196 if ( pls->xoffset != 0 || pls->yoffset != 0 )
01197 {
01198 hint.flags |= USPosition;
01199 hint.x = (int) pls->xoffset;
01200 hint.y = (int) pls->yoffset;
01201 }
01202 else
01203 {
01204 hint.x = 0;
01205 hint.y = 0;
01206 }
01207
01208
01209
01210 dev->window =
01211 XCreateWindow( xwd->display,
01212 DefaultRootWindow( xwd->display ),
01213 hint.x, hint.y, hint.width, hint.height,
01214 dev->border, xwd->depth,
01215 InputOutput, xwd->visual,
01216 0, NULL );
01217
01218 XSetStandardProperties( xwd->display, dev->window, pls->plwindow, pls->plwindow,
01219 None, 0, 0, &hint );
01220 }
01221
01222
01223
01224
01225
01226
01227
01228 static void
01229 MapMain( PLStream *pls )
01230 {
01231 XwDev *dev = (XwDev *) pls->dev;
01232 XwDisplay *xwd = (XwDisplay *) dev->xwd;
01233 XEvent event;
01234
01235 dbug_enter( "MapMain" );
01236
01237
01238
01239 dev->event_mask =
01240 ButtonPressMask |
01241 KeyPressMask |
01242 ExposureMask |
01243 ButtonMotionMask |
01244 StructureNotifyMask;
01245
01246 XSelectInput( xwd->display, dev->window, dev->event_mask );
01247
01248
01249
01250 XMapRaised( xwd->display, dev->window );
01251
01252 Atom wmDelete = XInternAtom( xwd->display, "WM_DELETE_WINDOW", False );
01253 XSetWMProtocols( xwd->display, dev->window, &wmDelete, 1 );
01254
01255
01256
01257
01258 for (;; )
01259 {
01260 XWindowEvent( xwd->display, dev->window, dev->event_mask, &event );
01261 if ( event.type == Expose )
01262 {
01263 while ( XCheckWindowEvent( xwd->display, dev->window,
01264 ExposureMask, &event ) )
01265 ;
01266 break;
01267 }
01268 }
01269 }
01270
01271
01272
01273
01274
01275
01276
01277
01278 static void
01279 WaitForPage( PLStream *pls )
01280 {
01281 XwDev *dev = (XwDev *) pls->dev;
01282 XwDisplay *xwd = (XwDisplay *) dev->xwd;
01283 XEvent event;
01284
01285 dbug_enter( "WaitForPage" );
01286
01287 while ( !dev->exit_eventloop )
01288 {
01289
01290 XNextEvent( xwd->display, &event );
01291 MasterEH( pls, &event );
01292 }
01293 dev->exit_eventloop = FALSE;
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317 #ifdef PL_HAVE_PTHREAD
01318 static void
01319 events_thread( void *pls )
01320 {
01321 if ( usepthreads )
01322 {
01323 PLStream *lpls = (PLStream *) pls;
01324 XwDev *dev = (XwDev *) lpls->dev;
01325 XwDisplay *xwd = (XwDisplay *) dev->xwd;
01326 PLStream *oplsc;
01327 struct timespec delay;
01328 XEvent event;
01329 long event_mask;
01330 sigset_t set;
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348 event_mask = ExposureMask | StructureNotifyMask;
01349
01350
01351 sigemptyset( &set );
01352
01353 sigaddset( &set, SIGINT );
01354
01355 sigprocmask( SIG_BLOCK, &set, NULL );
01356
01357 pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL );
01358 pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL );
01359
01360 delay.tv_sec = 0;
01361 delay.tv_nsec = 10000000;
01362
01363 while ( 1 )
01364 {
01365 pthread_mutex_lock( &events_mutex );
01366
01367 if ( dev->is_main && !lpls->plbuf_read &&
01368 ++dev->instr % dev->max_instr == 0 )
01369 {
01370 dev->instr = 0;
01371 while ( XCheckWindowEvent( xwd->display, dev->window, event_mask, &event ) )
01372 {
01373
01374
01375
01376
01377
01378 oplsc = plsc;
01379 plsc = lpls;
01380 switch ( event.type )
01381 {
01382 case Expose:
01383 ExposeEH( lpls, &event );
01384 break;
01385 case ConfigureNotify:
01386 ResizeEH( lpls, &event );
01387 break;
01388 }
01389 plsc = oplsc;
01390 }
01391 }
01392
01393 pthread_mutex_unlock( &events_mutex );
01394 nanosleep( &delay, NULL );
01395
01396 }
01397 }
01398 }
01399 #endif
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416 static void
01417 CheckForEvents( PLStream *pls )
01418 {
01419 XwDev *dev = (XwDev *) pls->dev;
01420
01421 if ( dev->is_main &&
01422 !pls->plbuf_read &&
01423 ++dev->instr % dev->max_instr == 0 )
01424 {
01425 dev->instr = 0;
01426 HandleEvents( pls );
01427 }
01428 }
01429
01430
01431
01432
01433
01434
01435
01436
01437 static void
01438 HandleEvents( PLStream *pls )
01439 {
01440 XwDev *dev = (XwDev *) pls->dev;
01441 XwDisplay *xwd = (XwDisplay *) dev->xwd;
01442 XEvent event;
01443
01444 while ( XCheckTypedWindowEvent( xwd->display, dev->window,
01445 ClientMessage, &event ) ||
01446 XCheckWindowEvent( xwd->display, dev->window,
01447 dev->event_mask, &event ) )
01448 MasterEH( pls, &event );
01449 }
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467 static void
01468 MasterEH( PLStream *pls, XEvent *event )
01469 {
01470 XwDev *dev = (XwDev *) pls->dev;
01471
01472 if ( dev->MasterEH != NULL )
01473 ( *dev->MasterEH )( pls, event );
01474
01475 switch ( event->type )
01476 {
01477 case KeyPress:
01478 KeyEH( pls, event );
01479 break;
01480
01481 case ButtonPress:
01482 ButtonEH( pls, event );
01483 break;
01484
01485 case Expose:
01486 ExposeEH( pls, event );
01487 break;
01488
01489 case ConfigureNotify:
01490 ResizeEH( pls, event );
01491 break;
01492
01493 case MotionNotify:
01494 if ( event->xmotion.state )
01495 ButtonEH( pls, event );
01496 MotionEH( pls, event );
01497 break;
01498
01499 case EnterNotify:
01500 EnterEH( pls, event );
01501 break;
01502
01503 case LeaveNotify:
01504 LeaveEH( pls, event );
01505 break;
01506
01507 case ClientMessage:
01508 ClientEH( pls, event );
01509 break;
01510 }
01511 }
01512
01513
01514
01515
01516
01517
01518
01519 static void
01520 ClientEH( PLStream *pls, XEvent *event )
01521 {
01522 XwDev *dev = (XwDev *) pls->dev;
01523 XwDisplay *xwd = (XwDisplay *) dev->xwd;
01524
01525 if ( event->xclient.data.l[0] == XInternAtom( xwd->display, "WM_DELETE_WINDOW", False ) )
01526 {
01527 pls->nopause = TRUE;
01528 pls->stream_closed = TRUE;
01529 dev->exit_eventloop = TRUE;
01530
01531 }
01532 }
01533
01534
01535
01536
01537
01538
01539
01540
01541 static void
01542 KeyEH( PLStream *pls, XEvent *event )
01543 {
01544 XwDev *dev = (XwDev *) pls->dev;
01545
01546 dbug_enter( "KeyEH" );
01547
01548 LookupXKeyEvent( pls, event );
01549 if ( dev->locate_mode )
01550 LocateKey( pls );
01551 else
01552 ProcessKey( pls );
01553 }
01554
01555
01556
01557
01558
01559
01560
01561 static void
01562 ButtonEH( PLStream *pls, XEvent *event )
01563 {
01564 XwDev *dev = (XwDev *) pls->dev;
01565
01566 dbug_enter( "ButtonEH" );
01567
01568 LookupXButtonEvent( pls, event );
01569 if ( dev->locate_mode )
01570 LocateButton( pls );
01571 else
01572 ProcessButton( pls );
01573 }
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596 static void
01597 LookupXKeyEvent( PLStream *pls, XEvent *event )
01598 {
01599 XwDev *dev = (XwDev *) pls->dev;
01600 PLGraphicsIn *gin = &( dev->gin );
01601 XKeyEvent *keyEvent = (XKeyEvent *) event;
01602 KeySym keysym;
01603 int nchars, ncmax = PL_MAXKEY - 1;
01604 XComposeStatus cs;
01605
01606 gin->pX = keyEvent->x;
01607 gin->pY = keyEvent->y;
01608 gin->dX = (PLFLT) keyEvent->x / ( dev->width - 1 );
01609 gin->dY = 1.0 - (PLFLT) keyEvent->y / ( dev->height - 1 );
01610
01611 gin->state = keyEvent->state;
01612
01613 nchars = XLookupString( keyEvent, gin->string, ncmax, &keysym, &cs );
01614 gin->string[nchars] = '\0';
01615
01616 pldebug( "LookupXKeyEvent",
01617 "Keysym %x, translation: %s\n", keysym, gin->string );
01618
01619 switch ( keysym )
01620 {
01621 case XK_BackSpace:
01622 case XK_Tab:
01623 case XK_Linefeed:
01624 case XK_Return:
01625 case XK_Escape:
01626 case XK_Delete:
01627 gin->keysym = 0xFF & keysym;
01628 break;
01629
01630 default:
01631 gin->keysym = keysym;
01632 }
01633 }
01634
01635
01636
01637
01638
01639
01640
01641 static void
01642 LookupXButtonEvent( PLStream *pls, XEvent *event )
01643 {
01644 XwDev *dev = (XwDev *) pls->dev;
01645 PLGraphicsIn *gin = &( dev->gin );
01646 XButtonEvent *buttonEvent = (XButtonEvent *) event;
01647
01648 pldebug( "LookupXButtonEvent",
01649 "Button: %d, x: %d, y: %d\n",
01650 buttonEvent->button, buttonEvent->x, buttonEvent->y );
01651
01652 gin->pX = buttonEvent->x;
01653 gin->pY = buttonEvent->y;
01654 gin->dX = (PLFLT) buttonEvent->x / ( dev->width - 1 );
01655 gin->dY = 1.0 - (PLFLT) buttonEvent->y / ( dev->height - 1 );
01656
01657 gin->button = buttonEvent->button;
01658 gin->state = buttonEvent->state;
01659 gin->keysym = 0x20;
01660 }
01661
01662
01663
01664
01665
01666
01667
01668 static void
01669 ProcessKey( PLStream *pls )
01670 {
01671 XwDev *dev = (XwDev *) pls->dev;
01672 PLGraphicsIn *gin = &( dev->gin );
01673
01674 dbug_enter( "ProcessKey" );
01675
01676
01677
01678
01679 if ( pls->KeyEH != NULL )
01680 ( *pls->KeyEH )( gin, pls->KeyEH_data, &dev->exit_eventloop );
01681
01682
01683
01684 switch ( gin->keysym )
01685 {
01686 case PLK_Return:
01687 case PLK_Linefeed:
01688 case PLK_Next:
01689
01690
01691 dev->exit_eventloop = TRUE;
01692 break;
01693
01694 case 'Q':
01695
01696 pls->nopause = TRUE;
01697 plexit( "" );
01698 break;
01699
01700 case 'L':
01701
01702 dev->locate_mode = LOCATE_INVOKED_VIA_DRIVER;
01703 CreateXhairs( pls );
01704 break;
01705 }
01706 }
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718 static void
01719 ProcessButton( PLStream *pls )
01720 {
01721 XwDev *dev = (XwDev *) pls->dev;
01722 PLGraphicsIn *gin = &( dev->gin );
01723
01724 dbug_enter( "ProcessButton" );
01725
01726
01727
01728
01729 if ( pls->ButtonEH != NULL )
01730 ( *pls->ButtonEH )( gin, pls->ButtonEH_data, &dev->exit_eventloop );
01731
01732
01733
01734 switch ( gin->button )
01735 {
01736 case Button3:
01737 dev->exit_eventloop = TRUE;
01738 break;
01739 }
01740 }
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753 static void
01754 LocateKey( PLStream *pls )
01755 {
01756 XwDev *dev = (XwDev *) pls->dev;
01757 XwDisplay *xwd = (XwDisplay *) dev->xwd;
01758 PLGraphicsIn *gin = &( dev->gin );
01759
01760
01761
01762 if ( gin->keysym == PLK_Escape )
01763 {
01764 dev->locate_mode = 0;
01765 DestroyXhairs( pls );
01766 plGinInit( gin );
01767 }
01768
01769
01770
01771 else if ( IsModifierKey( gin->keysym ) )
01772 {
01773 plGinInit( gin );
01774 }
01775
01776
01777
01778 else if ( IsCursorKey( gin->keysym ) )
01779 {
01780 int x1, y1, dx = 0, dy = 0;
01781 int xmin = 0, xmax = dev->width - 1, ymin = 0, ymax = dev->height - 1;
01782
01783 switch ( gin->keysym )
01784 {
01785 case PLK_Left:
01786 dx = -1;
01787 break;
01788 case PLK_Right:
01789 dx = 1;
01790 break;
01791 case PLK_Up:
01792 dy = -1;
01793 break;
01794 case PLK_Down:
01795 dy = 1;
01796 break;
01797 }
01798
01799
01800
01801
01802
01803 if ( gin->state & 0x01 )
01804 {
01805 dx *= 5;
01806 dy *= 5;
01807 }
01808
01809
01810
01811 if ( gin->state & 0x02 )
01812 {
01813 dx *= 5;
01814 dy *= 5;
01815 }
01816
01817
01818
01819 if ( gin->state & 0x04 )
01820 {
01821 dx *= 5;
01822 dy *= 5;
01823 }
01824
01825
01826
01827 if ( gin->state & 0x08 )
01828 {
01829 dx *= 5;
01830 dy *= 5;
01831 }
01832
01833
01834
01835 x1 = gin->pX + dx;
01836 y1 = gin->pY + dy;
01837
01838 if ( x1 < xmin )
01839 dx = xmin - gin->pX;
01840 if ( y1 < ymin )
01841 dy = ymin - gin->pY;
01842 if ( x1 > xmax )
01843 dx = xmax - gin->pX;
01844 if ( y1 > ymax )
01845 dy = ymax - gin->pY;
01846
01847
01848
01849 XWarpPointer( xwd->display, dev->window, None, 0, 0, 0, 0, dx, dy );
01850 plGinInit( gin );
01851 }
01852
01853
01854
01855 else
01856 {
01857 Locate( pls );
01858 }
01859 }
01860
01861
01862
01863
01864
01865
01866
01867
01868 static void
01869 LocateButton( PLStream *pls )
01870 {
01871 XwDev *dev = (XwDev *) pls->dev;
01872 PLGraphicsIn *gin = &( dev->gin );
01873
01874 switch ( gin->button )
01875 {
01876 case Button1:
01877 Locate( pls );
01878 break;
01879 }
01880 }
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911 static void
01912 Locate( PLStream *pls )
01913 {
01914 XwDev *dev = (XwDev *) pls->dev;
01915 PLGraphicsIn *gin = &( dev->gin );
01916
01917
01918
01919 if ( pls->LocateEH != NULL )
01920 ( *pls->LocateEH )( gin, pls->LocateEH_data, &dev->locate_mode );
01921
01922
01923
01924 else
01925 {
01926
01927
01928 if ( plTranslateCursor( gin ) )
01929 {
01930
01931
01932
01933 if ( dev->locate_mode == LOCATE_INVOKED_VIA_DRIVER )
01934 {
01935 pltext();
01936 if ( gin->keysym < 0xFF && isprint( gin->keysym ) )
01937 printf( "%f %f %c\n", gin->wX, gin->wY, gin->keysym );
01938 else
01939 printf( "%f %f 0x%02x\n", gin->wX, gin->wY, gin->keysym );
01940
01941 plgra();
01942 }
01943 }
01944 else
01945 {
01946
01947
01948 dev->locate_mode = 0;
01949 DestroyXhairs( pls );
01950 }
01951 }
01952 }
01953
01954
01955
01956
01957
01958
01959
01960
01961 static void
01962 MotionEH( PLStream *pls, XEvent *event )
01963 {
01964 XwDev *dev = (XwDev *) pls->dev;
01965 XMotionEvent *motionEvent = (XMotionEvent *) event;
01966
01967 if ( dev->drawing_xhairs )
01968 {
01969 DrawXhairs( pls, motionEvent->x, motionEvent->y );
01970 }
01971 }
01972
01973
01974
01975
01976
01977
01978
01979
01980 static void
01981 EnterEH( PLStream *pls, XEvent *event )
01982 {
01983 XwDev *dev = (XwDev *) pls->dev;
01984 XCrossingEvent *crossingEvent = (XCrossingEvent *) event;
01985
01986 DrawXhairs( pls, crossingEvent->x, crossingEvent->y );
01987 dev->drawing_xhairs = 1;
01988 }
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998 static void
01999 LeaveEH( PLStream *pls, XEvent *event )
02000 {
02001 XwDev *dev = (XwDev *) pls->dev;
02002
02003 UpdateXhairs( pls );
02004 dev->drawing_xhairs = 0;
02005 }
02006
02007
02008
02009
02010
02011
02012
02013 static void
02014 CreateXhairs( PLStream *pls )
02015 {
02016 XwDev *dev = (XwDev *) pls->dev;
02017 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02018 Window root, child;
02019 int root_x, root_y, win_x, win_y;
02020 unsigned int mask;
02021 XEvent event;
02022
02023
02024
02025 if ( !xwd->xhair_cursor )
02026 xwd->xhair_cursor = XCreateFontCursor( xwd->display, XC_crosshair );
02027
02028 XDefineCursor( xwd->display, dev->window, xwd->xhair_cursor );
02029
02030
02031
02032
02033 if ( XQueryPointer( xwd->display, dev->window, &root, &child,
02034 &root_x, &root_y, &win_x, &win_y, &mask ) )
02035 {
02036 if ( win_x >= 0 && win_x < (int) dev->width &&
02037 win_y >= 0 && win_y < (int) dev->height )
02038 {
02039 DrawXhairs( pls, win_x, win_y );
02040 dev->drawing_xhairs = 1;
02041 }
02042 }
02043
02044
02045
02046 XSync( xwd->display, 0 );
02047 while ( XCheckWindowEvent( xwd->display, dev->window,
02048 PointerMotionMask, &event ) )
02049 ;
02050
02051
02052
02053 dev->event_mask |= PointerMotionMask | EnterWindowMask | LeaveWindowMask;
02054 XSelectInput( xwd->display, dev->window, dev->event_mask );
02055 }
02056
02057
02058
02059
02060
02061
02062
02063 static void
02064 DestroyXhairs( PLStream *pls )
02065 {
02066 XwDev *dev = (XwDev *) pls->dev;
02067 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02068
02069
02070
02071 XUndefineCursor( xwd->display, dev->window );
02072
02073
02074
02075 dev->event_mask &=
02076 ~PointerMotionMask & ~EnterWindowMask & ~LeaveWindowMask;
02077 XSelectInput( xwd->display, dev->window, dev->event_mask );
02078
02079
02080
02081 UpdateXhairs( pls );
02082 dev->drawing_xhairs = 0;
02083 }
02084
02085
02086
02087
02088
02089
02090
02091 static void
02092 DrawXhairs( PLStream *pls, int x0, int y0 )
02093 {
02094 XwDev *dev = (XwDev *) pls->dev;
02095
02096 int xmin = 0, xmax = dev->width - 1;
02097 int ymin = 0, ymax = dev->height - 1;
02098
02099 if ( dev->drawing_xhairs )
02100 UpdateXhairs( pls );
02101
02102 dev->xhair_x[0].x = xmin; dev->xhair_x[0].y = y0;
02103 dev->xhair_x[1].x = xmax; dev->xhair_x[1].y = y0;
02104
02105 dev->xhair_y[0].x = x0; dev->xhair_y[0].y = ymin;
02106 dev->xhair_y[1].x = x0; dev->xhair_y[1].y = ymax;
02107
02108 UpdateXhairs( pls );
02109 }
02110
02111
02112
02113
02114
02115
02116
02117 static void
02118 UpdateXhairs( PLStream *pls )
02119 {
02120 XwDev *dev = (XwDev *) pls->dev;
02121 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02122
02123 XDrawLines( xwd->display, dev->window, xwd->gcXor, dev->xhair_x, 2,
02124 CoordModeOrigin );
02125
02126 XDrawLines( xwd->display, dev->window, xwd->gcXor, dev->xhair_y, 2,
02127 CoordModeOrigin );
02128 }
02129
02130
02131
02132
02133
02134
02135
02136
02137 static void
02138 ExposeEH( PLStream *pls, XEvent *event )
02139 {
02140 XwDev *dev = (XwDev *) pls->dev;
02141 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02142 XExposeEvent *exposeEvent = (XExposeEvent *) event;
02143 PLDisplay pldis;
02144 int redrawn;
02145
02146 dbug_enter( "ExposeEH" );
02147
02148 pldebug( "ExposeEH",
02149 "x = %d, y = %d, width = %d, height = %d, count = %d, pending = %d\n",
02150 exposeEvent->x, exposeEvent->y,
02151 exposeEvent->width, exposeEvent->height,
02152 exposeEvent->count, XPending( xwd->display ) );
02153
02154
02155
02156
02157
02158
02159
02160 if ( dev->drawing_xhairs )
02161 {
02162 XClearWindow( xwd->display, dev->window );
02163 ExposeCmd( pls, NULL );
02164 UpdateXhairs( pls );
02165 redrawn = 1;
02166 }
02167 else
02168 {
02169 pldis.x = exposeEvent->x;
02170 pldis.y = exposeEvent->y;
02171 pldis.width = exposeEvent->width;
02172 pldis.height = exposeEvent->height;
02173
02174 ExposeCmd( pls, &pldis );
02175 redrawn = !dev->write_to_pixmap;
02176 }
02177
02178
02179
02180 if ( redrawn )
02181 while ( XCheckWindowEvent( xwd->display, dev->window,
02182 ExposureMask | StructureNotifyMask, event ) )
02183 ;
02184 }
02185
02186
02187
02188
02189
02190
02191
02192
02193 static void
02194 ResizeEH( PLStream *pls, XEvent *event )
02195 {
02196 XwDev *dev = (XwDev *) pls->dev;
02197 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02198 XConfigureEvent *configEvent = (XConfigureEvent *) event;
02199 PLDisplay pldis;
02200
02201 dbug_enter( "ResizeEH" );
02202
02203 pldis.width = configEvent->width;
02204 pldis.height = configEvent->height;
02205
02206
02207
02208 if ( pldis.width == dev->width && pldis.height == dev->height )
02209 return;
02210
02211 pldebug( "ResizeEH",
02212 "x = %d, y = %d, pending = %d\n",
02213 configEvent->width, configEvent->height, XPending( xwd->display ) );
02214
02215
02216
02217 ResizeCmd( pls, &pldis );
02218 if ( dev->drawing_xhairs )
02219 {
02220 UpdateXhairs( pls );
02221 }
02222
02223
02224
02225
02226 XFlush( xwd->display );
02227 while ( XCheckWindowEvent( xwd->display, dev->window,
02228 ExposureMask | StructureNotifyMask, event ) )
02229 ;
02230 }
02231
02232
02233
02234
02235
02236
02237
02238
02239 static void
02240 ExposeCmd( PLStream *pls, PLDisplay *pldis )
02241 {
02242 XwDev *dev = (XwDev *) pls->dev;
02243 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02244 int x, y, width, height;
02245
02246 dbug_enter( "ExposeCmd" );
02247
02248
02249
02250 if ( dev == NULL )
02251 {
02252 plwarn( "ExposeCmd: Illegal call -- driver uninitialized" );
02253 return;
02254 }
02255
02256
02257
02258 if ( pldis == NULL )
02259 {
02260 x = 0;
02261 y = 0;
02262 width = dev->width;
02263 height = dev->height;
02264 }
02265 else
02266 {
02267 x = pldis->x;
02268 y = pldis->y;
02269 width = pldis->width;
02270 height = pldis->height;
02271 }
02272
02273
02274
02275
02276 XSync( xwd->display, 0 );
02277 if ( dev->write_to_pixmap )
02278 {
02279 XCopyArea( xwd->display, dev->pixmap, dev->window, dev->gc,
02280 x, y, width, height, x, y );
02281 XSync( xwd->display, 0 );
02282 #ifdef DEBUG
02283 if ( pls->debug )
02284 {
02285 XPoint pts[5];
02286 int x0 = x, x1 = x + width, y0 = y, y1 = y + height;
02287 pts[0].x = x0; pts[0].y = y0;
02288 pts[1].x = x1; pts[1].y = y0;
02289 pts[2].x = x1; pts[2].y = y1;
02290 pts[3].x = x0; pts[3].y = y1;
02291 pts[4].x = x0; pts[4].y = y0;
02292
02293 XDrawLines( xwd->display, dev->window, dev->gc, pts, 5,
02294 CoordModeOrigin );
02295 }
02296 #endif
02297 }
02298 else
02299 {
02300 plRemakePlot( pls );
02301 XFlush( xwd->display );
02302 }
02303 }
02304
02305
02306
02307
02308
02309
02310
02311 static void
02312 ResizeCmd( PLStream *pls, PLDisplay *pldis )
02313 {
02314 XwDev *dev = (XwDev *) pls->dev;
02315 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02316 int write_to_window = dev->write_to_window;
02317
02318 dbug_enter( "ResizeCmd" );
02319
02320
02321
02322 if ( dev == NULL )
02323 {
02324 plwarn( "ResizeCmd: Illegal call -- driver uninitialized" );
02325 return;
02326 }
02327
02328
02329
02330 if ( pldis == NULL )
02331 {
02332 plwarn( "ResizeCmd: Illegal call -- window pointer uninitialized" );
02333 return;
02334 }
02335
02336
02337
02338 dev->width = pldis->width;
02339 dev->height = pldis->height;
02340
02341 dev->xscale = dev->width / (double) dev->init_width;
02342 dev->yscale = dev->height / (double) dev->init_height;
02343
02344 dev->xscale = dev->xscale * dev->xscale_init;
02345 dev->yscale = dev->yscale * dev->yscale_init;
02346
02347 #if PHYSICAL
02348 {
02349 PLFLT pxlx = DPMM / dev->xscale;
02350 PLFLT pxly = DPMM / dev->yscale;
02351 plP_setpxl( pxlx, pxly );
02352 }
02353 #endif
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363 if ( dev->write_to_pixmap )
02364 {
02365 dev->write_to_window = 0;
02366 XFreePixmap( xwd->display, dev->pixmap );
02367 CreatePixmap( pls );
02368 }
02369
02370
02371 if ( pls->ext_resize_draw )
02372 return;
02373
02374
02375
02376 if ( dev->write_to_pixmap )
02377 {
02378 XSetForeground( xwd->display, dev->gc, dev->bgcolor.pixel );
02379 XFillRectangle( xwd->display, dev->pixmap, dev->gc, 0, 0,
02380 dev->width, dev->height );
02381 XSetForeground( xwd->display, dev->gc, dev->curcolor.pixel );
02382 }
02383 if ( dev->write_to_window )
02384 {
02385 XClearWindow( xwd->display, dev->window );
02386 }
02387 plRemakePlot( pls );
02388 XSync( xwd->display, 0 );
02389
02390
02391
02392 if ( dev->write_to_pixmap )
02393 {
02394 dev->write_to_window = write_to_window;
02395 XCopyArea( xwd->display, dev->pixmap, dev->window, dev->gc, 0, 0,
02396 dev->width, dev->height, 0, 0 );
02397 XSync( xwd->display, 0 );
02398 }
02399 }
02400
02401
02402
02403
02404
02405
02406
02407
02408 static void ConfigBufferingCmd( PLStream *pls, PLBufferingCB *ptr )
02409 {
02410 XwDev *dev = (XwDev *) pls->dev;
02411
02412 switch ( ptr->cmd )
02413 {
02414 case PLESC_DOUBLEBUFFERING_ENABLE:
02415 dev->write_to_window = 0;
02416 pls->db = 1;
02417 break;
02418
02419 case PLESC_DOUBLEBUFFERING_DISABLE:
02420 dev->write_to_window = 1;
02421 pls->db = 0;
02422 break;
02423
02424 case PLESC_DOUBLEBUFFERING_QUERY:
02425 ptr->result = pls->db;
02426 break;
02427
02428 default:
02429 printf( "Unrecognized buffering request ignored.\n" );
02430 break;
02431 }
02432 }
02433
02434
02435
02436
02437
02438
02439
02440
02441 static void
02442 RedrawCmd( PLStream *pls )
02443 {
02444 XwDev *dev = (XwDev *) pls->dev;
02445 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02446 int write_to_window = dev->write_to_window;
02447
02448 dbug_enter( "RedrawCmd" );
02449
02450
02451
02452 if ( dev == NULL )
02453 {
02454 plwarn( "RedrawCmd: Illegal call -- driver uninitialized" );
02455 return;
02456 }
02457
02458
02459
02460 if ( dev->write_to_pixmap )
02461 {
02462 dev->write_to_window = 0;
02463 XSetForeground( xwd->display, dev->gc, dev->bgcolor.pixel );
02464 XFillRectangle( xwd->display, dev->pixmap, dev->gc, 0, 0,
02465 dev->width, dev->height );
02466 XSetForeground( xwd->display, dev->gc, dev->curcolor.pixel );
02467 }
02468 if ( dev->write_to_window )
02469 {
02470 XClearWindow( xwd->display, dev->window );
02471 }
02472 plRemakePlot( pls );
02473 XSync( xwd->display, 0 );
02474
02475 dev->write_to_window = write_to_window;
02476
02477
02478
02479 if ( dev->write_to_pixmap )
02480 {
02481 XCopyArea( xwd->display, dev->pixmap, dev->window, dev->gc, 0, 0,
02482 dev->width, dev->height, 0, 0 );
02483 XSync( xwd->display, 0 );
02484 }
02485 }
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495 static unsigned char CreatePixmapStatus;
02496
02497 static int
02498 CreatePixmapErrorHandler( Display *display, XErrorEvent *error )
02499 {
02500 CreatePixmapStatus = error->error_code;
02501 if ( error->error_code != BadAlloc )
02502 {
02503 char buffer[256];
02504 XGetErrorText( display, error->error_code, buffer, 256 );
02505 fprintf( stderr, "Error in XCreatePixmap: %s.\n", buffer );
02506 }
02507 return 1;
02508 }
02509
02510
02511
02512
02513
02514
02515
02516
02517 static void
02518 CreatePixmap( PLStream *pls )
02519 {
02520 XwDev *dev = (XwDev *) pls->dev;
02521 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02522
02523 int ( *oldErrorHandler )();
02524
02525 oldErrorHandler = XSetErrorHandler( CreatePixmapErrorHandler );
02526
02527 CreatePixmapStatus = Success;
02528 pldebug( "CreatePixmap",
02529 "creating pixmap: width = %d, height = %d, depth = %d\n",
02530 dev->width, dev->height, xwd->depth );
02531
02532 dev->pixmap = XCreatePixmap( xwd->display, dev->window,
02533 dev->width, dev->height, xwd->depth );
02534 XSync( xwd->display, 0 );
02535 if ( CreatePixmapStatus != Success )
02536 {
02537 dev->write_to_pixmap = 0;
02538 dev->write_to_window = 1;
02539 pls->db = 0;
02540 fprintf( stderr, "\n\
02541 Warning: pixmap could not be allocated (insufficient memory on server).\n\
02542 Driver will redraw the entire plot to handle expose events.\n" );
02543 }
02544
02545 XSetErrorHandler( oldErrorHandler );
02546 }
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559 static void
02560 GetVisual( PLStream *pls )
02561 {
02562 XwDev *dev = (XwDev *) pls->dev;
02563 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02564 int visuals_matched = 0;
02565
02566 dbug_enter( "GetVisual" );
02567
02568 if ( !defaultvisual )
02569 {
02570 XVisualInfo vTemplate, *visualList;
02571
02572
02573
02574 vTemplate.screen = xwd->screen;
02575 vTemplate.depth = 8;
02576
02577 visualList = XGetVisualInfo( xwd->display,
02578 VisualScreenMask | VisualDepthMask,
02579 &vTemplate, &visuals_matched );
02580
02581 #ifdef HACK_STATICCOLOR
02582 if ( visuals_matched )
02583 {
02584 int i, found = 0;
02585 printf( "visuals_matched = %d\n", visuals_matched );
02586 for ( i = 0; i < visuals_matched && !found; i++ )
02587 {
02588 Visual *v = visualList[i].visual;
02589 printf( "Checking visual %d: ", i );
02590 switch ( v->class )
02591 {
02592 case PseudoColor:
02593 printf( "PseudoColor\n" );
02594 break;
02595 case GrayScale:
02596 printf( "GrayScale\n" );
02597 break;
02598 case DirectColor:
02599 printf( "DirectColor\n" );
02600 break;
02601 case TrueColor:
02602 printf( "TrueColor\n" );
02603 break;
02604 case StaticColor:
02605 printf( "StaticColor\n" );
02606 break;
02607 case StaticGray:
02608 printf( "StaticGray\n" );
02609 break;
02610 default:
02611 printf( "Unknown.\n" );
02612 break;
02613 }
02614 if ( v->class == StaticColor )
02615 {
02616 xwd->visual = v;
02617 xwd->depth = visualList[i].depth;
02618 found = 1;
02619 }
02620 }
02621 if ( !found )
02622 {
02623 plexit( "Unable to get a StaticColor visual." );
02624 }
02625 printf( "Found StaticColor visual, depth=%d\n", xwd->depth );
02626 }
02627 #else
02628 if ( visuals_matched )
02629 {
02630 xwd->visual = visualList->visual;
02631 xwd->depth = vTemplate.depth;
02632 }
02633 #endif // HACK_STATICCOLOR
02634 }
02635
02636 if ( !visuals_matched )
02637 {
02638 xwd->visual = DefaultVisual( xwd->display, xwd->screen );
02639 xwd->depth = DefaultDepth( xwd->display, xwd->screen );
02640 }
02641
02642
02643
02644 switch ( xwd->visual->class )
02645 {
02646 case TrueColor:
02647 case StaticColor:
02648 case StaticGray:
02649 xwd->rw_cmap = 0;
02650 break;
02651 default:
02652 xwd->rw_cmap = 1;
02653 }
02654
02655
02656
02657
02658
02659 if ( pls->verbose )
02660 {
02661 fprintf( stderr, "XVisual class == " );
02662 switch ( xwd->visual->class )
02663 {
02664 case PseudoColor:
02665 fprintf( stderr, "PseudoColor\n" );
02666 break;
02667 case GrayScale:
02668 fprintf( stderr, "GrayScale\n" );
02669 break;
02670 case DirectColor:
02671 fprintf( stderr, "DirectColor\n" );
02672 break;
02673 case TrueColor:
02674 fprintf( stderr, "TrueColor\n" );
02675 break;
02676 case StaticColor:
02677 fprintf( stderr, "StaticColor\n" );
02678 break;
02679 case StaticGray:
02680 fprintf( stderr, "StaticGray\n" );
02681 break;
02682 default:
02683 fprintf( stderr, "Unknown.\n" );
02684 break;
02685 }
02686 fprintf( stderr, "xwd->rw_cmap = %d\n", xwd->rw_cmap );
02687 }
02688 }
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698 static void
02699 AllocBGFG( PLStream *pls )
02700 {
02701 XwDev *dev = (XwDev *) pls->dev;
02702 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02703
02704 int i, j, npixels;
02705 unsigned long plane_masks[1], pixels[RWMAP_MAX_COLORS];
02706
02707 dbug_enter( "AllocBGFG" );
02708
02709
02710 if ( !xwd->color )
02711 return;
02712
02713 if ( xwd->rw_cmap &&
02714
02715 XAllocColorCells( xwd->display, xwd->map, False,
02716 plane_masks, 0, pixels, 1 ) )
02717 {
02718
02719 xwd->cmap0[0].pixel = pixels[0];
02720 }
02721 else
02722 {
02723
02724 xwd->cmap0[0].pixel = BlackPixel( xwd->display, xwd->screen );
02725 xwd->fgcolor.pixel = WhitePixel( xwd->display, xwd->screen );
02726 if ( xwd->rw_cmap && pls->verbose )
02727 fprintf( stderr, "Downgrading to r/o cmap.\n" );
02728 xwd->rw_cmap = 0;
02729 return;
02730 }
02731
02732
02733
02734 npixels = RWMAP_MAX_COLORS;
02735 for (;; )
02736 {
02737 if ( XAllocColorCells( xwd->display, xwd->map, False,
02738 plane_masks, 0, pixels, npixels ) )
02739 break;
02740 npixels--;
02741 if ( npixels == 0 )
02742 break;
02743 }
02744
02745
02746
02747
02748 for ( i = 0; i < npixels - 1; i++ )
02749 {
02750 if ( pixels[i] == ( ~xwd->cmap0[0].pixel & 0xFF ) )
02751 break;
02752 }
02753
02754
02755
02756 xwd->fgcolor.pixel = pixels[i];
02757 for ( j = 0; j < npixels; j++ )
02758 {
02759 if ( j != i )
02760 XFreeColors( xwd->display, xwd->map, &pixels[j], 1, 0 );
02761 }
02762 }
02763
02764
02765
02766
02767
02768
02769
02770
02771 static void
02772 SetBGFG( PLStream *pls )
02773 {
02774 XwDev *dev = (XwDev *) pls->dev;
02775 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02776
02777 PLColor fgcolor;
02778 int gslevbg, gslevfg;
02779
02780 dbug_enter( "SetBGFG" );
02781
02782
02783
02784
02785
02786
02787
02788
02789 if ( !xwd->color )
02790 {
02791 pls->cmap0[0].r = pls->cmap0[0].g = pls->cmap0[0].b = 0xFF;
02792 }
02793 gslevbg = ( (long) pls->cmap0[0].r +
02794 (long) pls->cmap0[0].g +
02795 (long) pls->cmap0[0].b ) / 3;
02796
02797 PLColor_to_XColor( &pls->cmap0[0], &xwd->cmap0[0] );
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809 if ( gslevbg > 0x7F )
02810 gslevfg = 0;
02811 else
02812 gslevfg = 0xFF;
02813
02814 fgcolor.r = fgcolor.g = fgcolor.b = gslevfg;
02815
02816 PLColor_to_XColor( &fgcolor, &xwd->fgcolor );
02817
02818
02819
02820 if ( xwd->rw_cmap && xwd->color )
02821 {
02822 XStoreColor( xwd->display, xwd->map, &xwd->fgcolor );
02823 XStoreColor( xwd->display, xwd->map, &xwd->cmap0[0] );
02824 }
02825 else
02826 {
02827 XAllocColor( xwd->display, xwd->map, &xwd->cmap0[0] );
02828 XAllocColor( xwd->display, xwd->map, &xwd->fgcolor );
02829 }
02830 }
02831
02832
02833
02834
02835
02836
02837
02838 static void
02839 InitColors( PLStream *pls )
02840 {
02841 XwDev *dev = (XwDev *) pls->dev;
02842 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02843
02844 dbug_enter( "InitColors" );
02845
02846
02847
02848
02849 if ( xwd->color )
02850 {
02851 if ( plplot_ccmap )
02852 {
02853 AllocCustomMap( pls );
02854 }
02855 else
02856 {
02857 AllocCmap0( pls );
02858 }
02859 }
02860 }
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887 static void
02888 AllocCustomMap( PLStream *pls )
02889 {
02890 XwDev *dev = (XwDev *) pls->dev;
02891 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02892
02893 XColor xwm_colors[RWMAP_MAX_COLORS];
02894 int i, npixels;
02895 unsigned long plane_masks[1], pixels[RWMAP_MAX_COLORS];
02896
02897 dbug_enter( "AllocCustomMap" );
02898
02899
02900
02901 for ( i = 0; i < RWMAP_MAX_COLORS; i++ )
02902 {
02903 xwm_colors[i].pixel = i;
02904 }
02905 XQueryColors( xwd->display, xwd->map, xwm_colors, RWMAP_MAX_COLORS );
02906
02907
02908
02909
02910
02911
02912 AllocCmap0( pls );
02913 XAllocColor( xwd->display, xwd->map, &xwd->fgcolor );
02914
02915
02916
02917 xwd->map = XCreateColormap( xwd->display, DefaultRootWindow( xwd->display ),
02918 xwd->visual, AllocNone );
02919
02920
02921
02922 npixels = RWMAP_MAX_COLORS;
02923 for (;; )
02924 {
02925 if ( XAllocColorCells( xwd->display, xwd->map, False,
02926 plane_masks, 0, pixels, npixels ) )
02927 break;
02928 npixels--;
02929 if ( npixels == 0 )
02930 plexit( "couldn't allocate any colors" );
02931 }
02932
02933
02934
02935 for ( i = 0; i < CCMAP_XWM_COLORS; i++ )
02936 {
02937 XStoreColor( xwd->display, xwd->map, &xwm_colors[i] );
02938 pixels[xwm_colors[i].pixel] = 0;
02939 }
02940
02941
02942
02943 for ( i = 0; i < xwd->ncol0; i++ )
02944 {
02945 XStoreColor( xwd->display, xwd->map, &xwd->cmap0[i] );
02946 pixels[xwd->cmap0[i].pixel] = 0;
02947 }
02948
02949
02950
02951
02952
02953
02954
02955 if ( sxwm_colors_set )
02956 {
02957 for ( i = 0; i < RWMAP_MAX_COLORS; i++ )
02958 {
02959 if ( ( xwm_colors[i].red != sxwm_colors[i].red ) ||
02960 ( xwm_colors[i].green != sxwm_colors[i].green ) ||
02961 ( xwm_colors[i].blue != sxwm_colors[i].blue ) )
02962 {
02963 if ( pixels[i] != 0 )
02964 {
02965 XStoreColor( xwd->display, xwd->map, &xwm_colors[i] );
02966 pixels[i] = 0;
02967 }
02968 }
02969 }
02970 }
02971
02972
02973
02974 for ( i = 0; i < npixels; i++ )
02975 {
02976 if ( pixels[i] != 0 )
02977 XFreeColors( xwd->display, xwd->map, &pixels[i], 1, 0 );
02978 }
02979
02980
02981
02982 AllocCmap1( pls );
02983 }
02984
02985
02986
02987
02988
02989
02990
02991 static void
02992 AllocCmap0( PLStream *pls )
02993 {
02994 XwDev *dev = (XwDev *) pls->dev;
02995 XwDisplay *xwd = (XwDisplay *) dev->xwd;
02996 int i;
02997
02998 dbug_enter( "AllocCmap0" );
02999
03000
03001 for ( i = 1; i < xwd->ncol0; i++ )
03002 {
03003 unsigned long pixel = xwd->cmap0[i].pixel;
03004 XFreeColors( xwd->display, xwd->map, &pixel, 1, 0 );
03005 }
03006
03007
03008 if ( pls->ncol0 > xwd->ncol0_alloc )
03009 {
03010 xwd->ncol0_alloc = pls->ncol0;
03011 xwd->cmap0 = (XColor *)
03012 realloc( xwd->cmap0, (size_t) pls->ncol0 * sizeof ( XColor ) );
03013 if ( xwd->cmap0 == 0 )
03014 plexit( "couldn't allocate space for cmap0 colors" );
03015 }
03016
03017 if ( xwd->rw_cmap )
03018 {
03019 int npixels;
03020 unsigned long plane_masks[1], pixels[RWMAP_MAX_COLORS];
03021
03022
03023
03024 npixels = pls->ncol0 - 1;
03025 for (;; )
03026 {
03027 if ( XAllocColorCells( xwd->display, xwd->map, False,
03028 plane_masks, 0, &pixels[1], npixels ) )
03029 break;
03030 npixels--;
03031 if ( npixels == 0 )
03032 plexit( "couldn't allocate any colors" );
03033 }
03034
03035 xwd->ncol0 = npixels + 1;
03036 for ( i = 1; i < xwd->ncol0; i++ )
03037 {
03038 xwd->cmap0[i].pixel = pixels[i];
03039 }
03040
03041 StoreCmap0( pls );
03042 }
03043 else
03044 {
03045 if ( pls->verbose )
03046 fprintf( stderr, "Attempting to allocate r/o colors in cmap0.\n" );
03047
03048 for ( i = 1; i < pls->ncol0; i++ )
03049 {
03050 int r;
03051 XColor c;
03052 PLColor_to_XColor( &pls->cmap0[i], &c );
03053 r = XAllocColor( xwd->display, xwd->map, &c );
03054 if ( pls->verbose )
03055 fprintf( stderr, "i=%d, r=%d, pixel=%d\n", i, r, (int) c.pixel );
03056 if ( r )
03057 {
03058 xwd->cmap0[i] = c;
03059 xwd->cmap0[i].pixel = c.pixel;
03060 }
03061 else
03062 {
03063 XColor screen_def, exact_def;
03064
03065 if ( pls->verbose )
03066 fprintf( stderr,
03067 "color alloc failed, trying by name: %s.\n",
03068 pls->cmap0[i].name );
03069
03070
03071 r = XAllocNamedColor( xwd->display, xwd->map,
03072 pls->cmap0[i].name,
03073 &screen_def, &exact_def );
03074
03075
03076
03077 if ( r )
03078 {
03079 if ( pls->verbose )
03080 fprintf( stderr, "yes, got a color by name.\n" );
03081
03082 xwd->cmap0[i] = screen_def;
03083 xwd->cmap0[i].pixel = screen_def.pixel;
03084 }
03085 else
03086 {
03087 r = XAllocNamedColor( xwd->display, xwd->map,
03088 "white",
03089 &screen_def, &exact_def );
03090 if ( r )
03091 {
03092 xwd->cmap0[i] = screen_def;
03093 xwd->cmap0[i].pixel = screen_def.pixel;
03094 }
03095 else
03096 printf( "Can't find white?! Giving up...\n" );
03097 }
03098 }
03099 }
03100 xwd->ncol0 = i;
03101
03102 if ( pls->verbose )
03103 fprintf( stderr, "Allocated %d colors in cmap0.\n", xwd->ncol0 );
03104 }
03105 }
03106
03107
03108
03109
03110
03111
03112
03113 static void
03114 AllocCmap1( PLStream *pls )
03115 {
03116 XwDev *dev = (XwDev *) pls->dev;
03117 XwDisplay *xwd = (XwDisplay *) dev->xwd;
03118
03119 int i, j, npixels;
03120 unsigned long plane_masks[1], pixels[RWMAP_MAX_COLORS];
03121
03122 dbug_enter( "AllocCmap1" );
03123
03124 if ( xwd->rw_cmap )
03125 {
03126 if ( pls->verbose )
03127 fprintf( stderr, "Attempting to allocate r/w colors in cmap1.\n" );
03128
03129
03130
03131
03132 npixels = MAX( 2, MIN( RWMAP_CMAP1_COLORS, pls->ncol1 ) );
03133 for (;; )
03134 {
03135 if ( XAllocColorCells( xwd->display, xwd->map, False,
03136 plane_masks, 0, pixels, npixels ) )
03137 break;
03138 npixels--;
03139 if ( npixels == 0 )
03140 break;
03141 }
03142
03143 if ( npixels < 2 )
03144 {
03145 xwd->ncol1 = -1;
03146 fprintf( stderr, "Warning: unable to allocate sufficient colors in cmap1.\n" );
03147 return;
03148 }
03149
03150 xwd->ncol1 = npixels;
03151 if ( pls->verbose )
03152 fprintf( stderr, "AllocCmap1 (xwin.c): Allocated %d colors in cmap1.\n", npixels );
03153
03154
03155 if ( !xwd->cmap1 )
03156 {
03157 xwd->ncol1_alloc = xwd->ncol1;
03158 xwd->cmap1 = (XColor *) calloc( xwd->ncol1, (size_t) sizeof ( XColor ) );
03159 if ( !xwd->cmap1 )
03160 plexit( "couldn't allocate space for cmap1 colors" );
03161 }
03162
03163
03164
03165
03166 for ( j = i = 0; i < xwd->ncol1; i++ )
03167 {
03168 while ( pixels[j] == 0 )
03169 j++;
03170
03171 xwd->cmap1[i].pixel = pixels[j];
03172 pixels[j] = 0;
03173
03174 j += 2;
03175 if ( j >= xwd->ncol1 )
03176 j = 0;
03177 }
03178
03179 StoreCmap1( pls );
03180 }
03181 else
03182 {
03183 int i, r, ncolors;
03184 PLColor cmap1color;
03185 XColor xcol;
03186
03187 if ( pls->verbose )
03188 fprintf( stderr, "Attempting to allocate r/o colors in cmap1.\n" );
03189
03190 switch ( xwd->visual->class )
03191 {
03192 case TrueColor:
03193 ncolors = TC_CMAP1_COLORS;
03194 break;
03195 default:
03196 ncolors = ROMAP_CMAP1_COLORS;
03197 }
03198
03199
03200 if ( !xwd->cmap1 )
03201 {
03202 xwd->ncol1_alloc = ncolors;
03203 xwd->cmap1 = (XColor *) calloc( ncolors, (size_t) sizeof ( XColor ) );
03204 if ( !xwd->cmap1 )
03205 plexit( "couldn't allocate space for cmap1 colors" );
03206 }
03207
03208 for ( i = 0; i < ncolors; i++ )
03209 {
03210 plcol_interp( pls, &cmap1color, i, ncolors );
03211 PLColor_to_XColor( &cmap1color, &xcol );
03212
03213 r = XAllocColor( xwd->display, xwd->map, &xcol );
03214 if ( pls->verbose )
03215 fprintf( stderr, "i=%d, r=%d, pixel=%d\n", i, r, (int) xcol.pixel );
03216 if ( r )
03217 xwd->cmap1[i] = xcol;
03218 else
03219 break;
03220 }
03221 if ( i < ncolors )
03222 {
03223 xwd->ncol1 = -1;
03224 fprintf( stderr,
03225 "Warning: unable to allocate sufficient colors in cmap1\n" );
03226 return;
03227 }
03228 else
03229 {
03230 xwd->ncol1 = ncolors;
03231 if ( pls->verbose )
03232 fprintf( stderr, "AllocCmap1 (xwin.c): Allocated %d colors in cmap1\n", ncolors );
03233 }
03234 }
03235 }
03236
03237
03238
03239
03240
03241
03242
03243 static void
03244 StoreCmap0( PLStream *pls )
03245 {
03246 XwDev *dev = (XwDev *) pls->dev;
03247 XwDisplay *xwd = (XwDisplay *) dev->xwd;
03248 int i;
03249
03250 if ( !xwd->color )
03251 return;
03252
03253 for ( i = 1; i < xwd->ncol0; i++ )
03254 {
03255 PLColor_to_XColor( &pls->cmap0[i], &xwd->cmap0[i] );
03256 if ( xwd->rw_cmap )
03257 XStoreColor( xwd->display, xwd->map, &xwd->cmap0[i] );
03258 else
03259 XAllocColor( xwd->display, xwd->map, &xwd->cmap0[i] );
03260 }
03261 }
03262
03263
03264
03265
03266
03267
03268
03269 static void
03270 StoreCmap1( PLStream *pls )
03271 {
03272 XwDev *dev = (XwDev *) pls->dev;
03273 XwDisplay *xwd = (XwDisplay *) dev->xwd;
03274
03275 PLColor cmap1color;
03276 int i;
03277
03278 if ( !xwd->color )
03279 return;
03280
03281 for ( i = 0; i < xwd->ncol1; i++ )
03282 {
03283 plcol_interp( pls, &cmap1color, i, xwd->ncol1 );
03284 PLColor_to_XColor( &cmap1color, &xwd->cmap1[i] );
03285 if ( xwd->rw_cmap )
03286 XStoreColor( xwd->display, xwd->map, &xwd->cmap1[i] );
03287 else
03288 XAllocColor( xwd->display, xwd->map, &xwd->cmap1[i] );
03289 }
03290 }
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300 #define ToXColor( a ) ( ( ( 0xFF & ( a ) ) << 8 ) | ( a ) )
03301 #define ToPLColor( a ) ( ( (U_LONG) a ) >> 8 )
03302
03303 static void
03304 PLColor_to_XColor( PLColor *plcolor, XColor *xcolor )
03305 {
03306 xcolor->red = ToXColor( plcolor->r );
03307 xcolor->green = ToXColor( plcolor->g );
03308 xcolor->blue = ToXColor( plcolor->b );
03309 xcolor->flags = DoRed | DoGreen | DoBlue;
03310 }
03311
03312
03313
03314
03315
03316
03317
03318
03319 static void
03320 PLColor_from_XColor( PLColor *plcolor, XColor *xcolor )
03321 {
03322 plcolor->r = ToPLColor( xcolor->red );
03323 plcolor->g = ToPLColor( xcolor->green );
03324 plcolor->b = ToPLColor( xcolor->blue );
03325 }
03326
03327
03328
03329
03330
03331
03332
03333
03334
03335 static int
03336 AreWeGrayscale( Display *display )
03337 {
03338 #if defined ( __cplusplus ) || defined ( c_plusplus )
03339 #define THING c_class
03340 #else
03341 #define THING class
03342 #endif
03343
03344 XVisualInfo *visuals;
03345 int nitems, i, igray;
03346
03347
03348 visuals = XGetVisualInfo( display, 0, NULL, &nitems );
03349
03350 igray = 1;
03351
03352 for ( i = 0; i < nitems; i++ )
03353 if ( ( visuals[i].THING != GrayScale ) &&
03354 ( visuals[i].THING != StaticGray ) )
03355 {
03356 igray = 0;
03357 break;
03358 }
03359
03360 XFree( visuals );
03361
03362 return igray;
03363 }
03364
03365 #ifdef DUMMY
03366
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379
03380 static void
03381 SaveColormap( Display *display, Colormap colormap )
03382 {
03383 int i;
03384
03385 if ( !plplot_ccmap )
03386 return;
03387
03388 sxwm_colors_set = 1;
03389 for ( i = 0; i < RWMAP_MAX_COLORS; i++ )
03390 {
03391 sxwm_colors[i].pixel = i;
03392 }
03393 XQueryColors( display, colormap, sxwm_colors, RWMAP_MAX_COLORS );
03394
03395
03396
03397
03398
03399
03400
03401
03402 }
03403 #endif
03404
03405
03406
03407
03408
03409
03410
03411
03412 static int
03413 GetImageErrorHandler( Display *display, XErrorEvent *error )
03414 {
03415 if ( error->error_code != BadMatch )
03416 {
03417 char buffer[256];
03418 XGetErrorText( display, error->error_code, buffer, 256 );
03419 fprintf( stderr, "xwin: Error in XGetImage: %s.\n", buffer );
03420 }
03421 return 1;
03422 }
03423
03424
03425
03426
03427
03428
03429
03430
03431 static void
03432 DrawImage( PLStream *pls )
03433 {
03434 XwDev *dev = (XwDev *) pls->dev;
03435 XwDisplay *xwd = (XwDisplay *) dev->xwd;
03436 XImage *ximg = NULL;
03437 XColor curcolor;
03438 PLINT xmin, xmax, ymin, ymax, icol1;
03439
03440 int ( *oldErrorHandler )();
03441
03442 float mlr, mtb;
03443 float blt, brt, brb, blb;
03444 float left, right;
03445 int kx, ky;
03446 int nx, ny, ix, iy;
03447 int i, corners[4], r[4];
03448
03449 struct
03450 {
03451 float x, y;
03452 } Ppts[4];
03453
03454 CheckForEvents( pls );
03455
03456 xmin = dev->xscale * pls->imclxmin;
03457 xmax = dev->xscale * pls->imclxmax;
03458 ymin = dev->yscale * pls->imclymin;
03459 ymax = dev->yscale * pls->imclymax;
03460
03461 nx = pls->dev_nptsX;
03462 ny = pls->dev_nptsY;
03463
03464
03465 oldErrorHandler = XSetErrorHandler( GetImageErrorHandler );
03466
03467 XFlush( xwd->display );
03468 if ( dev->write_to_pixmap )
03469 ximg = XGetImage( xwd->display, dev->pixmap, 0, 0, dev->width, dev->height,
03470 AllPlanes, ZPixmap );
03471
03472 if ( dev->write_to_window )
03473 ximg = XGetImage( xwd->display, dev->window, 0, 0, dev->width, dev->height,
03474 AllPlanes, ZPixmap );
03475
03476 XSetErrorHandler( oldErrorHandler );
03477
03478 if ( ximg == NULL )
03479 {
03480 plabort( "Can't get image, the window must be partly off-screen, move it to fit screen" );
03481 return;
03482 }
03483
03484 if ( xwd->ncol1 == 0 )
03485 AllocCmap1( pls );
03486 if ( xwd->ncol1 < 2 )
03487 return;
03488
03489
03490 switch ( (int) ( pls->diorot - 4. * floor( pls->diorot / 4. ) ) )
03491 {
03492 case 0:
03493 r[0] = 0; r[1] = 1; r[2] = 2; r[3] = 3; break;
03494 case 1:
03495 r[0] = 1; r[1] = 2; r[2] = 3; r[3] = 0; break;
03496 case 2:
03497 r[0] = 2; r[1] = 3; r[2] = 0; r[3] = 1; break;
03498 case 3:
03499 r[0] = 3; r[1] = 0; r[2] = 1; r[3] = 2;
03500 }
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518 mlr = ( dev->yscale * ( pls->dev_iy[1] - pls->dev_iy[0] ) ) /
03519 ( dev->xscale * ( pls->dev_ix[1] - pls->dev_ix[0] ) );
03520
03521 mtb = ( dev->yscale * ( pls->dev_iy[ny] - pls->dev_iy[0] ) ) /
03522 ( dev->xscale * ( pls->dev_ix[ny] - pls->dev_ix[0] ) );
03523
03524 for ( ix = 0; ix < nx - 1; ix++ )
03525 {
03526 for ( iy = 0; iy < ny - 1; iy++ )
03527 {
03528 corners[0] = ix * ny + iy;
03529 corners[1] = ( ix + 1 ) * ny + iy;
03530 corners[2] = ( ix + 1 ) * ny + iy + 1;
03531 corners[3] = ix * ny + iy + 1;
03532
03533 for ( i = 0; i < 4; i++ )
03534 {
03535 Ppts[i].x = dev->xscale * ( pls->dev_ix[corners[r[i]]] );
03536 Ppts[i].y = dev->yscale * ( pls->dev_iy[corners[r[i]]] );
03537 }
03538
03539
03540 if ( Ppts[0].x >= xmin || Ppts[2].x <= xmax ||
03541 Ppts[1].y >= ymin || Ppts[3].y <= ymax )
03542 {
03543 Ppts[0].x = MAX( Ppts[0].x, xmin );
03544 Ppts[2].x = MIN( Ppts[2].x, xmax );
03545 Ppts[1].y = MAX( Ppts[1].y, ymin );
03546 Ppts[3].y = MIN( Ppts[3].y, ymax );
03547
03548
03549 icol1 = pls->dev_z[ix * ( ny - 1 ) + iy];
03550
03551
03552 if ( icol1 < pls->dev_zmin || icol1 > pls->dev_zmax )
03553 continue;
03554
03555 icol1 = icol1 / (float) USHRT_MAX * ( xwd->ncol1 - 1 );
03556 if ( xwd->color )
03557 curcolor = xwd->cmap1[icol1];
03558 else
03559 curcolor = xwd->fgcolor;
03560
03561
03562
03563
03564 if ( ( fabs( Ppts[2].x - Ppts[0].x ) == 1 ) &&
03565 ( fabs( Ppts[3].y - Ppts[1].y ) == 1 ) )
03566 {
03567 XPutPixel( ximg, Ppts[0].x, dev->height - 1 - Ppts[0].y, curcolor.pixel );
03568
03569
03570 }
03571 else if ( pls->diorot == floor( pls->diorot ) )
03572 {
03573 for ( ky = Ppts[1].y; ky < Ppts[3].y; ky++ )
03574 for ( kx = Ppts[0].x; kx < Ppts[2].x; kx++ )
03575 XPutPixel( ximg, kx, dev->height - 1 - ky, curcolor.pixel );
03576
03577
03578 }
03579 else
03580 {
03581
03582 blt = Ppts[0].y - mlr * Ppts[0].x;
03583 brb = Ppts[2].y - mlr * Ppts[2].x;
03584
03585 brt = Ppts[2].y - mtb * Ppts[2].x;
03586 blb = Ppts[0].y - mtb * Ppts[0].x;
03587
03588 for ( ky = Ppts[1].y; ky < Ppts[3].y; ky++ )
03589 {
03590 left = MAX( ( ( ky - blt ) / mlr ), ( ( ky - blb ) / mtb ) );
03591 right = MIN( ( ( ky - brt ) / mtb ), ( ( ky - brb ) / mlr ) );
03592 for ( kx = Ppts[0].x; kx < Ppts[2].x; kx++ )
03593 {
03594 if ( kx >= rint( left ) && kx <= rint( right ) )
03595 {
03596 XPutPixel( ximg, kx, dev->height - 1 - ky, curcolor.pixel );
03597 }
03598 }
03599 }
03600 }
03601 }
03602 }
03603 }
03604
03605 if ( dev->write_to_pixmap )
03606 XPutImage( xwd->display, dev->pixmap, dev->gc, ximg, 0, 0, 0, 0, dev->width, dev->height );
03607
03608 if ( dev->write_to_window )
03609 XPutImage( xwd->display, dev->window, dev->gc, ximg, 0, 0,
03610 0, 0, dev->width, dev->height );
03611
03612 XDestroyImage( ximg );
03613 }
03614
03615 static void
03616 imageops( PLStream *pls, PLINT *ptr )
03617 {
03618 XwDev *dev = (XwDev *) pls->dev;
03619 XwDisplay *xwd = (XwDisplay *) dev->xwd;
03620
03621
03622
03623 switch ( *ptr )
03624 {
03625 case ZEROW2D:
03626 dev->write_to_window = 0;
03627 break;
03628
03629 case ONEW2D:
03630 dev->write_to_window = 1;
03631 break;
03632
03633 case ZEROW2B:
03634 dev->write_to_pixmap = 0;
03635 break;
03636
03637 case ONEW2B:
03638 XFlush( xwd->display );
03639 dev->write_to_pixmap = 1;
03640 break;
03641 }
03642 }
03643
03644 #else
03645 int
03646 pldummy_xwin()
03647 {
03648 return 0;
03649 }
03650
03651 #endif // PLD_xwin