1/* Hello, Emacs, this is -*-C-*- */ 2 3/* GNUPLOT - ggi.trm */ 4 5/*[ 6 * Copyright 2000, 2004 7 * 8 * Permission to use, copy, and distribute this software and its 9 * documentation for any purpose with or without fee is hereby granted, 10 * provided that the above copyright notice appear in all copies and 11 * that both that copyright notice and this permission notice appear 12 * in supporting documentation. 13 * 14 * Permission to modify the software is granted, but not the right to 15 * distribute the complete modified source code. Modifications are to 16 * be distributed as patches to the released version. Permission to 17 * distribute binaries produced by compiling modified sources is granted, 18 * provided you 19 * 1. distribute the corresponding source modifications from the 20 * released version in the form of a patch file along with the binaries, 21 * 2. add special version identification to distinguish your version 22 * in addition to the base release version number, 23 * 3. provide your name and address as the primary contact for the 24 * support of your modified version, and 25 * 4. retain our contact information in regard to use of the base 26 * software. 27 * Permission to distribute the released version of the source code along 28 * with corresponding source modifications in the form of a patch file is 29 * granted with same provisions 2 through 4 for binary distributions. 30 * 31 * This software is provided "as is" without express or implied warranty 32 * to the extent permitted by applicable law. 33 ]*/ 34 35/* 36 * AUTHOR: 37 * Cesar Crusius <crusius@leland.stanford.edu> 38 * event / mouse processing & double-buffering 39 * by Johannes Zellner <johannes@zellner.org> 40 * pm3d support by Johannes Zellner <johannes@zellner.org> (Oct. 2000) 41 * 42 * TODO: 43 * 44 * - reimplement wmh (if it's available) 45 * - implement window title using wmh (if it's available) 46 * - check for availability of two frames, and if not 47 * do it with one frame. (will eventually not do 48 * with mouse/event reporting) 49 * - check if libxmi is available and if so, use 50 * it to draw filled polygons. 51 * - enable cursors using blits. 52 */ 53 54#include "driver.h" 55 56#ifdef TERM_REGISTER 57register_term(ggi) 58#endif 59 60#ifdef TERM_PROTO 61 62#include <ggi/ggi.h> 63#ifdef USE_MOUSE 64# include <ggi/ggi-unix.h> 65#endif 66 67#ifdef HAVE_GGI_WMH_H 68# include <ggi/wmh.h> 69static TBOOLEAN GGI_use_whm = 0; 70#endif 71 72#if 1 73#if defined(HAVE_GGI_XMI_H) 74# define ENABLE_XMI 1 75#endif 76#endif 77 78#ifdef ENABLE_XMI 79# include <ggi/xmi.h> 80#endif 81 82static void GGI_line_colors(void); 83TERM_PUBLIC void GGI_graphics(void); 84TERM_PUBLIC void GGI_set_size(void); 85TERM_PUBLIC void GGI_init(void); 86TERM_PUBLIC void GGI_linetype(int); 87TERM_PUBLIC void GGI_move(unsigned int,unsigned int); 88TERM_PUBLIC void GGI_options(void); 89TERM_PUBLIC void GGI_put_text(unsigned int,unsigned int, const char*); 90TERM_PUBLIC void GGI_suspend(void); 91TERM_PUBLIC void GGI_resume(void); 92TERM_PUBLIC void GGI_fillbox(int style, unsigned int x, unsigned int y, 93 unsigned int w, unsigned int h); 94TERM_PUBLIC void GGI_close(void); 95TERM_PUBLIC void GGI_reset(void); 96TERM_PUBLIC void GGI_text(void); 97TERM_PUBLIC void GGI_vector(unsigned int,unsigned int); 98 99#ifdef USE_MOUSE 100 101/* zoom box information */ 102 103typedef struct { 104 int x; 105 int y; 106} GGI_point_t; 107 108typedef struct { 109 int x; 110 int y; 111 int width; 112 int height; 113 char str[0xff]; 114} GGI_vertex_t; 115 116TERM_PUBLIC long int GGI_SetTime(const struct timeval* current); 117TERM_PUBLIC int GGI_from_keysym(uint32_t keysym); 118TERM_PUBLIC int GGI_from_button(uint32_t button); 119TERM_PUBLIC int GGI_y(int32_t y); 120TERM_PUBLIC int GGI_dispatch_event(const ggi_event* event); 121TERM_PUBLIC int GGI_eventually_update_modifiers(const ggi_event* event, const int add); 122TERM_PUBLIC int GGI_waitforinput(int); 123TERM_PUBLIC void GGI_draw_ruler(void); 124TERM_PUBLIC void GGI_clear_zoombox(void); 125TERM_PUBLIC void GGI_draw_zoombox(void); 126TERM_PUBLIC void GGI_set_ruler(int, int); 127TERM_PUBLIC void GGI_set_cursor(int, int, int); 128TERM_PUBLIC void GGI_save_frame_canvas(void); 129TERM_PUBLIC void GGI_save_frame_stl(void); 130TERM_PUBLIC void GGI_replot(void); 131TERM_PUBLIC void GGI_clear(const GGI_vertex_t* v, const int tag); 132TERM_PUBLIC void GGI_save_puts(GGI_vertex_t* v, const int tag); 133TERM_PUBLIC void GGI_set_vertex(GGI_vertex_t* v, const int x, const int y, const char* str, const int tag); 134TERM_PUBLIC void GGI_abort_zooming(void); 135TERM_PUBLIC void GGI_put_tmptext(int, const char str[]); 136TERM_PUBLIC void GGI_relative(int r[2]); 137TERM_PUBLIC void GGI_clear_hline(int x1, int x2, int y); 138TERM_PUBLIC void GGI_clear_vline(int y1, int y2, int x); 139TERM_PUBLIC void GGI_draw_hline(int x1, int x2, int y); 140TERM_PUBLIC void GGI_draw_vline(int y1, int y2, int x); 141TERM_PUBLIC void GGI_set_clipboard(const char[]); 142#endif /* USE_MOUSE */ 143 144TERM_PUBLIC int GGI_make_palette(t_sm_palette*); 145TERM_PUBLIC void GGI_previous_palette(void); 146TERM_PUBLIC void GGI_set_color(struct t_colorspec *colorspec); 147#ifdef ENABLE_XMI 148TERM_PUBLIC void GGI_filled_polygon(int, gpiPoint*); 149#endif 150 151#define GOT_GGI_PROTO 152#endif 153 154#ifndef TERM_PROTO_ONLY 155#ifdef TERM_BODY 156 157#define GGI_XMAX 800 158#define GGI_YMAX 600 159#define GGI_VCHAR 8 160#define GGI_HCHAR 8 161#define GGI_VTIC 8 162#define GGI_HTIC 8 163 164 165#ifdef USE_MOUSE 166static GGI_vertex_t GGI_zoom[2][2]; 167static GGI_vertex_t GGI_stl_vertex; 168static GGI_point_t GGI_ruler = {-1, -1}; 169static GGI_point_t GGI_zoombox[2] = {{-1, -1}, {-1, -1}}; 170 171static struct timeval GGI_timestamp; 172static int GGI_mouse_x = 0; 173static int GGI_mouse_y = 0; 174static int GGI_modifiers = 0; 175static int GGI_use_mouse = 1; /* mouse is on by default */ 176static unsigned int GGIcanvas_height = 0; 177static int GGI_font_width = 0; 178static int GGI_font_height = 0; 179static int GGI_saved_canvas = 0; 180static int GGI_saved_stl = 0; 181static int GGI_needs_update = 1; 182#endif 183 184static t_sm_palette GGI_save_pal = { 185 -1, -1, -1, -1, -1, -1, -1, -1, 186 (rgb_color*) 0, -1, -1 187}; 188 189/* First to some global variables 190 * 191 * GGIvisual is our 'piece of paper.' 192 * GGIborderColor and axixColor have the obvious meanings. 193 * GGIcolors are the colors for linestyles 0 and up. 194 * GGImap is for initializing colors. 195 * GGIx,GGIy are the current coordinates. 196 * GGIwidth, GGIheight are the extensions in the visual. 197 * GGIymax = term->ymax 198 */ 199static ggi_visual_t GGIvisual = (ggi_visual_t)0; 200static ggi_pixel GGIborderColor; 201static ggi_pixel GGIaxisColor; 202static ggi_pixel GGIblack; 203static ggi_pixel GGIbackground; 204static ggi_pixel GGIcolors[7]; 205#define GGI_PM3D_COLORS 240 206static const int ggi_pm3d_colors = GGI_PM3D_COLORS; 207static ggi_pixel GGI_smooth_colors[GGI_PM3D_COLORS]; 208static unsigned int GGIx,GGIy; 209static unsigned int GGIwidth, GGIheight, GGIymax; 210#if 0 211static unsigned int Xenv; 212#endif 213static int GGI_frames = 214#ifdef USE_MOUSE 2152 216#else 2171 218#endif 219; 220 221#ifdef ENABLE_XMI 222static miGC* GGI_miGC = (miGC*)0; 223static miPaintedSet* GGI_miPaintedSet = (miPaintedSet*)0; 224static miPixel GGI_miPixels[2]; /* only GGI_miPixels[1] is used */ 225static int GGI_numblendstages = 0; 226static miBlendStage GGI_blendstages[4]; 227#endif 228 229static TBOOLEAN GGI_mode_changed = 1; 230static char GGI_mode_spec[0xff] = ""; 231static int GGI_acceleration = 7; /* arbitrary */ 232 233enum GGI_id { 234 GGI_MODE, 235 GGI_ACCELERATION, 236 GGI_OTHER 237}; 238 239static struct gen_table GGI_opts[] = 240{ 241 { "mo$de", GGI_MODE }, 242 { "ac$celeration", GGI_ACCELERATION }, 243 { NULL, GGI_OTHER } 244}; 245 246static void 247GGI_line_colors() 248{ 249 ggi_pixel GGIwhite,GGIred,GGIgreen,GGIblue,GGIcyan,GGImagenta,GGIgray; 250 ggi_pixel GGIyellow; 251 ggi_color color; 252 253 color.r = 0xFFFF; color.g = 0xFFFF; color.b = 0xFFFF; GGIwhite = ggiMapColor(GGIvisual,&color); 254 color.r = 0x0000; color.g = 0x0000; color.b = 0x0000; GGIblack = ggiMapColor(GGIvisual,&color); 255 color.r = 0xFFFF; color.g = 0x0000; color.b = 0x0000; GGIred = ggiMapColor(GGIvisual,&color); 256 color.r = 0x0000; color.g = 0xFFFF; color.b = 0x0000; GGIgreen = ggiMapColor(GGIvisual,&color); 257 color.r = 0x0000; color.g = 0x0000; color.b = 0xFFFF; GGIblue = ggiMapColor(GGIvisual,&color); 258 color.r = 0x0000; color.g = 0xFFFF; color.b = 0xFFFF; GGIcyan = ggiMapColor(GGIvisual,&color); 259 color.r = 0xFFFF; color.g = 0x0000; color.b = 0xFFFF; GGImagenta = ggiMapColor(GGIvisual,&color); 260 color.r = 0xFFFF; color.g = 0xFFFF; color.b = 0x0000; GGIyellow = ggiMapColor(GGIvisual,&color); 261 color.r = 0x8888; color.g = 0x8888; color.b = 0x8888; GGIgray = ggiMapColor(GGIvisual,&color); 262 263 GGIborderColor = GGIwhite; 264 GGIbackground = GGIblack; 265 GGIaxisColor = GGIgray; 266 GGIcolors[0] = GGIred; 267 GGIcolors[1] = GGIgreen; 268 GGIcolors[2] = GGIblue; 269 GGIcolors[3] = GGImagenta; 270 GGIcolors[4] = GGIcyan; 271 GGIcolors[5] = GGIyellow; 272 GGIcolors[6] = GGIgray; 273} 274 275/* Called before a graphic is displayed */ 276TERM_PUBLIC void GGI_graphics() 277{ 278#ifdef USE_MOUSE 279 int i, j; 280 int display_frame = ggiGetDisplayFrame(GGIvisual); 281#endif 282#if 0 283 if(!Xenv) 284 { 285 GGI_line_colors(); 286 return; 287 } 288#endif 289 ggiSetGCForeground(GGIvisual,GGIblack); 290#ifdef USE_MOUSE 291 /* write to the currently not displayed buffer */ 292 ggiSetWriteFrame(GGIvisual, !display_frame); 293 294 /* mark the contents of the alternate frame as invalid */ 295 GGI_saved_canvas = 0; 296 GGI_saved_stl = 0; 297 GGI_needs_update = 1; 298 299 /* reset the stl vertex */ 300 GGI_stl_vertex.width = 0; 301 302 /* reset the zoom box coordinates */ 303 for (i = 0; i < 2; i++) { 304 for (j = 0; j < 2; j++) { 305 GGI_zoom[i][j].width = 0; 306 } 307 GGI_zoombox[i].x = -1; 308 GGI_zoombox[i].y = -1; 309 } 310#endif /* USE_MOUSE */ 311 312 /* clear *write* buffer. */ 313 ggiDrawBox(GGIvisual, 0, 0, GGIwidth, GGIheight); 314 315#ifdef USE_MOUSE 316 if (GGI_use_mouse) { 317 /* copy the contents of the currently 318 * displayed stl to the write frame. 319 * This way the stl won't jitter. */ 320 ggiSetReadFrame(GGIvisual, display_frame); 321 ggiCopyBox(GGIvisual, 0, GGIcanvas_height, 322 GGIwidth, GGI_font_height, 0, GGIcanvas_height); 323 } 324#endif 325} 326 327TERM_PUBLIC void 328GGI_set_size() 329{ 330 ggi_mode mode; 331 ggiGetMode(GGIvisual,&mode); 332 333 GGIwidth = mode.virt.x; 334 GGIheight = mode.virt.y; 335 336 term->xmax = mode.virt.x - 1; 337 338#ifdef USE_MOUSE 339 GGIcanvas_height = mode.virt.y - (GGI_use_mouse ? GGI_font_height : 0); 340 term->ymax = GGIcanvas_height - 1; 341#else 342 term->ymax = mode.virt.y - 1; 343#endif 344 GGIymax = term->ymax; 345} 346 347/* 348 * init 349 * ----------------------- 350 * Called only once, when the terminal is initialized. We have to open the visual here because it 351 * is during 'init' that we have to change the terminal dimensions (xmax, ymax). 352 */ 353TERM_PUBLIC void GGI_init() 354{ 355 int success = 0; 356 ggi_mode mode; 357 358#if 0 359 if (0 != giiInit()) { 360 ggiPanic("*** giiInit() failed *** \n"); 361 } 362#endif 363 364 if (0 != ggiInit()) { 365 ggiPanic("*** ggiInit() failed *** \n"); 366 } 367 368 if (NULL == (GGIvisual = ggiOpen(NULL))) { 369 /* TODO: abort a bit more gracefully */ 370 ggiPanic("(GGI_init() unable to open default\n"); 371 } 372 373 if (strlen(GGI_mode_spec)) { 374 /* user specified mode */ 375 if (!ggiParseMode(GGI_mode_spec, &mode)) { 376 mode.frames = GGI_frames; 377 if (!ggiSetMode(GGIvisual, &mode)) { 378 success = 1; 379 } 380 } 381 } 382 383 if (!success) { 384 /* try the default mode */ 385 if(ggiSetSimpleMode(GGIvisual,GGI_AUTO,GGI_AUTO,GGI_frames,GT_AUTO)) { 386 ggiPanic("(GGI_init() unable to set default mode\n"); 387 GGIvisual = (ggi_visual_t)0; 388 } 389 } 390 391 ggiGetMode(GGIvisual, &mode); 392 393 /* print the mode only once if it has changed */ 394 if (GGI_mode_changed) { 395 GGI_mode_changed = 0; 396 ggiFPrintMode(stderr, &mode); 397 fprintf(stderr, "\n"); 398 } 399 400 401#ifdef USE_MOUSE 402 /* must come before GGI_set_size() */ 403 ggiGetCharSize(GGIvisual, &GGI_font_width, &GGI_font_height); 404#endif 405 406 GGI_set_size(); 407 408#ifdef USE_MOUSE 409 ggiSetReadFrame(GGIvisual, 0); 410 ggiSetWriteFrame(GGIvisual, 0); 411 ggiSetDisplayFrame(GGIvisual, 0); 412#endif 413 414#ifdef HAVE_GGI_WMH_H 415 /* Initialize WMH extension */ 416 if (ggiWmhInit() != 0 || ggiWmhAttach(GGIvisual) < 0) { 417 GGI_use_whm = 0; 418 } else { 419 GGI_use_whm = 1; 420 ggiWmhAllowResize(GGIvisual, 100, 50, 2000, 2000, 10, 10); 421 ggiWmhSetTitle(GGIvisual, "GGI Gnuplot Driver"); 422 ggiWmhSetIconTitle(GGIvisual, "Gnuplot"); 423 } 424#endif 425 426 /* 427 * if(!(Xenv=!ggiWmhAttach(GGIvisual))) ggiWmhDetach(GGIvisual); 428 * else Xenv=!ggiWmhSetTitle(GGIvisual,"GGI Gnuplot Driver"); 429 */ 430#if 0 431 if(!Xenv) 432 { 433 /* 434 * ggiWmhDetach(GGIvisual); 435 * ggiWmhExit(); 436 */ 437 ggiClose(GGIvisual); 438 ggiExit(); 439 GGIvisual=NULL; 440 } 441#endif 442 GGI_line_colors(); 443 ggiSetFlags(GGIvisual, GGIFLAG_ASYNC); 444#ifdef USE_MOUSE 445 GGI_mouse_x = 0; 446 GGI_mouse_y = 0; 447 GGI_modifiers = 0; 448 { 449 struct timeval tv; 450 struct timezone tz; 451 gettimeofday(&tv, &tz); 452 GGI_SetTime(&tv); /* initialize time */ 453 } 454#endif 455 456#ifdef ENABLE_XMI 457 if (0 != xmiInit()) { 458 /* TODO: abort a bit more gracefully */ 459 ggiPanic("(GGI_init() unable to initialize xmi\n"); 460 } 461 462 if (xmiAttach(GGIvisual) < 0) { 463 ggiPanic("(GGI_init) Unable to attach XMI extension to visual\n"); 464 } 465 466 /* miPaintedSet */ 467 if (GGI_miPaintedSet) { 468 miDeletePaintedSet(GGIvisual, GGI_miPaintedSet); 469 GGI_miPaintedSet = (miPaintedSet*)0; 470 } 471 GGI_miPaintedSet = miNewPaintedSet(GGIvisual); 472 miClearPaintedSet(GGIvisual, GGI_miPaintedSet); 473 474 /* miGC */ 475 if (GGI_miGC) { 476 miDeleteGC(GGIvisual, GGI_miGC); 477 GGI_miGC = (miGC*)0; 478 } 479 GGI_miGC = miNewGC(GGIvisual, 2, 480 GGI_miPixels, GGI_numblendstages, GGI_blendstages); 481#endif 482 setvbuf(stdin, (char*)0, _IONBF, 0); 483} 484 485TERM_PUBLIC void GGI_linetype(int linetype) 486{ 487 if(linetype == LT_BLACK) 488 ggiSetGCForeground(GGIvisual,GGIborderColor); 489 if(linetype == LT_AXIS) 490 ggiSetGCForeground(GGIvisual,GGIaxisColor); 491 if(linetype < 0) 492 return; 493 if(linetype >= 6) 494 linetype%=6; 495 ggiSetGCForeground(GGIvisual,GGIcolors[linetype]); 496} 497 498TERM_PUBLIC void GGI_move(unsigned int x, unsigned int y) 499{ 500 GGIx=x; 501 GGIy=GGI_y(y); 502} 503 504TERM_PUBLIC void 505GGI_options() 506{ 507 while (!END_OF_COMMAND) { 508 switch(lookup_table(&GGI_opts[0], c_token)) { 509 case GGI_ACCELERATION: 510 { 511 int itmp; 512 struct value a; 513 514 c_token++; 515 itmp = (int) real(const_express(&a)); 516 if (itmp < 1) { 517 fprintf(stderr, "acceleration must be strictly positive!\n"); 518 } else { 519 GGI_acceleration = itmp; 520 } 521 break; 522 } 523 case GGI_MODE: 524 c_token++; 525 /* fallthru */ 526 default: 527 if (!END_OF_COMMAND) { 528 copy_str(GGI_mode_spec, c_token, 0xfe); 529 GGI_mode_changed = 1; 530 } 531 break; 532 } 533 c_token++; 534 } /* while(command) */ 535 536 if (*GGI_mode_spec) { 537 sprintf(term_options, "mode %s acceleration %d", 538 GGI_mode_spec, GGI_acceleration); 539 } else { 540 sprintf(term_options, "acceleration %d", GGI_acceleration); 541 } 542} 543 544TERM_PUBLIC void 545GGI_close() 546{ 547 ggiFlush(GGIvisual); 548 /* DETACH EXTENSIONS */ 549#if HAVE_WMH_H 550 if(GGI_use_whm) { 551 ggiWmhDetach(GGIvisual); 552 } 553#endif 554#ifdef ENABLE_XMI 555 xmiDetach(GGIvisual); 556#endif 557 558 ggiClose(GGIvisual); 559 GGIvisual = (ggi_visual_t)0; 560 561 /* EXIT EXTENSIONS */ 562#if HAVE_WMH_H 563 if(GGI_use_whm) { 564 ggiWmhExit(); 565 GGI_use_whm = 0; 566 } 567#endif 568#ifdef ENABLE_XMI 569 xmiExit(); 570#endif 571} 572 573/* Called when terminal is terminated i.e. 574 * when switching to another terminal. */ 575TERM_PUBLIC void 576GGI_reset() 577{ 578 if(GGIvisual!=NULL) { 579 GGI_close(); 580 } 581# if 0 /* not needed */ 582 GGI_save_pal.colorFormulae = -1; /* force later reallocation of palette */ 583# endif 584} 585 586TERM_PUBLIC void 587GGI_put_text(unsigned int x, unsigned int y, const char *str) 588{ 589 ggi_pixel current_foreground; 590 ggiGetGCForeground(GGIvisual,¤t_foreground); 591 ggiSetGCForeground(GGIvisual,GGIborderColor); 592 ggiPuts(GGIvisual,x,GGI_y(y) - 4 /* ? (joze ? */,str); 593 ggiSetGCForeground(GGIvisual,current_foreground); 594} 595 596TERM_PUBLIC void 597GGI_suspend() 598{ 599 /* this fails on the console */ 600 GGI_text(); 601} 602 603TERM_PUBLIC void 604GGI_resume() 605{ 606 /* do nothing */ 607} 608 609TERM_PUBLIC void 610GGI_fillbox( 611 int style, 612 unsigned int x, unsigned int y, 613 unsigned int w, unsigned int h) 614{ 615 ggiDrawBox(GGIvisual, x, GGI_y((int)(y+h)), w, h); 616} 617 618TERM_PUBLIC void 619GGI_text() 620{ 621 ggiFlush(GGIvisual); 622#ifdef USE_MOUSE 623 /* now display the buffer which was just written */ 624 ggiSetDisplayFrame(GGIvisual, ggiGetWriteFrame(GGIvisual)); 625 return; 626#else 627 /* Wait for a key to be pressed and exit graphics mode if 628 * running in console mode. */ 629 /* TODO: return immediately, if in X */ 630 ggiGetc(GGIvisual); 631 GGI_close(); 632#endif 633} 634 635TERM_PUBLIC void 636GGI_vector(unsigned int x, unsigned int y) 637{ 638 y = GGI_y(y); 639 ggiDrawLine(GGIvisual,GGIx,GGIy,x,y); 640 GGIx=x; 641 GGIy=y; 642} 643 644#ifdef USE_MOUSE 645 646/* translate ggi keysym to gnuplot keysym */ 647TERM_PUBLIC int 648GGI_from_keysym(uint32_t keysym) 649{ 650 switch (keysym) { 651 case GIIUC_BackSpace: 652 return GP_BackSpace; 653 case GIIUC_Tab: 654 return GP_Tab; 655 case GIIUC_Linefeed: 656 return GP_Linefeed; 657 case GIIK_Clear: 658 return GP_Clear; 659 case GIIUC_Return: 660 return GP_Return; 661 case GIIK_Pause: 662 return GP_Pause; 663 case GIIK_ScrollLock: 664 return GP_Scroll_Lock; 665 case GIIK_SysRq: 666 return GP_Sys_Req; 667 case GIIUC_Escape: 668 return GP_Escape; 669 case GIIK_Insert: 670 return GP_Insert; 671 case GIIUC_Delete: 672 return GP_Delete; 673 case GIIK_Home: 674 return GP_Home; 675 case GIIK_Left: 676 return GP_Left; 677 case GIIK_Up: 678 return GP_Up; 679 case GIIK_Right: 680 return GP_Right; 681 case GIIK_Down: 682 return GP_Down; 683 case GIIK_PageUp: 684 return GP_PageUp; 685 case GIIK_PageDown: 686 return GP_PageDown; 687 case GIIK_End: 688 return GP_End; 689 case GIIK_Begin: 690 return GP_Begin; 691 case GIIK_PSpace: 692 return GP_KP_Space; 693 case GIIK_PTab: 694 return GP_KP_Tab; 695 case GIIK_PEnter: 696 return GP_KP_Enter; 697 698 case GIIK_PF1: 699 return GP_KP_F1; 700 case GIIK_PF2: 701 return GP_KP_F2; 702 case GIIK_PF3: 703 return GP_KP_F3; 704 case GIIK_PF4: 705 return GP_KP_F4; 706 707#if 0 708 case 1: 709 return GP_KP_Insert; /* ~ KP_0 */ 710 case 1: 711 return GP_KP_End; /* ~ KP_1 */ 712 case 1: 713 return GP_KP_Down; /* ~ KP_2 */ 714 case 1: 715 return GP_KP_Page_Down; /* ~ KP_3 */ 716 case 1: 717 return GP_KP_Left; /* ~ KP_4 */ 718 case 1: 719 return GP_KP_Begin; /* ~ KP_5 */ 720 case 1: 721 return GP_KP_Right; /* ~ KP_6 */ 722 case 1: 723 return GP_KP_Home; /* ~ KP_7 */ 724 case 1: 725 return GP_KP_Up; /* ~ KP_8 */ 726 case 1: 727 return GP_KP_Page_Up; /* ~ KP_9 */ 728#endif 729 730#if 0 731 case GIIK_PDelete: 732 return GP_KP_Delete; 733#endif 734 case GIIK_PEqual: 735 return GP_KP_Equal; 736 case GIIK_PAsterisk: 737 return GP_KP_Multiply; 738 case GIIK_PPlus: 739 return GP_KP_Add; 740 case GIIK_PSeparator: 741 return GP_KP_Separator; 742 case GIIK_PMinus: 743 return GP_KP_Subtract; 744 case GIIK_PDecimal: 745 return GP_KP_Decimal; 746 case GIIK_PSlash: 747 return GP_KP_Divide; 748 749 case GIIK_P0: 750 return GP_KP_0; 751 case GIIK_P1: 752 return GP_KP_1; 753 case GIIK_P2: 754 return GP_KP_2; 755 case GIIK_P3: 756 return GP_KP_3; 757 case GIIK_P4: 758 return GP_KP_4; 759 case GIIK_P5: 760 return GP_KP_5; 761 case GIIK_P6: 762 return GP_KP_6; 763 case GIIK_P7: 764 return GP_KP_7; 765 case GIIK_P8: 766 return GP_KP_8; 767 case GIIK_P9: 768 return GP_KP_9; 769 770 case GIIK_F1: 771 return GP_F1; 772 case GIIK_F2: 773 return GP_F2; 774 case GIIK_F3: 775 return GP_F3; 776 case GIIK_F4: 777 return GP_F4; 778 case GIIK_F5: 779 return GP_F5; 780 case GIIK_F6: 781 return GP_F6; 782 case GIIK_F7: 783 return GP_F7; 784 case GIIK_F8: 785 return GP_F8; 786 case GIIK_F9: 787 return GP_F9; 788 case GIIK_F10: 789 return GP_F10; 790 case GIIK_F11: 791 return GP_F11; 792 case GIIK_F12: 793 return GP_F12; 794 795 default: 796 /* return it untranslated */ 797 return keysym; 798 } 799} 800 801TERM_PUBLIC long int 802GGI_SetTime(const struct timeval* current) 803{ 804 /* --> dsec in musec */ 805 int dsec = (current->tv_sec - GGI_timestamp.tv_sec) * 1000000; 806 /* --> dmu in millisec */ 807 int dmu = (current->tv_usec - GGI_timestamp.tv_usec + dsec) / 1000; 808 809 GGI_timestamp = *current; 810 return dmu; 811} 812 813TERM_PUBLIC int 814GGI_from_button(uint32_t button) 815{ 816 switch (button) { 817 case GII_PBUTTON_LEFT: 818 return 1; 819 case GII_PBUTTON_MIDDLE: 820 return 2; 821 case GII_PBUTTON_RIGHT: 822 return 3; 823 default: 824 /* should not happen */ 825 return 0; 826 } 827} 828 829TERM_PUBLIC int 830GGI_y(int32_t y) 831{ 832 return GGIymax - y; 833} 834 835TERM_PUBLIC int 836GGI_eventually_update_modifiers(const ggi_event* event, const int add) 837{ 838 int mod = 0; 839 int old_modifiers = GGI_modifiers; 840 841 switch (event->key.sym) { 842 case GIIK_Shift: 843 mod = Mod_Shift; 844 break; 845 case GIIK_Ctrl: 846 mod = Mod_Ctrl; 847 break; 848 case GIIK_Alt: 849 case GIIK_Meta: 850 mod = Mod_Alt; 851 break; 852 default: 853 return 0; 854 } 855 856 if (add) { 857 GGI_modifiers |= mod; 858 } else { 859 GGI_modifiers &= ~mod; 860 } 861 862 if (GGI_modifiers != old_modifiers) { 863 864 struct gp_event_t gp_ev; 865 866 gp_ev.type = GE_modifier; 867 gp_ev.mx = GGI_mouse_x; 868 gp_ev.my = GGI_y(GGI_mouse_y); 869 gp_ev.par1 = 0; 870 gp_ev.par2 = 0; 871 gp_ev.par1 = GGI_modifiers; 872 873 do_event(&gp_ev); 874 } 875 876 return 1; 877} 878 879TERM_PUBLIC int 880GGI_dispatch_event(const ggi_event* event) 881{ 882 struct gp_event_t gp_ev; 883 884 gp_ev.type = 0; 885 gp_ev.mx = GGI_mouse_x; 886 gp_ev.my = GGI_y(GGI_mouse_y); 887 gp_ev.par1 = 0; 888 gp_ev.par2 = 0; 889 890 switch (event->any.type) { 891 892 /* [-- KEY EVENTS --] */ 893 case evKeyPress: 894 case evKeyRepeat: 895 if (GGI_eventually_update_modifiers(event, 1)) { 896 /* was just a modifier pressed */ 897 return 0; 898 } 899 gp_ev.type = GE_keypress; 900 gp_ev.par1 = GGI_from_keysym(event->key.sym); 901 if ('q' == gp_ev.par1) { 902 return 'q'; 903 } 904 break; 905 case evKeyRelease: 906 if (GGI_eventually_update_modifiers(event, 0)) { 907 /* was just a modifier pressed */ 908 return 0; 909 } 910 break; 911 912 /* [-- POINTER EVENTS --] */ 913 case evPtrRelative: 914 /* relative motion is not implemented. Should it ? */ 915 /* 916 * fprintf(stderr, "%s:%d report this to <johannes@zellner.org> %d %d\n", 917 * __FILE__, __LINE__, event->pmove.x, event->pmove.y); 918 */ 919 gp_ev.type = GE_motion; 920 GGI_mouse_x += GGI_acceleration * event->pmove.x; 921 GGI_mouse_y += GGI_acceleration * event->pmove.y; 922 break; 923 case evPtrAbsolute: 924 gp_ev.type = GE_motion; 925 GGI_mouse_x = event->pmove.x; 926 GGI_mouse_y = event->pmove.y; 927 break; 928 case evPtrButtonPress: 929 gp_ev.type = GE_buttonpress; 930 gp_ev.par1 = GGI_from_button(event->pbutton.button); 931 break; 932 case evPtrButtonRelease: 933 gp_ev.type = GE_buttonrelease; 934 gp_ev.par1 = GGI_from_button(event->pbutton.button); 935 gp_ev.par2 = GGI_SetTime(&(event->pbutton.time)); 936 break; 937#ifdef HAVE_GGI_WMH_H 938 case evCommand: 939 /* [-- resizing --] */ 940 if (GGI_use_whm) { 941 /* fprintf(stderr, "(GGI_dispatch_event) \n"); */ 942 if (event->cmd.code==GGICMD_REQUEST_SWITCH) { 943 /* 944 * ggi_cmddata_switchrequest *req; 945 * req = &(event->cmd.data); 946 * ggi_resize(GGIvisual, &(req->mode)); 947 */ 948 /* 949 * while( ggiEventPoll(GGIvisual, emAll, &tv) ) { 950 * ggiEventRead(GGIvisual, event, emAll); 951 * } 952 */ 953 } 954 } 955 break; 956#endif 957 default: 958 /* fprintf(stderr, "(GGI_dispatch_event) unhandled event\n"); */ 959 break; 960 } 961 do_event(&gp_ev); 962 gp_ev.type = GE_plotdone; 963 do_event(&gp_ev); 964 return 0; 965} 966 967/* save currently displayed frame to alternate buffer */ 968TERM_PUBLIC void 969GGI_save_frame_canvas() 970{ 971 if (!GGI_saved_canvas && GGIvisual) { 972 int display_frame = ggiGetDisplayFrame(GGIvisual); 973 974 /* save the currently displayed frame to alternate frame */ 975 ggiSetReadFrame(GGIvisual, display_frame); 976 ggiSetWriteFrame(GGIvisual, !display_frame); 977 ggiCopyBox(GGIvisual, 0, 0, GGIwidth, GGIcanvas_height, 0, 0); 978 979 /* write again directly to the display frame */ 980 ggiSetWriteFrame(GGIvisual, display_frame); 981 982 /* remember that the alternate frame is valid */ 983 GGI_saved_canvas = 1; 984 } 985} 986 987TERM_PUBLIC void 988GGI_save_frame_stl() 989{ 990 if (!GGI_saved_stl) { 991 int display_frame = ggiGetDisplayFrame(GGIvisual); 992 993 /* clear the stl part of the alternate buffer */ 994 ggiSetGCForeground(GGIvisual, GGIblack); 995 ggiSetWriteFrame(GGIvisual, !display_frame); 996 ggiDrawBox(GGIvisual, 0, GGIcanvas_height, GGIwidth, GGI_font_height); 997 ggiSetWriteFrame(GGIvisual, display_frame); 998 999 /* clear the currently displayed area, which is left 1000 * from a previous plot (see above, where the stl of 1001 * the previous plot is copied to the current frame) */ 1002 ggiSetReadFrame(GGIvisual, !display_frame); 1003 ggiCopyBox(GGIvisual, 0, GGIcanvas_height, 1004 GGIwidth, GGI_font_height, 0, GGIcanvas_height); 1005 1006 GGI_saved_stl = 1; 1007 } 1008} 1009 1010TERM_PUBLIC void 1011GGI_replot() 1012{ 1013 struct gp_event_t ev = { 1014 GE_replot, 1015 0, 0, 0, 0 1016 }; 1017 1018 do_event(&ev); 1019} 1020 1021TERM_PUBLIC void 1022GGI_clear(const GGI_vertex_t* v, const int tag) 1023{ 1024 if (tag && v->width) { 1025 /* turn off current */ 1026 ggiSetReadFrame(GGIvisual, !ggiGetDisplayFrame(GGIvisual)); 1027 ggiCopyBox(GGIvisual, v->x, v->y, v->width, v->height, v->x, v->y); 1028 } 1029} 1030 1031TERM_PUBLIC void 1032GGI_save_puts(GGI_vertex_t* v, const int tag) 1033{ 1034 GGI_clear(v, tag); 1035 1036 if (v->width) { 1037 1038 /* draw the text in the axis color (gray) */ 1039 ggiSetGCForeground(GGIvisual, GGIaxisColor); 1040 1041 /* write the string directly to the display */ 1042 ggiPuts(GGIvisual, v->x, v->y, v->str); 1043 1044 } 1045} 1046 1047TERM_PUBLIC void 1048GGI_set_vertex( 1049 GGI_vertex_t* v, 1050 const int x, 1051 const int y, 1052 const char* str, 1053 const int tag) 1054{ 1055 GGI_clear(v, tag); 1056 1057 v->x = x; 1058 v->y = y; 1059 v->height = GGI_font_height; 1060 1061 if (str && *str) { 1062 v->width = strlen(str) * GGI_font_width; 1063 strcpy(v->str, str); 1064 } else { 1065 /* turn string off */ 1066 v->width = 0; 1067 *(v->str) = '\0'; 1068 } 1069} 1070 1071TERM_PUBLIC void 1072GGI_relative(int r[2]) 1073{ 1074 int diff = r[1] - r[0]; 1075 if (diff < 0) { 1076 r[0] = r[1]; 1077 r[1] = -diff; 1078 } else { 1079 r[1] = diff; 1080 } 1081} 1082 1083TERM_PUBLIC void 1084GGI_clear_hline(int x1, int x2, int y) 1085{ 1086 if (GGI_saved_canvas && x1 >= 0 && x2 >= 0 && y >= 0) { 1087 int r[2]; 1088 ggiSetReadFrame(GGIvisual, !ggiGetDisplayFrame(GGIvisual)); 1089 1090 r[0] = x1; 1091 r[1] = x2; 1092 GGI_relative(r); 1093 /* horizontal line */ 1094 ggiCopyBox(GGIvisual, r[0], y, r[1], 1, r[0], y); 1095 } 1096} 1097 1098TERM_PUBLIC void 1099GGI_clear_vline(int y1, int y2, int x) 1100{ 1101 if (GGI_saved_canvas && y1 >= 0 && y2 >= 0 && x >= 0) { 1102 int r[2]; 1103 ggiSetReadFrame(GGIvisual, !ggiGetDisplayFrame(GGIvisual)); 1104 1105 r[0] = y1; 1106 r[1] = y2; 1107 GGI_relative(r); 1108 /* vertical line */ 1109 ggiCopyBox(GGIvisual, x, r[0], 1, r[1], x, r[0]); 1110 } 1111} 1112 1113TERM_PUBLIC void 1114GGI_draw_hline(int x1, int x2, int y) 1115{ 1116 if (x1 >= 0 && x2 >= 0 && y >= 0) { 1117 int r[2]; 1118 1119 r[0] = x1; 1120 r[1] = x2; 1121 GGI_relative(r); 1122 /* horizontal line */ 1123 ggiDrawHLine(GGIvisual, r[0], y, r[1]); 1124 } 1125} 1126 1127TERM_PUBLIC void 1128GGI_draw_vline(int y1, int y2, int x) 1129{ 1130 if (y1 >= 0 && y2 >= 0 && x >= 0) { 1131 int r[2]; 1132 1133 r[0] = y1; 1134 r[1] = y2; 1135 GGI_relative(r); 1136 /* vertical line */ 1137 ggiDrawVLine(GGIvisual, x, r[0], r[1]); 1138 } 1139} 1140 1141TERM_PUBLIC void 1142GGI_draw_ruler() 1143{ 1144 if (GGI_ruler.x >= 0 && GGI_ruler.y >= 0) { 1145 ggi_pixel current_foreground; 1146 1147 GGI_save_frame_canvas(); 1148 1149 /* TODO: we could choose a nicer color here */ 1150 ggiGetGCForeground(GGIvisual, ¤t_foreground); 1151 ggiSetGCForeground(GGIvisual, GGIaxisColor); 1152 1153 ggiDrawHLine(GGIvisual, 0, GGI_ruler.y, GGIwidth); 1154 ggiDrawVLine(GGIvisual, GGI_ruler.x, 0, GGIcanvas_height); 1155 1156 /* restore old foreground color */ 1157 /* XXX need this ? */ 1158 ggiSetGCForeground(GGIvisual, current_foreground); 1159 } 1160} 1161 1162TERM_PUBLIC void 1163GGI_clear_zoombox() 1164{ 1165 GGI_clear_hline(GGI_zoombox[0].x, GGI_zoombox[1].x, GGI_zoombox[0].y); 1166 GGI_clear_hline(GGI_zoombox[0].x, GGI_zoombox[1].x, GGI_zoombox[1].y); 1167 GGI_clear_vline(GGI_zoombox[0].y, GGI_zoombox[1].y, GGI_zoombox[0].x); 1168 GGI_clear_vline(GGI_zoombox[0].y, GGI_zoombox[1].y, GGI_zoombox[1].x); 1169} 1170 1171TERM_PUBLIC void 1172GGI_draw_zoombox() 1173{ 1174 if (GGI_zoombox[0].x >= 0 && GGI_zoombox[0].y >= 0 1175 && GGI_zoombox[0].x >= 0 && GGI_zoombox[0].y >= 0) { 1176 ggi_pixel current_foreground; 1177 1178 GGI_save_frame_canvas(); 1179 1180 /* TODO: we could choose a nicer color here */ 1181 ggiGetGCForeground(GGIvisual, ¤t_foreground); 1182 ggiSetGCForeground(GGIvisual, GGIaxisColor); 1183 1184 GGI_draw_hline(GGI_zoombox[0].x, GGI_zoombox[1].x, GGI_zoombox[0].y); 1185 GGI_draw_hline(GGI_zoombox[0].x, GGI_zoombox[1].x, GGI_zoombox[1].y); 1186 GGI_draw_vline(GGI_zoombox[0].y, GGI_zoombox[1].y, GGI_zoombox[0].x); 1187 GGI_draw_vline(GGI_zoombox[0].y, GGI_zoombox[1].y, GGI_zoombox[1].x); 1188 1189 /* restore old foreground color */ 1190 /* XXX need this ? */ 1191 ggiSetGCForeground(GGIvisual, current_foreground); 1192 } 1193} 1194 1195TERM_PUBLIC void 1196GGI_abort_zooming() 1197{ 1198 /* empty string: finish zooming */ 1199 int i, j; 1200 GGI_clear_zoombox(); 1201 for (i = 0; i < 2; i++) { 1202 for (j = 0; j < 2; j++) { 1203 GGI_set_vertex(&(GGI_zoom[i][j]), 0, 0, (char*)0, GGI_saved_canvas); 1204 } 1205 GGI_zoombox[i].x = -1; 1206 } 1207} 1208 1209TERM_PUBLIC int 1210GGI_waitforinput(int options) 1211{ 1212 char c; 1213 1214 /* XXX: if the input device it not a tty (e.g. /dev/null) 1215 * mouse events are not processed. This is necessary 1216 * as on some systems /dev/null is not selectable. 1217 */ 1218 /* FIXME: Not implemented yet */ 1219 if (options == TERM_ONLY_CHECK_MOUSING) return '\0'; 1220 1221 if (GGIvisual) { 1222 fd_set fds; 1223 int fd = fileno(stdin); 1224 int i, j; 1225 do { 1226 ggi_event_mask mask = emAll; /* TODO: choose a more selective mask */ 1227 ggiSetEventMask(GGIvisual, mask); 1228 1229 FD_ZERO(&fds); 1230 FD_SET(fd, &fds); /* listen to stdin */ 1231 1232 if (GGI_needs_update) { 1233 /* draw the ruler below the other items */ 1234 GGI_draw_ruler(); 1235 1236 /* update the zoombox */ 1237 GGI_draw_zoombox(); 1238 for (i = 0; i < 2; i++) { 1239 for (j = 0; j < 2; j++) { 1240 GGI_save_puts(&(GGI_zoom[i][j]), GGI_saved_canvas); 1241 } 1242 } 1243 1244 /* update the status line */ 1245 GGI_save_puts(&GGI_stl_vertex, GGI_saved_stl); 1246 1247 ggiFlush(GGIvisual); 1248 1249 GGI_needs_update = 0; 1250 } 1251 1252 ggiEventSelect(GGIvisual, &mask, fd + 1, 1253 SELECT_TYPE_ARG234 &fds, 0, 0, (struct timeval*)0); 1254 1255 if (mask) { 1256 ggi_event event; 1257 /* mask pointer motions and key repeat events, 1258 * to they don't pile up */ 1259 ggiEventRead(GGIvisual, &event, mask); 1260 ggiRemoveEventMask(GGIvisual, emPtrMove | emKeyRepeat); 1261 if ('q' == GGI_dispatch_event(&event)) { 1262 term_reset(); 1263 break; 1264 } else { 1265 ggiAddEventMask(GGIvisual, emPtrMove | emKeyRepeat); 1266 } 1267 } 1268 1269 } while (!FD_ISSET(fd, &fds) && GGIvisual); 1270 } 1271 1272 if (read(0, &c, 1)!=1) return EOF; 1273 else return c; 1274} 1275 1276TERM_PUBLIC void 1277GGI_put_tmptext(int i, const char str[]) 1278{ 1279 char* second; 1280 1281 if (GGIvisual == NULL) 1282 return; 1283 1284 switch (i) { 1285 case 0: /* statusline text */ 1286 1287 if (!str || !(*str)) { 1288 /* statusline is empty. This is the case, 1289 * if the mouse was just turned off. */ 1290 if (GGI_use_mouse) { 1291 /* The user just toggled of the mouse. */ 1292 GGI_use_mouse = 0; 1293 GGI_set_size(); 1294 GGI_replot(); 1295 } 1296 } else { 1297 /* statusline is non-empty */ 1298 if (!GGI_use_mouse) { 1299 /* The mouse was off before and was just turned on. */ 1300 GGI_use_mouse = 1; 1301 GGI_set_size(); 1302 GGI_replot(); 1303 } 1304 GGI_save_frame_stl(); 1305 GGI_set_vertex(&GGI_stl_vertex, 0, GGIcanvas_height, str, GGI_saved_stl); 1306 } 1307 break; 1308 1309 case 1: /* coordinate text for first corner of zoombox */ 1310 case 2: /* coordinate text for second corner of zoombox */ 1311 GGI_save_frame_canvas(); 1312 second = (char*) strchr(str, '\r'); 1313 --i; /* transform to [0, 1] */ 1314 GGI_clear_zoombox(); 1315 if (second == NULL) { 1316 /* remove box and / or coordinates */ 1317 GGI_set_vertex(&(GGI_zoom[i][0]), 0, 0, (char*)0, GGI_saved_canvas); 1318 GGI_set_vertex(&(GGI_zoom[i][1]), 0, 0, (char*)0, GGI_saved_canvas); 1319 break; 1320 } else { 1321 *second = '\0'; /* XXX this assumes that str is writable XXX */ 1322 second++; 1323 GGI_set_vertex(&(GGI_zoom[i][0]), GGI_mouse_x, GGI_mouse_y - GGI_font_height - 1, str, GGI_saved_canvas); 1324 GGI_set_vertex(&(GGI_zoom[i][1]), GGI_mouse_x, GGI_mouse_y + 1, second, GGI_saved_canvas); 1325 GGI_zoombox[i].x = GGI_mouse_x; 1326 GGI_zoombox[i].y = GGI_mouse_y; 1327 } 1328 break; 1329 } 1330 GGI_needs_update++; 1331} 1332 1333TERM_PUBLIC void 1334GGI_set_ruler(int x, int y) 1335{ 1336 if (x < 0) { 1337 1338 /* turn ruler off */ 1339 GGI_clear_hline(0, GGIwidth, GGI_ruler.y); 1340 GGI_clear_vline(0, GGIcanvas_height, GGI_ruler.x); 1341 GGI_ruler.x = -1; 1342 GGI_ruler.y = -1; 1343 1344 } else { 1345 GGI_ruler.x = x; 1346 GGI_ruler.y = GGI_y(y); 1347 } 1348 GGI_needs_update++; 1349} 1350 1351TERM_PUBLIC void 1352GGI_set_cursor(int c, int x, int y) 1353{ 1354 /* TODO */ 1355 switch (c) { 1356 case 0: 1357 GGI_abort_zooming(); 1358 break; 1359 case 1: 1360 case 2: 1361 case 3: 1362 default: 1363 /* XXX not implemented */ 1364 break; 1365 } 1366 GGI_needs_update++; 1367} 1368 1369TERM_PUBLIC void 1370GGI_set_clipboard(const char s[]) 1371{ 1372 /* XXX: not implemented */ 1373 (void) s; /* avoid -Wunused */ 1374} 1375 1376#endif 1377 1378TERM_PUBLIC int 1379GGI_make_palette(t_sm_palette *palette) 1380{ 1381 /* reallocate only, if it has changed */ 1382 if (palette && (GGI_save_pal.colorFormulae < 0 1383 || palette->colorFormulae != GGI_save_pal.colorFormulae 1384 || palette->colorMode != GGI_save_pal.colorMode 1385 || palette->formulaR != GGI_save_pal.formulaR 1386 || palette->formulaG != GGI_save_pal.formulaG 1387 || palette->formulaB != GGI_save_pal.formulaB 1388 || palette->positive != GGI_save_pal.positive)) { 1389 int i; 1390 ggi_color color; 1391 for (i = 0; i < ggi_pm3d_colors; i++) { 1392 color.r = (short)floor(palette->color[i].r * 0xffff), 1393 color.g = (short)floor(palette->color[i].g * 0xffff), 1394 color.b = (short)floor(palette->color[i].b * 0xffff), 1395 GGI_smooth_colors[i] = ggiMapColor(GGIvisual, &color); 1396 } 1397 GGI_save_pal = *palette; 1398 } else { 1399 return ggi_pm3d_colors; 1400 } 1401 return 0; 1402} 1403 1404TERM_PUBLIC void 1405GGI_previous_palette() 1406{ 1407#if 0 1408#ifdef ENABLE_XMI 1409 fprintf(stderr, "(GGI_previous_palette) \n"); 1410 if (GGI_miPaintedSet) { 1411 miPoint offset; 1412 offset.x = 0; offset.y = 0; 1413 miCopyPaintedSetToVisual(GGIvisual, GGI_miGC, GGI_miPaintedSet, offset); 1414 miClearPaintedSet(GGIvisual, GGI_miPaintedSet); 1415 } 1416#endif 1417#endif 1418} 1419 1420TERM_PUBLIC void 1421GGI_set_color(struct t_colorspec *colorspec) 1422{ 1423 ggi_color rgb; 1424 double gray = colorspec->value; 1425 1426 if (colorspec->type == TC_RGB) { 1427 rgb.r = ((colorspec->lt >> 16) & 0xff) * (65535./255.); 1428 rgb.g = ((colorspec->lt >> 8) & 0xff) * (65535./255.); 1429 rgb.b = ((colorspec->lt) & 0xff) * (65535./255.); 1430 ggiSetGCForeground(GGIvisual, ggiMapColor(GGIvisual,&rgb)); 1431 } 1432 1433 if (colorspec->type != TC_FRAC) 1434 return; 1435 1436 if (GGIvisual) { 1437 int idx = (gray <= 0) ? 0 : (int)(gray * ggi_pm3d_colors); 1438 if (idx >= ggi_pm3d_colors) 1439 idx = ggi_pm3d_colors - 1; 1440 ggiSetGCForeground(GGIvisual, GGI_smooth_colors[idx]); 1441#ifdef ENABLE_XMI 1442 GGI_miGC->pixels[1] = GGI_smooth_colors[idx]; 1443#endif 1444 } 1445} 1446 1447#ifdef ENABLE_XMI 1448TERM_PUBLIC void 1449GGI_filled_polygon(int points, gpiPoint *corners) 1450{ 1451 static miPoint offset = {0, 0}; 1452 if (GGI_miPaintedSet) { 1453#define MI_POINTS 4 1454 miPoint mi_corners[MI_POINTS]; 1455 unsigned int i; 1456 if (MI_POINTS != points) { 1457 fprintf(stderr, "(GGI_filled_polygon) internal error %s:%d\n", __FILE__, __LINE__); 1458 return; 1459 } 1460 for (i = 0; i < MI_POINTS; i++) { 1461 mi_corners[i].x = corners[i].x; 1462 mi_corners[i].y = GGI_y(corners[i].y); 1463 } 1464 miFillPolygon(GGIvisual, GGI_miPaintedSet, GGI_miGC, 1465 MI_SHAPE_GENERAL, MI_COORD_MODE_ORIGIN, MI_POINTS, mi_corners); 1466 miCopyPaintedSetToVisual(GGIvisual, GGI_miGC, GGI_miPaintedSet, offset); 1467 miClearPaintedSet(GGIvisual, GGI_miPaintedSet); 1468 } 1469} 1470#endif 1471 1472#endif /* TERM_BODY */ 1473 1474#ifdef TERM_TABLE 1475 1476TERM_TABLE_START(ggi_driver) 1477 "ggi", "GGI target", 1478 GGI_XMAX, GGI_YMAX, GGI_VCHAR, GGI_HCHAR, GGI_VTIC, GGI_HTIC, 1479 GGI_options, GGI_init, GGI_reset, GGI_text, 1480 null_scale, GGI_graphics, GGI_move, GGI_vector, 1481 GGI_linetype, GGI_put_text, 1482 0, /* angle */ 1483 0, /* justify text */ 1484 0, /* point */ 1485 0, /* arrow */ 1486 0, /* set_font */ 1487 0, /* set_pointsize */ 1488 TERM_CAN_MULTIPLOT, 1489 GGI_suspend, 1490 GGI_resume, 1491 GGI_fillbox, 1492 0 /* linewidth */ 1493#ifdef USE_MOUSE 1494 , GGI_waitforinput, GGI_put_tmptext, GGI_set_ruler, GGI_set_cursor, GGI_set_clipboard 1495#endif 1496 , GGI_make_palette, 1497 GGI_previous_palette, 1498 GGI_set_color, 1499#ifdef ENABLE_XMI 1500 GGI_filled_polygon 1501#else 1502 0 /* GGI_filled_polygon */ 1503#endif 1504TERM_TABLE_END(ggi_driver) 1505 1506#endif /* TERM_TABLE */ 1507#endif /* TERM_PROTO_ONLY */ 1508 1509#ifdef TERM_HELP 1510START_HELP(ggi) 1511"1 ggi", 1512"?commands set terminal ggi", 1513"?set terminal ggi", 1514"?set term ggi", 1515"?terminal ggi", 1516"?term ggi", 1517"?ggi", 1518" Legacy terminal driver for the GGI (General Graphics Interface) project." 1519"", 1520" Syntax:", 1521" set terminal ggi [acceleration <integer>] [[mode] {mode}]", 1522"", 1523" In X the window cannot be resized using window manager handles, but the", 1524" mode can be given with the mode option, e.g.:", 1525" - V1024x768", 1526" - V800x600", 1527" - V640x480", 1528" - V320x200", 1529" Please refer to the ggi documentation for other modes. The 'mode' keyword", 1530" is optional. It is recommended to select the target by environment variables", 1531" as explained in the libggi manual page. To get DGA on X, you should for", 1532" example", 1533" bash> export GGI_DISPLAY=DGA", 1534" csh> setenv GGI_DISPLAY DGA", 1535"", 1536" 'acceleration' is only used for targets which report relative pointer", 1537" motion events (e.g. DGA) and is a strictly positive integer multiplication", 1538" factor for the relative distances. The default for acceleration is 7.", 1539"", 1540" Examples:", 1541" set term ggi acc 10", 1542" set term ggi acc 1 mode V1024x768", 1543" set term ggi V1024x768" 1544END_HELP(ggi) 1545#endif 1546