00001 #include <math.h>
00002 #include <stdlib.h>
00003 #include <stdio.h>
00004 #include <string.h>
00005
00006 #include "util.h"
00007 #include "graphics.h"
00008 #include "vpr_types.h"
00009
00010
00011 #ifndef NO_GRAPHICS
00012
00013 #include <X11/Xlib.h>
00014 #include <X11/Xutil.h>
00015 #include <X11/Xos.h>
00016 #include <X11/Xatom.h>
00017
00018 #endif
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 #ifndef NO_GRAPHICS
00070
00071
00072
00073
00074
00075 #define XPOST(worldx) (((worldx)-xleft)*ps_xmult + ps_left)
00076 #define YPOST(worldy) (((worldy)-ybot)*ps_ymult + ps_bot)
00077
00078
00079
00080
00081 #define XTOWORLD(x) (((float) x)/xmult + xleft)
00082 #define YTOWORLD(y) (((float) y)/ymult + ytop)
00083
00084 #define max(a,b) (((a) > (b))? (a) : (b))
00085 #define min(a,b) ((a) > (b)? (b) : (a))
00086
00087 #define MWIDTH 104
00088 #define T_AREA_HEIGHT 24
00089 #define MAX_FONT_SIZE 40
00090 #define PI 3.141592654
00091
00092 #define BUTTON_TEXT_LEN 20
00093
00094 typedef struct
00095 {
00096 int width;
00097 int height;
00098 int xleft;
00099 int ytop;
00100 void (*fcn) (void (*drawscreen) (void));
00101 Window win;
00102 int istext;
00103 char text[BUTTON_TEXT_LEN];
00104 int ispoly;
00105 int poly[3][2];
00106 int ispressed;
00107 }
00108 t_button;
00109
00110
00111
00112
00113
00114
00115 static const int menu_font_size = 14;
00116
00117 static t_button *button;
00118 static int num_buttons;
00119
00120 static int disp_type;
00121 static Display *display;
00122 static int screen_num;
00123 static GC gc, gcxor, gc_menus;
00124 static XFontStruct *font_info[MAX_FONT_SIZE + 1];
00125 static int font_is_loaded[MAX_FONT_SIZE + 1];
00126 static unsigned int display_width, display_height;
00127 static unsigned int top_width, top_height;
00128 static Window toplevel, menu, textarea;
00129 static float xleft, xright, ytop, ybot;
00130
00131
00132 static float saved_xleft, saved_xright, saved_ytop, saved_ybot;
00133
00134 static float ps_left, ps_right, ps_top, ps_bot;
00135
00136 static float ps_xmult, ps_ymult;
00137 static float xmult, ymult;
00138 static Colormap private_cmap;
00139
00140
00141 static int currentcolor = BLACK;
00142 static int currentlinestyle = SOLID;
00143 static int currentlinewidth = 0;
00144 static int currentfontsize = 10;
00145
00146 static char message[BUFSIZE] = "\0";
00147
00148
00149 static int colors[NUM_COLOR];
00150
00151
00152 static FILE *ps;
00153
00154
00155
00156
00157 #define MAXPIXEL 15000
00158 #define MINPIXEL -15000
00159
00160
00161
00162
00163
00164
00165 static void translate_up(void (*drawscreen) (void));
00166 static void translate_left(void (*drawscreen) (void));
00167 static void translate_right(void (*drawscreen) (void));
00168 static void translate_down(void (*drawscreen) (void));
00169 static void zoom_in(void (*drawscreen) (void));
00170 static void zoom_out(void (*drawscreen) (void));
00171 static void zoom_fit(void (*drawscreen) (void));
00172 static void adjustwin(void (*drawscreen) (void));
00173 static void postscript(void (*drawscreen) (void));
00174 static void proceed(void (*drawscreen) (void));
00175 static void quit(void (*drawscreen) (void));
00176
00177 static Bool test_if_exposed(Display * disp,
00178 XEvent * event_ptr,
00179 XPointer dummy);
00180 static void map_button(int bnum);
00181 static void unmap_button(int bnum);
00182
00183
00184
00185
00186
00187
00188 static int
00189 xcoord(float worldx)
00190 {
00191
00192
00193
00194 int winx;
00195
00196 winx = (int)((worldx - xleft) * xmult + 0.5);
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 winx = max(winx, MINPIXEL);
00209 winx = min(winx, MAXPIXEL);
00210
00211 return (winx);
00212 }
00213
00214
00215 static int
00216 ycoord(float worldy)
00217 {
00218
00219
00220
00221 int winy;
00222
00223 winy = (int)((worldy - ytop) * ymult + 0.5);
00224
00225
00226 winy = max(winy, MINPIXEL);
00227 winy = min(winy, MAXPIXEL);
00228
00229 return (winy);
00230 }
00231
00232
00233 static void
00234 load_font(int pointsize)
00235 {
00236
00237
00238
00239
00240
00241 char fontname[44];
00242
00243 sprintf(fontname, "-*-helvetica-medium-r-*--*-%d0-*-*-*-*-*-*",
00244 pointsize);
00245
00246 #ifdef VERBOSE
00247 printf("Loading font: point size: %d, fontname: %s\n", pointsize,
00248 fontname);
00249 #endif
00250
00251
00252
00253 if((font_info[pointsize] = XLoadQueryFont(display, fontname)) == NULL)
00254 {
00255 fprintf(stderr, "Cannot open desired font\n");
00256 exit(-1);
00257 }
00258 }
00259
00260
00261 static void
00262 force_setcolor(int cindex)
00263 {
00264
00265 static char *ps_cnames[NUM_COLOR] =
00266 { "white", "black", "grey55", "grey75",
00267 "blue", "green", "yellow", "cyan", "red", "darkgreen", "magenta",
00268 "bisque", "lightblue", "thistle", "plum", "khaki",
00269 "coral", "turquoise", "mediumpurple", "darkslateblue", "darkkhaki"
00270 };
00271
00272 currentcolor = cindex;
00273
00274 if(disp_type == SCREEN)
00275 {
00276 XSetForeground(display, gc, colors[cindex]);
00277 }
00278 else
00279 {
00280 fprintf(ps, "%s\n", ps_cnames[cindex]);
00281 }
00282 }
00283
00284
00285 void
00286 setcolor(int cindex)
00287 {
00288
00289 if(currentcolor != cindex)
00290 force_setcolor(cindex);
00291 }
00292
00293
00294 static void
00295 force_setlinestyle(int linestyle)
00296 {
00297
00298
00299
00300
00301
00302 static char *ps_text[2] = { "linesolid", "linedashed" };
00303 static int x_vals[2] = { LineSolid, LineOnOffDash };
00304
00305 currentlinestyle = linestyle;
00306
00307 if(disp_type == SCREEN)
00308 {
00309 XSetLineAttributes(display, gc, currentlinewidth,
00310 x_vals[linestyle], CapButt, JoinMiter);
00311 }
00312 else
00313 {
00314 fprintf(ps, "%s\n", ps_text[linestyle]);
00315 }
00316 }
00317
00318
00319 void
00320 setlinestyle(int linestyle)
00321 {
00322
00323 if(linestyle != currentlinestyle)
00324 force_setlinestyle(linestyle);
00325 }
00326
00327
00328 static void
00329 force_setlinewidth(int linewidth)
00330 {
00331
00332
00333
00334
00335 static int x_vals[2] = { LineSolid, LineOnOffDash };
00336
00337 currentlinewidth = linewidth;
00338
00339 if(disp_type == SCREEN)
00340 {
00341 XSetLineAttributes(display, gc, linewidth,
00342 x_vals[currentlinestyle], CapButt, JoinMiter);
00343 }
00344 else
00345 {
00346 fprintf(ps, "%d setlinewidth\n", linewidth);
00347 }
00348 }
00349
00350
00351 void
00352 setlinewidth(int linewidth)
00353 {
00354
00355 if(linewidth != currentlinewidth)
00356 force_setlinewidth(linewidth);
00357 }
00358
00359
00360 static void
00361 force_setfontsize(int pointsize)
00362 {
00363
00364
00365
00366 if(pointsize < 1)
00367 pointsize = 1;
00368 else if(pointsize > MAX_FONT_SIZE)
00369 pointsize = MAX_FONT_SIZE;
00370
00371 currentfontsize = pointsize;
00372
00373
00374 if(disp_type == SCREEN)
00375 {
00376 if(!font_is_loaded[pointsize])
00377 {
00378 load_font(pointsize);
00379 font_is_loaded[pointsize] = 1;
00380 }
00381 XSetFont(display, gc, font_info[pointsize]->fid);
00382 }
00383
00384 else
00385 {
00386
00387
00388 fprintf(ps, "%d setfontsize\n", pointsize);
00389 }
00390 }
00391
00392
00393 void
00394 setfontsize(int pointsize)
00395 {
00396
00397
00398
00399
00400
00401 if(pointsize != currentfontsize)
00402 force_setfontsize(pointsize);
00403 }
00404
00405
00406 static void
00407 build_textarea(void)
00408 {
00409
00410
00411
00412 XSetWindowAttributes menu_attributes;
00413 unsigned long valuemask;
00414
00415 textarea = XCreateSimpleWindow(display, toplevel,
00416 0, top_height - T_AREA_HEIGHT,
00417 display_width, T_AREA_HEIGHT - 4, 2,
00418 colors[BLACK], colors[LIGHTGREY]);
00419 menu_attributes.event_mask = ExposureMask;
00420
00421 menu_attributes.do_not_propagate_mask = ButtonPressMask;
00422
00423 menu_attributes.win_gravity = SouthWestGravity;
00424 valuemask = CWWinGravity | CWEventMask | CWDontPropagate;
00425 XChangeWindowAttributes(display, textarea, valuemask, &menu_attributes);
00426 XMapWindow(display, textarea);
00427 }
00428
00429
00430 static void
00431 setpoly(int bnum,
00432 int xc,
00433 int yc,
00434 int r,
00435 float theta)
00436 {
00437
00438
00439
00440 int i;
00441
00442 button[bnum].istext = 0;
00443 button[bnum].ispoly = 1;
00444 for(i = 0; i < 3; i++)
00445 {
00446 button[bnum].poly[i][0] = (int)(xc + r * cos(theta) + 0.5);
00447 button[bnum].poly[i][1] = (int)(yc + r * sin(theta) + 0.5);
00448 theta += 2 * PI / 3;
00449 }
00450 }
00451
00452
00453 static void
00454 build_default_menu(void)
00455 {
00456
00457
00458
00459 XSetWindowAttributes menu_attributes;
00460 unsigned long valuemask;
00461 int i, xcen, x1, y1, bwid, bheight, space;
00462
00463
00464 menu = XCreateSimpleWindow(display, toplevel,
00465 top_width - MWIDTH, 0, MWIDTH - 4,
00466 display_height, 2, colors[BLACK],
00467 colors[LIGHTGREY]);
00468 menu_attributes.event_mask = ExposureMask;
00469
00470 menu_attributes.do_not_propagate_mask = ButtonPressMask;
00471
00472 menu_attributes.win_gravity = NorthEastGravity;
00473 valuemask = CWWinGravity | CWEventMask | CWDontPropagate;
00474 XChangeWindowAttributes(display, menu, valuemask, &menu_attributes);
00475 XMapWindow(display, menu);
00476
00477 num_buttons = 11;
00478 button = (t_button *) my_malloc(num_buttons * sizeof(t_button));
00479
00480
00481 bwid = 28;
00482 space = 3;
00483 y1 = 10;
00484 xcen = 51;
00485 x1 = xcen - bwid / 2;
00486 button[0].xleft = x1;
00487 button[0].ytop = y1;
00488 setpoly(0, bwid / 2, bwid / 2, bwid / 3, -PI / 2.);
00489 button[0].fcn = translate_up;
00490
00491 y1 += bwid + space;
00492 x1 = xcen - 3 * bwid / 2 - space;
00493 button[1].xleft = x1;
00494 button[1].ytop = y1;
00495 setpoly(1, bwid / 2, bwid / 2, bwid / 3, PI);
00496 button[1].fcn = translate_left;
00497
00498 x1 = xcen + bwid / 2 + space;
00499 button[2].xleft = x1;
00500 button[2].ytop = y1;
00501 setpoly(2, bwid / 2, bwid / 2, bwid / 3, 0);
00502 button[2].fcn = translate_right;
00503
00504 y1 += bwid + space;
00505 x1 = xcen - bwid / 2;
00506 button[3].xleft = x1;
00507 button[3].ytop = y1;
00508 setpoly(3, bwid / 2, bwid / 2, bwid / 3, +PI / 2.);
00509 button[3].fcn = translate_down;
00510
00511 for(i = 0; i < 4; i++)
00512 {
00513 button[i].width = bwid;
00514 button[i].height = bwid;
00515 }
00516
00517
00518
00519 y1 += bwid + space + 6;
00520 space = 8;
00521 bwid = 90;
00522 bheight = 26;
00523 x1 = xcen - bwid / 2;
00524 for(i = 4; i < num_buttons; i++)
00525 {
00526 button[i].xleft = x1;
00527 button[i].ytop = y1;
00528 y1 += bheight + space;
00529 button[i].istext = 1;
00530 button[i].ispoly = 0;
00531 button[i].width = bwid;
00532 button[i].height = bheight;
00533 }
00534
00535 strcpy(button[4].text, "Zoom In");
00536 strcpy(button[5].text, "Zoom Out");
00537 strcpy(button[6].text, "Zoom Fit");
00538 strcpy(button[7].text, "Window");
00539 strcpy(button[8].text, "PostScript");
00540 strcpy(button[9].text, "Proceed");
00541 strcpy(button[10].text, "Exit");
00542
00543 button[4].fcn = zoom_in;
00544 button[5].fcn = zoom_out;
00545 button[6].fcn = zoom_fit;
00546 button[7].fcn = adjustwin;
00547 button[8].fcn = postscript;
00548 button[9].fcn = proceed;
00549 button[10].fcn = quit;
00550
00551 for(i = 0; i < num_buttons; i++)
00552 map_button(i);
00553 }
00554
00555
00556 static void
00557 map_button(int bnum)
00558 {
00559
00560
00561
00562 button[bnum].win = XCreateSimpleWindow(display, menu,
00563 button[bnum].xleft,
00564 button[bnum].ytop,
00565 button[bnum].width,
00566 button[bnum].height, 0,
00567 colors[WHITE], colors[LIGHTGREY]);
00568 XMapWindow(display, button[bnum].win);
00569 XSelectInput(display, button[bnum].win, ButtonPressMask);
00570 button[bnum].ispressed = 1;
00571 }
00572
00573
00574 static void
00575 unmap_button(int bnum)
00576 {
00577
00578
00579
00580 XUnmapWindow(display, button[bnum].win);
00581 }
00582
00583
00584 void
00585 create_button(char *prev_button_text,
00586 char *button_text,
00587 void (*button_func) (void (*drawscreen) (void)))
00588 {
00589
00590
00591
00592
00593
00594 int i, bnum, space;
00595
00596 space = 8;
00597
00598
00599
00600 bnum = -1;
00601 for(i = 4; i < num_buttons; i++)
00602 {
00603 if(button[i].istext == 1 &&
00604 strcmp(button[i].text, prev_button_text) == 0)
00605 {
00606 bnum = i + 1;
00607 break;
00608 }
00609 }
00610
00611 if(bnum == -1)
00612 {
00613 printf
00614 ("Error in create_button: button with text %s not found.\n",
00615 prev_button_text);
00616 exit(1);
00617 }
00618
00619 num_buttons++;
00620 button = (t_button *) my_realloc(button, num_buttons * sizeof(t_button));
00621
00622
00623
00624
00625 button[num_buttons - 1].xleft = button[num_buttons - 2].xleft;
00626 button[num_buttons - 1].ytop = button[num_buttons - 2].ytop +
00627 button[num_buttons - 2].height + space;
00628 button[num_buttons - 1].height = button[num_buttons - 2].height;
00629 button[num_buttons - 1].width = button[num_buttons - 2].width;
00630 map_button(num_buttons - 1);
00631
00632
00633 for(i = num_buttons - 1; i > bnum; i--)
00634 {
00635 button[i].ispoly = button[i - 1].ispoly;
00636
00637
00638
00639 button[i].istext = button[i - 1].istext;
00640 strcpy(button[i].text, button[i - 1].text);
00641 button[i].fcn = button[i - 1].fcn;
00642 button[i].ispressed = button[i - 1].ispressed;
00643 }
00644
00645 button[bnum].istext = 1;
00646 button[bnum].ispoly = 0;
00647 my_strncpy(button[bnum].text, button_text, BUTTON_TEXT_LEN);
00648 button[bnum].fcn = button_func;
00649 button[bnum].ispressed = 1;
00650 }
00651
00652
00653 void
00654 destroy_button(char *button_text)
00655 {
00656
00657
00658
00659 int i, bnum;
00660
00661 bnum = -1;
00662 for(i = 4; i < num_buttons; i++)
00663 {
00664 if(button[i].istext == 1 &&
00665 strcmp(button[i].text, button_text) == 0)
00666 {
00667 bnum = i;
00668 break;
00669 }
00670 }
00671
00672 if(bnum == -1)
00673 {
00674 printf
00675 ("Error in destroy_button: button with text %s not found.\n",
00676 button_text);
00677 exit(1);
00678 }
00679
00680 for(i = bnum + 1; i < num_buttons; i++)
00681 {
00682 button[i - 1].ispoly = button[i].ispoly;
00683
00684
00685
00686 button[i - 1].istext = button[i].istext;
00687 strcpy(button[i - 1].text, button[i].text);
00688 button[i - 1].fcn = button[i].fcn;
00689 button[i - 1].ispressed = button[i].ispressed;
00690 }
00691
00692 unmap_button(num_buttons - 1);
00693 num_buttons--;
00694 button = (t_button *) my_realloc(button, num_buttons * sizeof(t_button));
00695 }
00696
00697
00698 void
00699 init_graphics(char *window_name)
00700 {
00701
00702
00703
00704
00705
00706 char *display_name = NULL;
00707 int x, y;
00708 unsigned int border_width = 2;
00709 XTextProperty windowName;
00710
00711
00712 char *cnames[NUM_COLOR] = { "white", "black", "grey55", "grey75", "blue",
00713 "green", "yellow", "cyan", "red", "RGBi:0.0/0.5/0.0", "magenta",
00714 "bisque", "lightblue", "thistle", "plum", "khaki",
00715 "coral", "turquoise", "mediumpurple", "darkslateblue", "darkkhaki"
00716 };
00717
00718 XColor exact_def;
00719 Colormap cmap;
00720 int i;
00721 unsigned long valuemask = 0;
00722 XGCValues values;
00723 XEvent event;
00724
00725
00726 disp_type = SCREEN;
00727
00728 for(i = 0; i <= MAX_FONT_SIZE; i++)
00729 font_is_loaded[i] = 0;
00730
00731
00732 if((display = XOpenDisplay(display_name)) == NULL)
00733 {
00734 fprintf(stderr, "Cannot connect to X server %s\n",
00735 XDisplayName(display_name));
00736 exit(-1);
00737 }
00738
00739
00740 screen_num = DefaultScreen(display);
00741 display_width = DisplayWidth(display, screen_num);
00742 display_height = DisplayHeight(display, screen_num);
00743
00744 x = y = 0;
00745
00746 top_width = 2 * display_width / 3;
00747 top_height = 4 * display_height / 5;
00748
00749 cmap = DefaultColormap(display, screen_num);
00750 private_cmap = None;
00751
00752 for(i = 0; i < NUM_COLOR; i++)
00753 {
00754 if(!XParseColor(display, cmap, cnames[i], &exact_def))
00755 {
00756 fprintf(stderr, "Color name %s not in database",
00757 cnames[i]);
00758 exit(-1);
00759 }
00760 if(!XAllocColor(display, cmap, &exact_def))
00761 {
00762 fprintf(stderr, "Couldn't allocate color %s.\n",
00763 cnames[i]);
00764
00765 if(private_cmap == None)
00766 {
00767 fprintf(stderr,
00768 "Will try to allocate a private colourmap.\n");
00769 fprintf(stderr,
00770 "Colours will only display correctly when your "
00771 "cursor is in the graphics window.\n"
00772 "Exit other colour applications and rerun this "
00773 "program if you don't like that.\n\n");
00774
00775 private_cmap =
00776 XCopyColormapAndFree(display, cmap);
00777 cmap = private_cmap;
00778 if(!XAllocColor(display, cmap, &exact_def))
00779 {
00780 fprintf(stderr,
00781 "Couldn't allocate color %s as private.\n",
00782 cnames[i]);
00783 exit(1);
00784 }
00785 }
00786
00787 else
00788 {
00789 fprintf(stderr,
00790 "Couldn't allocate color %s as private.\n",
00791 cnames[i]);
00792 exit(1);
00793 }
00794 }
00795 colors[i] = exact_def.pixel;
00796 }
00797
00798 toplevel =
00799 XCreateSimpleWindow(display, RootWindow(display, screen_num), x, y,
00800 top_width, top_height, border_width,
00801 colors[BLACK], colors[WHITE]);
00802
00803 if(private_cmap != None)
00804 XSetWindowColormap(display, toplevel, private_cmap);
00805
00806
00807
00808 XSelectInput(display, toplevel, ExposureMask | StructureNotifyMask |
00809 ButtonPressMask);
00810
00811
00812
00813 gc = XCreateGC(display, toplevel, valuemask, &values);
00814 gc_menus = XCreateGC(display, toplevel, valuemask, &values);
00815
00816
00817 values.function = GXxor;
00818 values.foreground = colors[BLACK];
00819 gcxor = XCreateGC(display, toplevel, (GCFunction | GCForeground),
00820 &values);
00821
00822
00823 load_font(menu_font_size);
00824 font_is_loaded[menu_font_size] = 1;
00825 XSetFont(display, gc_menus, font_info[menu_font_size]->fid);
00826
00827
00828
00829 force_setfontsize(currentfontsize);
00830 force_setcolor(currentcolor);
00831 force_setlinestyle(currentlinestyle);
00832 force_setlinewidth(currentlinewidth);
00833
00834 XStringListToTextProperty(&window_name, 1, &windowName);
00835 XSetWMName(display, toplevel, &windowName);
00836
00837
00838
00839
00840
00841
00842 free(windowName.value);
00843
00844 XMapWindow(display, toplevel);
00845 build_textarea();
00846 build_default_menu();
00847
00848
00849
00850
00851
00852
00853
00854
00855 XPeekIfEvent(display, &event, test_if_exposed, NULL);
00856 }
00857
00858
00859 static Bool
00860 test_if_exposed(Display * disp,
00861 XEvent * event_ptr,
00862 XPointer dummy)
00863 {
00864
00865
00866
00867
00868 if(event_ptr->type == Expose)
00869 {
00870 return (True);
00871 }
00872
00873 return (False);
00874 }
00875
00876
00877 static void
00878 menutext(Window win,
00879 int xc,
00880 int yc,
00881 char *text)
00882 {
00883
00884
00885
00886 int len, width;
00887
00888 len = strlen(text);
00889 width = XTextWidth(font_info[menu_font_size], text, len);
00890 XDrawString(display, win, gc_menus, xc - width / 2, yc +
00891 (font_info[menu_font_size]->ascent -
00892 font_info[menu_font_size]->descent) / 2, text, len);
00893 }
00894
00895
00896 static void
00897 drawbut(int bnum)
00898 {
00899
00900
00901
00902 int width, height, thick, i, ispressed;
00903 XPoint mypoly[6];
00904
00905 ispressed = button[bnum].ispressed;
00906 thick = 2;
00907 width = button[bnum].width;
00908 height = button[bnum].height;
00909
00910 if(ispressed)
00911 {
00912 XSetForeground(display, gc_menus, colors[BLACK]);
00913 }
00914 else
00915 {
00916 XSetForeground(display, gc_menus, colors[WHITE]);
00917 }
00918
00919
00920
00921
00922 mypoly[0].x = 0;
00923 mypoly[0].y = height;
00924 mypoly[1].x = 0;
00925 mypoly[1].y = 0;
00926 mypoly[2].x = width;
00927 mypoly[2].y = 0;
00928 mypoly[3].x = width - thick;
00929 mypoly[3].y = thick;
00930 mypoly[4].x = thick;
00931 mypoly[4].y = thick;
00932 mypoly[5].x = thick;
00933 mypoly[5].y = height - thick;
00934 XFillPolygon(display, button[bnum].win, gc_menus, mypoly, 6, Convex,
00935 CoordModeOrigin);
00936
00937
00938 if(ispressed)
00939 {
00940 XSetForeground(display, gc_menus, colors[WHITE]);
00941 }
00942 else
00943 {
00944 XSetForeground(display, gc_menus, colors[BLACK]);
00945 }
00946 mypoly[0].x = 0;
00947 mypoly[0].y = height;
00948 mypoly[1].x = width;
00949 mypoly[1].y = height;
00950 mypoly[2].x = width;
00951 mypoly[2].y = 0;
00952 mypoly[3].x = width - thick;
00953 mypoly[3].y = thick;
00954 mypoly[4].x = width - thick;
00955 mypoly[4].y = height - thick;
00956 mypoly[5].x = thick;
00957 mypoly[5].y = height - thick;
00958 XFillPolygon(display, button[bnum].win, gc_menus, mypoly, 6, Convex,
00959 CoordModeOrigin);
00960
00961
00962 if(ispressed)
00963 {
00964 XSetForeground(display, gc_menus, colors[DARKGREY]);
00965 }
00966 else
00967 {
00968 XSetForeground(display, gc_menus, colors[LIGHTGREY]);
00969 }
00970
00971
00972 XFillRectangle(display, button[bnum].win, gc_menus, thick, thick,
00973 width - 2 * thick, height - 2 * thick);
00974
00975
00976 if(button[bnum].ispoly)
00977 {
00978 for(i = 0; i < 3; i++)
00979 {
00980 mypoly[i].x = button[bnum].poly[i][0];
00981 mypoly[i].y = button[bnum].poly[i][1];
00982 }
00983 XSetForeground(display, gc_menus, colors[BLACK]);
00984 XFillPolygon(display, button[bnum].win, gc_menus, mypoly, 3,
00985 Convex, CoordModeOrigin);
00986 }
00987
00988
00989 if(button[bnum].istext)
00990 {
00991 XSetForeground(display, gc_menus, colors[BLACK]);
00992 menutext(button[bnum].win, button[bnum].width / 2,
00993 button[bnum].height / 2, button[bnum].text);
00994 }
00995 }
00996
00997
00998 static void
00999 turn_on_off(int pressed)
01000 {
01001
01002
01003
01004
01005 int i;
01006
01007 for(i = 0; i < num_buttons; i++)
01008 {
01009 button[i].ispressed = pressed;
01010 drawbut(i);
01011 }
01012 }
01013
01014
01015 static int
01016 which_button(Window win)
01017 {
01018 int i;
01019
01020 for(i = 0; i < num_buttons; i++)
01021 {
01022 if(button[i].win == win)
01023 return (i);
01024 }
01025 printf("Error: Unknown button ID in which_button.\n");
01026 return (0);
01027 }
01028
01029
01030 static void
01031 drawmenu(void)
01032 {
01033 int i;
01034
01035 for(i = 0; i < num_buttons; i++)
01036 {
01037 drawbut(i);
01038 }
01039 }
01040
01041
01042 static void
01043 update_transform(void)
01044 {
01045
01046
01047
01048
01049 float mult, y1, y2, x1, x2;
01050
01051
01052 xmult = ((float)top_width - 1. - MWIDTH) / (xright - xleft);
01053 ymult = ((float)top_height - 1. - T_AREA_HEIGHT) / (ybot - ytop);
01054
01055 if(fabs(xmult) <= fabs(ymult))
01056 {
01057 mult = fabs(ymult / xmult);
01058 y1 = ytop - (ybot - ytop) * (mult - 1.) / 2.;
01059 y2 = ybot + (ybot - ytop) * (mult - 1.) / 2.;
01060 ytop = y1;
01061 ybot = y2;
01062 }
01063 else
01064 {
01065 mult = fabs(xmult / ymult);
01066 x1 = xleft - (xright - xleft) * (mult - 1.) / 2.;
01067 x2 = xright + (xright - xleft) * (mult - 1.) / 2.;
01068 xleft = x1;
01069 xright = x2;
01070 }
01071 xmult = ((float)top_width - 1. - MWIDTH) / (xright - xleft);
01072 ymult = ((float)top_height - 1. - T_AREA_HEIGHT) / (ybot - ytop);
01073 }
01074
01075
01076 static void
01077 update_ps_transform(void)
01078 {
01079
01080
01081
01082
01083
01084
01085
01086 float ps_width, ps_height;
01087
01088 ps_width = 540.;
01089 ps_height = 720.;
01090
01091 ps_xmult = ps_width / (xright - xleft);
01092 ps_ymult = ps_height / (ytop - ybot);
01093
01094
01095
01096 if(fabs(ps_xmult) <= fabs(ps_ymult))
01097 {
01098 ps_left = 36.;
01099 ps_right = 36. + ps_width;
01100 ps_bot = 396. - fabs(ps_xmult * (ytop - ybot)) / 2.;
01101 ps_top = 396. + fabs(ps_xmult * (ytop - ybot)) / 2.;
01102
01103 ps_ymult = (ps_xmult * ps_ymult < 0) ? -ps_xmult : ps_xmult;
01104 }
01105 else
01106 {
01107 ps_bot = 36.;
01108 ps_top = 36. + ps_height;
01109 ps_left = 306. - fabs(ps_ymult * (xright - xleft)) / 2.;
01110 ps_right = 306. + fabs(ps_ymult * (xright - xleft)) / 2.;
01111
01112 ps_xmult = (ps_xmult * ps_ymult < 0) ? -ps_ymult : ps_ymult;
01113 }
01114 }
01115
01116
01117 void
01118 event_loop(void (*act_on_button) (float x,
01119 float y),
01120 void (*drawscreen) (void))
01121 {
01122
01123
01124
01125
01126
01127
01128 XEvent report;
01129 int bnum;
01130 float x, y;
01131
01132 #define OFF 1
01133 #define ON 0
01134
01135 turn_on_off(ON);
01136 while(1)
01137 {
01138 XNextEvent(display, &report);
01139 switch (report.type)
01140 {
01141 case Expose:
01142 #ifdef VERBOSE
01143 printf("Got an expose event.\n");
01144 printf("Count is: %d.\n", report.xexpose.count);
01145 printf("Window ID is: %d.\n", report.xexpose.window);
01146 #endif
01147 if(report.xexpose.count != 0)
01148 break;
01149 if(report.xexpose.window == menu)
01150 drawmenu();
01151 else if(report.xexpose.window == toplevel)
01152 drawscreen();
01153 else if(report.xexpose.window == textarea)
01154 draw_message();
01155 break;
01156 case ConfigureNotify:
01157 top_width = report.xconfigure.width;
01158 top_height = report.xconfigure.height;
01159 update_transform();
01160 #ifdef VERBOSE
01161 printf("Got a ConfigureNotify.\n");
01162 printf("New width: %d New height: %d.\n", top_width,
01163 top_height);
01164 #endif
01165 break;
01166 case ButtonPress:
01167 #ifdef VERBOSE
01168 printf("Got a buttonpress.\n");
01169 printf("Window ID is: %d.\n", report.xbutton.window);
01170 #endif
01171 if(report.xbutton.window == toplevel)
01172 {
01173 x = XTOWORLD(report.xbutton.x);
01174 y = YTOWORLD(report.xbutton.y);
01175 act_on_button(x, y);
01176 }
01177 else
01178 {
01179 bnum = which_button(report.xbutton.window);
01180 #ifdef VERBOSE
01181 printf("Button number is %d\n", bnum);
01182 #endif
01183 button[bnum].ispressed = 1;
01184 drawbut(bnum);
01185 XFlush(display);
01186 button[bnum].fcn(drawscreen);
01187 button[bnum].ispressed = 0;
01188 drawbut(bnum);
01189 if(button[bnum].fcn == proceed)
01190 {
01191 turn_on_off(OFF);
01192 flushinput();
01193 return;
01194
01195 }
01196 }
01197 break;
01198 }
01199 }
01200 }
01201
01202
01203
01204 void
01205 clearscreen(void)
01206 {
01207 int savecolor;
01208
01209 if(disp_type == SCREEN)
01210 {
01211 XClearWindow(display, toplevel);
01212 }
01213 else
01214 {
01215
01216
01217
01218 savecolor = currentcolor;
01219 setcolor(WHITE);
01220 fprintf(ps, "clippath fill\n\n");
01221 setcolor(savecolor);
01222 }
01223 }
01224
01225 static int
01226 rect_off_screen(float x1,
01227 float y1,
01228 float x2,
01229 float y2)
01230 {
01231
01232
01233
01234
01235
01236
01237
01238
01239 float xmin, xmax, ymin, ymax;
01240
01241 xmin = min(xleft, xright);
01242 if(x1 < xmin && x2 < xmin)
01243 return (1);
01244
01245 xmax = max(xleft, xright);
01246 if(x1 > xmax && x2 > xmax)
01247 return (1);
01248
01249 ymin = min(ytop, ybot);
01250 if(y1 < ymin && y2 < ymin)
01251 return (1);
01252
01253 ymax = max(ytop, ybot);
01254 if(y1 > ymax && y2 > ymax)
01255 return (1);
01256
01257 return (0);
01258 }
01259
01260
01261 void
01262 drawline(float x1,
01263 float y1,
01264 float x2,
01265 float y2)
01266 {
01267
01268
01269
01270
01271 if(rect_off_screen(x1, y1, x2, y2))
01272 return;
01273
01274 if(disp_type == SCREEN)
01275 {
01276
01277 XDrawLine(display, toplevel, gc, xcoord(x1), ycoord(y1),
01278 xcoord(x2), ycoord(y2));
01279 }
01280 else
01281 {
01282 fprintf(ps, "%.2f %.2f %.2f %.2f drawline\n", XPOST(x1),
01283 YPOST(y1), XPOST(x2), YPOST(y2));
01284 }
01285 }
01286
01287 void
01288 drawrect(float x1,
01289 float y1,
01290 float x2,
01291 float y2)
01292 {
01293
01294
01295
01296 unsigned int width, height;
01297 int xw1, yw1, xw2, yw2, xl, yt;
01298
01299 if(rect_off_screen(x1, y1, x2, y2))
01300 return;
01301
01302 if(disp_type == SCREEN)
01303 {
01304
01305 xw1 = xcoord(x1);
01306 xw2 = xcoord(x2);
01307 yw1 = ycoord(y1);
01308 yw2 = ycoord(y2);
01309 xl = min(xw1, xw2);
01310 yt = min(yw1, yw2);
01311 width = abs(xw1 - xw2);
01312 height = abs(yw1 - yw2);
01313 XDrawRectangle(display, toplevel, gc, xl, yt, width, height);
01314 }
01315 else
01316 {
01317 fprintf(ps, "%.2f %.2f %.2f %.2f drawrect\n", XPOST(x1),
01318 YPOST(y1), XPOST(x2), YPOST(y2));
01319 }
01320 }
01321
01322
01323 void
01324 fillrect(float x1,
01325 float y1,
01326 float x2,
01327 float y2)
01328 {
01329
01330
01331
01332 unsigned int width, height;
01333 int xw1, yw1, xw2, yw2, xl, yt;
01334
01335 if(rect_off_screen(x1, y1, x2, y2))
01336 return;
01337
01338 if(disp_type == SCREEN)
01339 {
01340
01341 xw1 = xcoord(x1);
01342 xw2 = xcoord(x2);
01343 yw1 = ycoord(y1);
01344 yw2 = ycoord(y2);
01345 xl = min(xw1, xw2);
01346 yt = min(yw1, yw2);
01347 width = abs(xw1 - xw2);
01348 height = abs(yw1 - yw2);
01349 XFillRectangle(display, toplevel, gc, xl, yt, width, height);
01350 }
01351 else
01352 {
01353 fprintf(ps, "%.2f %.2f %.2f %.2f fillrect\n", XPOST(x1),
01354 YPOST(y1), XPOST(x2), YPOST(y2));
01355 }
01356 }
01357
01358
01359 static float
01360 angnorm(float ang)
01361 {
01362
01363
01364 int scale;
01365
01366 if(ang < 0)
01367 {
01368 scale = (int)(ang / 360. - 1);
01369 }
01370 else
01371 {
01372 scale = (int)(ang / 360.);
01373 }
01374 ang = ang - scale * 360.;
01375 return (ang);
01376 }
01377
01378
01379 void
01380 drawarc(float xc,
01381 float yc,
01382 float rad,
01383 float startang,
01384 float angextent)
01385 {
01386
01387
01388
01389
01390
01391
01392
01393 int xl, yt;
01394 unsigned int width, height;
01395
01396
01397
01398
01399 if(rect_off_screen(xc - rad, yc - rad, xc + rad, yc + rad))
01400 return;
01401
01402
01403
01404 if(fabs(angextent) > 360.)
01405 angextent = 360.;
01406
01407 startang = angnorm(startang);
01408
01409 if(disp_type == SCREEN)
01410 {
01411 xl = (int)(xcoord(xc) - fabs(xmult * rad));
01412 yt = (int)(ycoord(yc) - fabs(ymult * rad));
01413 width = (unsigned int)(2 * fabs(xmult * rad));
01414 height = width;
01415 XDrawArc(display, toplevel, gc, xl, yt, width, height,
01416 (int)(startang * 64), (int)(angextent * 64));
01417 }
01418 else
01419 {
01420 fprintf(ps, "%.2f %.2f %.2f %.2f %.2f %s stroke\n", XPOST(xc),
01421 YPOST(yc), fabs(rad * ps_xmult), startang,
01422 startang + angextent,
01423 (angextent < 0) ? "drawarcn" : "drawarc");
01424 }
01425 }
01426
01427
01428 void
01429 fillarc(float xc,
01430 float yc,
01431 float rad,
01432 float startang,
01433 float angextent)
01434 {
01435
01436
01437
01438
01439 int xl, yt;
01440 unsigned int width, height;
01441
01442
01443
01444
01445 if(rect_off_screen(xc - rad, yc - rad, xc + rad, yc + rad))
01446 return;
01447
01448
01449
01450
01451 if(fabs(angextent) > 360.)
01452 angextent = 360.;
01453
01454 startang = angnorm(startang);
01455
01456 if(disp_type == SCREEN)
01457 {
01458 xl = (int)(xcoord(xc) - fabs(xmult * rad));
01459 yt = (int)(ycoord(yc) - fabs(ymult * rad));
01460 width = (unsigned int)(2 * fabs(xmult * rad));
01461 height = width;
01462 XFillArc(display, toplevel, gc, xl, yt, width, height,
01463 (int)(startang * 64), (int)(angextent * 64));
01464 }
01465 else
01466 {
01467 fprintf(ps, "%.2f %.2f %.2f %.2f %.2f %s\n", fabs(rad * ps_xmult),
01468 startang, startang + angextent, XPOST(xc), YPOST(yc),
01469 (angextent < 0) ? "fillarcn" : "fillarc");
01470 }
01471 }
01472
01473
01474 void
01475 fillpoly(t_point * points,
01476 int npoints)
01477 {
01478
01479 XPoint transpoints[MAXPTS];
01480 int i;
01481 float xmin, ymin, xmax, ymax;
01482
01483 if(npoints > MAXPTS)
01484 {
01485 printf
01486 ("Error in fillpoly: Only %d points allowed per polygon.\n",
01487 MAXPTS);
01488 printf("%d points were requested. Polygon is not drawn.\n",
01489 npoints);
01490 return;
01491 }
01492
01493
01494
01495
01496 xmin = xmax = points[0].x;
01497 ymin = ymax = points[0].y;
01498
01499 for(i = 1; i < npoints; i++)
01500 {
01501 xmin = min(xmin, points[i].x);
01502 xmax = max(xmax, points[i].x);
01503 ymin = min(ymin, points[i].y);
01504 ymax = max(ymax, points[i].y);
01505 }
01506
01507 if(rect_off_screen(xmin, ymin, xmax, ymax))
01508 return;
01509
01510 if(disp_type == SCREEN)
01511 {
01512 for(i = 0; i < npoints; i++)
01513 {
01514 transpoints[i].x = (short)xcoord(points[i].x);
01515 transpoints[i].y = (short)ycoord(points[i].y);
01516 }
01517 XFillPolygon(display, toplevel, gc, transpoints, npoints, Complex,
01518 CoordModeOrigin);
01519 }
01520 else
01521 {
01522 fprintf(ps, "\n");
01523
01524 for(i = npoints - 1; i >= 0; i--)
01525 fprintf(ps, "%.2f %.2f\n", XPOST(points[i].x),
01526 YPOST(points[i].y));
01527
01528 fprintf(ps, "%d fillpoly\n", npoints);
01529 }
01530 }
01531
01532 void
01533 drawtext(float xc,
01534 float yc,
01535 const char *text,
01536 float boundx)
01537 {
01538
01539
01540
01541 int len, width, xw_off, yw_off;
01542
01543 len = strlen(text);
01544 width = XTextWidth(font_info[currentfontsize], text, len);
01545 if(width > fabs(boundx * xmult))
01546 return;
01547
01548 xw_off = width / (2. * xmult);
01549
01550
01551 yw_off = (font_info[currentfontsize]->ascent +
01552 2 * font_info[currentfontsize]->descent) / (2. * ymult);
01553
01554
01555
01556
01557
01558
01559 if(rect_off_screen(xc - xw_off, yc - yw_off, xc + xw_off, yc + yw_off))
01560 return;
01561
01562 if(disp_type == SCREEN)
01563 {
01564 XDrawString(display, toplevel, gc, xcoord(xc) - width / 2,
01565 ycoord(yc) + (font_info[currentfontsize]->ascent -
01566 font_info[currentfontsize]->descent) /
01567 2, text, len);
01568 }
01569 else
01570 {
01571 fprintf(ps, "(%s) %.2f %.2f censhow\n", text, XPOST(xc),
01572 YPOST(yc));
01573 }
01574 }
01575
01576
01577 void
01578 flushinput(void)
01579 {
01580 if(disp_type != SCREEN)
01581 return;
01582 XFlush(display);
01583 }
01584
01585
01586 void
01587 init_world(float x1,
01588 float y1,
01589 float x2,
01590 float y2)
01591 {
01592
01593
01594
01595 xleft = x1;
01596 xright = x2;
01597 ytop = y1;
01598 ybot = y2;
01599
01600 saved_xleft = xleft;
01601 saved_xright = xright;
01602 saved_ytop = ytop;
01603 saved_ybot = ybot;
01604
01605 if(disp_type == SCREEN)
01606 {
01607 update_transform();
01608 }
01609 else
01610 {
01611 update_ps_transform();
01612 }
01613 }
01614
01615
01616 void
01617 draw_message(void)
01618 {
01619
01620
01621
01622 int len, width, savefontsize, savecolor;
01623 float ylow;
01624
01625 if(disp_type == SCREEN)
01626 {
01627 XClearWindow(display, textarea);
01628 len = strlen(message);
01629 width = XTextWidth(font_info[menu_font_size], message, len);
01630
01631 XSetForeground(display, gc_menus, colors[BLACK]);
01632 XDrawString(display, textarea, gc_menus,
01633 (top_width - MWIDTH - width) / 2,
01634 (T_AREA_HEIGHT - 4) / 2 +
01635 (font_info[menu_font_size]->ascent -
01636 font_info[menu_font_size]->descent) / 2, message,
01637 len);
01638 }
01639
01640 else
01641 {
01642
01643
01644
01645 savecolor = currentcolor;
01646 setcolor(BLACK);
01647 savefontsize = currentfontsize;
01648 setfontsize(menu_font_size - 2);
01649 ylow = ps_bot - 8.;
01650 fprintf(ps, "(%s) %.2f %.2f censhow\n", message,
01651 (ps_left + ps_right) / 2., ylow);
01652 setcolor(savecolor);
01653 setfontsize(savefontsize);
01654 }
01655 }
01656
01657
01658 void
01659 update_message(char *msg)
01660 {
01661
01662
01663
01664 my_strncpy(message, msg, BUFSIZE);
01665 draw_message();
01666 }
01667
01668
01669 static void
01670 zoom_in(void (*drawscreen) (void))
01671 {
01672
01673
01674
01675 float xdiff, ydiff;
01676
01677 xdiff = xright - xleft;
01678 ydiff = ybot - ytop;
01679 xleft += xdiff / 5.;
01680 xright -= xdiff / 5.;
01681 ytop += ydiff / 5.;
01682 ybot -= ydiff / 5.;
01683
01684 update_transform();
01685 drawscreen();
01686 }
01687
01688
01689 static void
01690 zoom_out(void (*drawscreen) (void))
01691 {
01692
01693
01694
01695 float xdiff, ydiff;
01696
01697 xdiff = xright - xleft;
01698 ydiff = ybot - ytop;
01699 xleft -= xdiff / 3.;
01700 xright += xdiff / 3.;
01701 ytop -= ydiff / 3.;
01702 ybot += ydiff / 3.;
01703
01704 update_transform();
01705 drawscreen();
01706 }
01707
01708
01709 static void
01710 zoom_fit(void (*drawscreen) (void))
01711 {
01712
01713
01714
01715
01716 xleft = saved_xleft;
01717 xright = saved_xright;
01718 ytop = saved_ytop;
01719 ybot = saved_ybot;
01720
01721 update_transform();
01722 drawscreen();
01723 }
01724
01725
01726 static void
01727 translate_up(void (*drawscreen) (void))
01728 {
01729
01730
01731
01732 float ystep;
01733
01734 ystep = (ybot - ytop) / 2.;
01735 ytop -= ystep;
01736 ybot -= ystep;
01737 update_transform();
01738 drawscreen();
01739 }
01740
01741
01742 static void
01743 translate_down(void (*drawscreen) (void))
01744 {
01745
01746
01747
01748 float ystep;
01749
01750 ystep = (ybot - ytop) / 2.;
01751 ytop += ystep;
01752 ybot += ystep;
01753 update_transform();
01754 drawscreen();
01755 }
01756
01757
01758 static void
01759 translate_left(void (*drawscreen) (void))
01760 {
01761
01762
01763
01764 float xstep;
01765
01766 xstep = (xright - xleft) / 2.;
01767 xleft -= xstep;
01768 xright -= xstep;
01769 update_transform();
01770 drawscreen();
01771 }
01772
01773
01774 static void
01775 translate_right(void (*drawscreen) (void))
01776 {
01777
01778
01779
01780 float xstep;
01781
01782 xstep = (xright - xleft) / 2.;
01783 xleft += xstep;
01784 xright += xstep;
01785 update_transform();
01786 drawscreen();
01787 }
01788
01789
01790 static void
01791 update_win(int x[2],
01792 int y[2],
01793 void (*drawscreen) (void))
01794 {
01795 float x1, x2, y1, y2;
01796
01797 x[0] = min(x[0], top_width - MWIDTH);
01798 x[1] = min(x[1], top_width - MWIDTH);
01799 y[0] = min(y[0], top_height - T_AREA_HEIGHT);
01800 y[1] = min(y[1], top_height - T_AREA_HEIGHT);
01801
01802 if((x[0] == x[1]) || (y[0] == y[1]))
01803 {
01804 printf("Illegal (zero area) window. Window unchanged.\n");
01805 return;
01806 }
01807 x1 = XTOWORLD(min(x[0], x[1]));
01808 x2 = XTOWORLD(max(x[0], x[1]));
01809 y1 = YTOWORLD(min(y[0], y[1]));
01810 y2 = YTOWORLD(max(y[0], y[1]));
01811 xleft = x1;
01812 xright = x2;
01813 ytop = y1;
01814 ybot = y2;
01815 update_transform();
01816 drawscreen();
01817 }
01818
01819
01820 static void
01821 adjustwin(void (*drawscreen) (void))
01822 {
01823
01824
01825
01826 XEvent report;
01827 int corner, xold, yold, x[2], y[2];
01828
01829 corner = 0;
01830 xold = -1;
01831 yold = -1;
01832
01833 while(corner < 2)
01834 {
01835 XNextEvent(display, &report);
01836 switch (report.type)
01837 {
01838 case Expose:
01839 #ifdef VERBOSE
01840 printf("Got an expose event.\n");
01841 printf("Count is: %d.\n", report.xexpose.count);
01842 printf("Window ID is: %d.\n", report.xexpose.window);
01843 #endif
01844 if(report.xexpose.count != 0)
01845 break;
01846 if(report.xexpose.window == menu)
01847 drawmenu();
01848 else if(report.xexpose.window == toplevel)
01849 {
01850 drawscreen();
01851 xold = -1;
01852 }
01853 else if(report.xexpose.window == textarea)
01854 draw_message();
01855 break;
01856 case ConfigureNotify:
01857 top_width = report.xconfigure.width;
01858 top_height = report.xconfigure.height;
01859 update_transform();
01860 #ifdef VERBOSE
01861 printf("Got a ConfigureNotify.\n");
01862 printf("New width: %d New height: %d.\n", top_width,
01863 top_height);
01864 #endif
01865 break;
01866 case ButtonPress:
01867 #ifdef VERBOSE
01868 printf("Got a buttonpress.\n");
01869 printf("Window ID is: %d.\n", report.xbutton.window);
01870 printf("Location (%d, %d).\n", report.xbutton.x,
01871 report.xbutton.y);
01872 #endif
01873 if(report.xbutton.window != toplevel)
01874 break;
01875 x[corner] = report.xbutton.x;
01876 y[corner] = report.xbutton.y;
01877 if(corner == 0)
01878 {
01879 XSelectInput(display, toplevel, ExposureMask |
01880 StructureNotifyMask | ButtonPressMask
01881 | PointerMotionMask);
01882 }
01883 else
01884 {
01885 update_win(x, y, drawscreen);
01886 }
01887 corner++;
01888 break;
01889 case MotionNotify:
01890 #ifdef VERBOSE
01891 printf("Got a MotionNotify Event.\n");
01892 printf("x: %d y: %d\n", report.xmotion.x,
01893 report.xmotion.y);
01894 #endif
01895 if(xold >= 0)
01896 {
01897 XDrawRectangle(display, toplevel, gcxor,
01898 min(x[0], xold), min(y[0], yold),
01899 abs(x[0] - xold),
01900 abs(y[0] - yold));
01901 }
01902
01903 xold = min(report.xmotion.x, top_width - 1 - MWIDTH);
01904 yold = report.xmotion.y;
01905 XDrawRectangle(display, toplevel, gcxor, min(x[0], xold),
01906 min(y[0], yold), abs(x[0] - xold),
01907 abs(y[0] - yold));
01908 break;
01909 }
01910 }
01911 XSelectInput(display, toplevel, ExposureMask | StructureNotifyMask
01912 | ButtonPressMask);
01913 }
01914
01915
01916 static void
01917 postscript(void (*drawscreen) (void))
01918 {
01919
01920
01921
01922
01923 static int piccount = 1;
01924 int success;
01925 char fname[20];
01926
01927 sprintf(fname, "pic%d.ps", piccount);
01928 success = init_postscript(fname);
01929
01930 if(success == 0)
01931 return;
01932
01933 drawscreen();
01934 close_postscript();
01935 piccount++;
01936 }
01937
01938
01939 static void
01940 proceed(void (*drawscreen) (void))
01941 {
01942
01943
01944
01945 }
01946
01947
01948 static void
01949 quit(void (*drawscreen) (void))
01950 {
01951
01952 close_graphics();
01953 exit(0);
01954 }
01955
01956
01957 void
01958 close_graphics(void)
01959 {
01960
01961
01962
01963
01964 int i;
01965
01966 for(i = 1; i <= MAX_FONT_SIZE; i++)
01967 if(font_is_loaded[i])
01968 XFreeFont(display, font_info[i]);
01969
01970 XFreeGC(display, gc);
01971 XFreeGC(display, gcxor);
01972 XFreeGC(display, gc_menus);
01973
01974 if(private_cmap != None)
01975 XFreeColormap(display, private_cmap);
01976
01977 XCloseDisplay(display);
01978 free(button);
01979 }
01980
01981
01982 int
01983 init_postscript(char *fname)
01984 {
01985
01986
01987
01988
01989 ps = fopen(fname, "w");
01990 if(ps == NULL)
01991 {
01992 printf("Error: could not open %s for PostScript output.\n",
01993 fname);
01994 printf("Drawing to screen instead.\n");
01995 return (0);
01996 }
01997 disp_type = POSTSCRIPT;
01998
01999
02000 fprintf(ps, "%%!PS-Adobe-1.0\n");
02001 fprintf(ps, "%%%%DocumentFonts: Helvetica\n");
02002 fprintf(ps, "%%%%Pages: 1\n");
02003
02004 update_ps_transform();
02005
02006 fprintf(ps, "%%%%BoundingBox: %d %d %d %d\n",
02007 (int)ps_left, (int)(ps_bot - 15.), (int)ps_right, (int)ps_top);
02008 fprintf(ps, "%%%%EndComments\n");
02009
02010 fprintf(ps, "/censhow %%draw a centered string\n");
02011 fprintf(ps, " { moveto %% move to proper spot\n");
02012 fprintf(ps, " dup stringwidth pop %% get x length of string\n");
02013 fprintf(ps, " -2 div %% Proper left start\n");
02014 fprintf(ps,
02015 " yoff rmoveto %% Move left that much and down half font height\n");
02016 fprintf(ps, " show newpath } def %% show the string\n\n");
02017
02018 fprintf(ps, "/setfontsize %% set font to desired size and compute "
02019 "centering yoff\n");
02020 fprintf(ps, " { /Helvetica findfont\n");
02021 fprintf(ps, " exch scalefont\n");
02022 fprintf(ps, " setfont %% Font size set ...\n\n");
02023 fprintf(ps, " 0 0 moveto %% Get vertical centering offset\n");
02024 fprintf(ps, " (Xg) true charpath\n");
02025 fprintf(ps, " flattenpath pathbbox\n");
02026 fprintf(ps, " /ascent exch def pop -1 mul /descent exch def pop\n");
02027 fprintf(ps, " newpath\n");
02028 fprintf(ps, " descent ascent sub 2 div /yoff exch def } def\n\n");
02029
02030 fprintf(ps, "%% Next two lines for debugging only.\n");
02031 fprintf(ps, "/str 20 string def\n");
02032 fprintf(ps, "/pnum {str cvs print ( ) print} def\n");
02033
02034 fprintf(ps, "/drawline %% draw a line from (x2,y2) to (x1,y1)\n");
02035 fprintf(ps, " { moveto lineto stroke } def\n\n");
02036
02037 fprintf(ps, "/rect %% outline a rectangle \n");
02038 fprintf(ps, " { /y2 exch def /x2 exch def /y1 exch def /x1 exch def\n");
02039 fprintf(ps, " x1 y1 moveto\n");
02040 fprintf(ps, " x2 y1 lineto\n");
02041 fprintf(ps, " x2 y2 lineto\n");
02042 fprintf(ps, " x1 y2 lineto\n");
02043 fprintf(ps, " closepath } def\n\n");
02044
02045 fprintf(ps, "/drawrect %% draw outline of a rectanagle\n");
02046 fprintf(ps, " { rect stroke } def\n\n");
02047
02048 fprintf(ps, "/fillrect %% fill in a rectanagle\n");
02049 fprintf(ps, " { rect fill } def\n\n");
02050
02051 fprintf(ps, "/drawarc { arc stroke } def %% draw an arc\n");
02052 fprintf(ps, "/drawarcn { arcn stroke } def "
02053 " %% draw an arc in the opposite direction\n\n");
02054
02055 fprintf(ps, "%%Fill a counterclockwise or clockwise arc sector, "
02056 "respectively.\n");
02057 fprintf(ps,
02058 "/fillarc { moveto currentpoint 5 2 roll arc closepath fill } "
02059 "def\n");
02060 fprintf(ps,
02061 "/fillarcn { moveto currentpoint 5 2 roll arcn closepath fill } "
02062 "def\n\n");
02063
02064 fprintf(ps,
02065 "/fillpoly { 3 1 roll moveto %% move to first point\n"
02066 " 2 exch 1 exch {pop lineto} for %% line to all other points\n"
02067 " closepath fill } def\n\n");
02068
02069
02070 fprintf(ps, "%%Color Definitions:\n");
02071 fprintf(ps, "/white { 1 setgray } def\n");
02072 fprintf(ps, "/black { 0 setgray } def\n");
02073 fprintf(ps, "/grey55 { .55 setgray } def\n");
02074 fprintf(ps, "/grey75 { .75 setgray } def\n");
02075 fprintf(ps, "/blue { 0 0 1 setrgbcolor } def\n");
02076 fprintf(ps, "/green { 0 1 0 setrgbcolor } def\n");
02077 fprintf(ps, "/yellow { 1 1 0 setrgbcolor } def\n");
02078 fprintf(ps, "/cyan { 0 1 1 setrgbcolor } def\n");
02079 fprintf(ps, "/red { 1 0 0 setrgbcolor } def\n");
02080 fprintf(ps, "/darkgreen { 0 0.5 0 setrgbcolor } def\n");
02081 fprintf(ps, "/magenta { 1 0 1 setrgbcolor } def\n");
02082 fprintf(ps, "/bisque { 1 0.9 0.8 setrgbcolor } def\n");
02083 fprintf(ps, "/lightblue { 0.7 0.8 0.9 setrgbcolor } def\n");
02084 fprintf(ps, "/thistle { 0.8 0.7 0.8 setrgbcolor } def\n");
02085 fprintf(ps, "/plum {0.8 0.6 0.8 setrgbcolor } def\n");
02086 fprintf(ps, "/khaki { 1 0.9 0.6 setrgbcolor } def\n");
02087 fprintf(ps, "/coral { 1 0.7 0.6 setrgbcolor } def\n");
02088 fprintf(ps, "/turquoise { 0.5 0.6 0.9 setrgbcolor } def\n");
02089 fprintf(ps, "/mediumpurple { 0.7 0.6 0.7 setrgbcolor } def\n");
02090 fprintf(ps, "/darkslateblue { 0.7 0.5 0.7 setrgbcolor } def\n");
02091 fprintf(ps, "/darkkhaki { 0.9 0.7 0.4 setrgbcolor } def\n");
02092
02093 fprintf(ps, "\n%%Solid and dashed line definitions:\n");
02094 fprintf(ps, "/linesolid {[] 0 setdash} def\n");
02095 fprintf(ps, "/linedashed {[3 3] 0 setdash} def\n");
02096
02097 fprintf(ps, "\n%%%%EndProlog\n");
02098 fprintf(ps, "%%%%Page: 1 1\n\n");
02099
02100
02101 force_setcolor(currentcolor);
02102 force_setlinestyle(currentlinestyle);
02103 force_setlinewidth(currentlinewidth);
02104 force_setfontsize(currentfontsize);
02105
02106
02107 draw_message();
02108
02109
02110 fprintf(ps, "%.2f %.2f %.2f %.2f rect ", ps_left, ps_bot, ps_right,
02111 ps_top);
02112 fprintf(ps, "clip newpath\n\n");
02113
02114 return (1);
02115 }
02116
02117 void
02118 close_postscript(void)
02119 {
02120
02121
02122
02123 fprintf(ps, "showpage\n");
02124 fprintf(ps, "\n%%%%Trailer\n");
02125 fclose(ps);
02126 disp_type = SCREEN;
02127 update_transform();
02128
02129
02130
02131
02132
02133
02134 force_setcolor(currentcolor);
02135 force_setlinestyle(currentlinestyle);
02136 force_setlinewidth(currentlinewidth);
02137 force_setfontsize(currentfontsize);
02138 }
02139
02140 #else
02141
02142 void
02143 event_loop(void (*act_on_button) (float x,
02144 float y),
02145 void (*drawscreen) (void))
02146 {
02147 }
02148
02149 void
02150 init_graphics(char *window_name)
02151 {
02152 }
02153 void
02154 close_graphics(void)
02155 {
02156 }
02157 void
02158 update_message(char *msg)
02159 {
02160 }
02161 void
02162 draw_message(void)
02163 {
02164 }
02165 void
02166 init_world(float xl,
02167 float yt,
02168 float xr,
02169 float yb)
02170 {
02171 }
02172 void
02173 flushinput(void)
02174 {
02175 }
02176 void
02177 setcolor(int cindex)
02178 {
02179 }
02180 void
02181 setlinestyle(int linestyle)
02182 {
02183 }
02184 void
02185 setlinewidth(int linewidth)
02186 {
02187 }
02188 void
02189 setfontsize(int pointsize)
02190 {
02191 }
02192 void
02193 drawline(float x1,
02194 float y1,
02195 float x2,
02196 float y2)
02197 {
02198 }
02199 void
02200 drawrect(float x1,
02201 float y1,
02202 float x2,
02203 float y2)
02204 {
02205 }
02206 void
02207 fillrect(float x1,
02208 float y1,
02209 float x2,
02210 float y2)
02211 {
02212 }
02213 void
02214 fillpoly(t_point * points,
02215 int npoints)
02216 {
02217 }
02218 void
02219 drawarc(float xcen,
02220 float ycen,
02221 float rad,
02222 float startang,
02223 float angextent)
02224 {
02225 }
02226
02227 void
02228 fillarc(float xcen,
02229 float ycen,
02230 float rad,
02231 float startang,
02232 float angextent)
02233 {
02234 }
02235
02236 void
02237 drawtext(float xc,
02238 float yc,
02239 const char *text,
02240 float boundx)
02241 {
02242 }
02243 void
02244 clearscreen(void)
02245 {
02246 }
02247
02248 void
02249 create_button(char *prev_button_text,
02250 char *button_text,
02251 void (*button_func) (void (*drawscreen) (void)))
02252 {
02253 }
02254
02255 void
02256 destroy_button(char *button_text)
02257 {
02258 }
02259
02260 int
02261 init_postscript(char *fname)
02262 {
02263 return (1);
02264 }
02265
02266 void
02267 close_postscript(void)
02268 {
02269 }
02270
02271 #endif