-
Notifications
You must be signed in to change notification settings - Fork 4
/
graphics.c
3988 lines (3385 loc) · 110 KB
/
graphics.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#define TRUE 1
#define FALSE 0
#ifndef NO_GRAPHICS
/* Written by Vaughn Betz at the University of Toronto, Department of *
* Electrical and Computer Engineering. Graphics package Version 1.3. *
* All rights reserved by U of T, etc. *
* *
* You may freely use this graphics interface for non-commercial purposes *
* as long as you leave the written by Vaughn Betz message in it -- who *
* knows, maybe someday an employer will see it and give me a job or large *
* sums of money :). *
* *
* Enhanced version by William Chow, named EasyGL for Windows after *
* Vaughn's initial EasyGL implementation *
* *
* Re-ported back to X11 with minor typefixes by Guy Lemieux. *
* *
* To do's : *
* - show new features in example.c *
* *
* Revision History: *
* *
* V1.06 : July 23, 2003 : (Guy Lemieux)
* - added some typecasts to cleanly compile with g++ and MS c++ tools
* - if WIN32 not defined, it defines X11 automatically
* - fixed X11 compilation; WIN32 broke some things
*
* V1.05 : July 26, 2001 : (William) *
* - changed keyboard detect function to accept an int (virtual key) *
* *
* V1.04 : June 29, 2001 : (William) *
* - added drawcurve(), fillcurve() using Bezier curves *
* (support WIN32 screen / ps) *
* - added pt on object capability : using a memory buffer to draw an *
* graphics objects, then query if a point fall on the object (bear the *
* object's colour) : object_start(), object_end(), pt_on_object() *
* - added drawellipticarc(), fillellipticarc() *
* - added findfontsize() to help find a pointsize of a given height *
* - extended t_report to keep xleft, xright, ytop, ybot *
* - added update_window() to set the window bb *
* *
* V1.03 : June 18, 2001 : (William) *
* - added change_button_text() *
* *
* V1.02 : June 13, 2001 : (William) *
* - extension to mouse click function : can tell if ctrl/shift keys are *
* pressed *
* *
* V1.01 : June 1, 2001 : (William) *
* - add tooltip support *
* *
* V1.0 : May 14, 2001 : (William) *
* - fixed a problem with line styles, initial release on the internet *
* *
* March 27, 2001 : (William) *
* - added setcolor_by_colorref to make more colors available (in Win32) *
* *
* February 16, 2001 : (William) *
* - added quick zoom using right mouse clicks *
* *
* February 11, 2001 : (William) *
* - can define cleanup(), passed in when calling init_graphics(), and *
* called when shutting down *
* *
* February 1, 2001 : (William) *
* - fix xor mode redraw problem *
* *
* September 19, 2000 : (William) *
* - can define mouse_move callback function *
* - can add separators in between buttons *
* *
* September 8, 2000 : (William) *
* - added result_structure(), *
* - can define background color in init_graphics *
* *
* August 10, 2000 : (William Chow, choww@eecg.utoronto.ca) *
* - Finished all Win32 support functions *
* - use XOR mode for window zooming box *
* - added double buffering feature *
* *
* January 12, 1999: (Paul) *
* - Fixed a bunch of stuff with the Win32 support (memory leaks, etc) *
* - Made the clipping function using the update rectangle for Win32 *
* *
* January 9, 1999: (Paul Leventis, leventi@eecg.utoronto.ca) *
* - Added Win32 support. Should work under Windows98/95/NT 4.0/NT 5.0. *
* - Added a check to deselect_all to determine whether the screen needs to *
* be updated or not. Should elminate flicker from mouse clicks *
* - Added invalidate_screen() call to graphics.c that in turn calls *
* update_screen, so this function was made non-static and added to the *
* header file. This is due to differences in the structure of Win32 *
* windowing apps. *
* - Added setOKtoPaint(TRUE/FALSE) to explicitly tell the graphics engine *
* that the data structures are o.k. to read for redrawing the screen. *
* Used for Win32 since painting is a separate thread of execution. *
* - Win32 needs clipping (though done automatically, could be faster) *
* *
* Sept. 19, 1997: Incorporated Zoom Fit code of Haneef Mohammed at *
* Cypress. Makes it easy to zoom to a full view of the graphics. *
* *
* Sept. 11, 1997: Added the create_and destroy_button interface to *
* make it easy to add and destroy buttons from user code. Removed the *
* bnum parameter to the button functions, since it wasn't really needed. *
* *
* June 28, 1997: Added filled arc drawing primitive. Minor modifications *
* to PostScript driver to make the PostScript output slightly smaller. *
* *
* April 15, 1997: Added code to init_graphics so it waits for a window *
* to be exposed before returning. This ensures that users of non- *
* interactive graphics can never draw to a window before it is available. *
* *
* Feb. 24, 1997: Added code so the package will allocate a private *
* colormap if the default colormap doesn't have enough free colours. *
* *
* June 28, 1996: Converted all internal functions in graphics.c to have *
* internal (static) linkage to avoid any conflicts with user routines in *
* the rest of the program. *
* *
* June 12, 1996: Added setfontsize and setlinewidth attributes. Added *
* pre-clipping of objects for speed (and compactness of PS output) when *
* graphics are zoomed in. Rewrote PostScript engine to shrink the output *
* and make it easier to read. Made drawscreen a callback function passed *
* in rather than a global. Graphics attribute calls are more efficient -- *
* they check if they have to change anything before doing it. *
* *
* October 27, 1995: Added the message area, a callback function for *
* interacting with user button clicks, and implemented a workaround for a *
* Sun X Server bug that misdisplays extremely highly zoomed graphics. *
* *
* Jan. 13, 1995: Modified to incorporate PostScript Support. */
/*********************************
* Common Preprocessor Directives *
*********************************/
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "graphics.h"
#include "allocation.h"
#if defined(X11) || defined(WIN32)
/* Macros for translation from world to PostScript coordinates */
#define XPOST(worldx) (((worldx)-xleft)*ps_xmult + ps_left)
#define YPOST(worldy) (((worldy)-ybot)*ps_ymult + ps_bot)
/* Macros to convert from X Windows Internal Coordinates to my *
* World Coordinates. (This macro is used only rarely, so *
* the divides don't hurt speed). */
#define XTOWORLD(x) (((float) x)*xdiv + xleft)
#define YTOWORLD(y) (((float) y)*ydiv + ytop)
#ifndef max
#define max(a,b) (((a) > (b))? (a) : (b))
#endif
#ifndef min
#define min(a,b) ((a) > (b)? (b) : (a))
#endif
#define MWIDTH 104 /* width of menu window */
#define T_AREA_HEIGHT 24 /* Height of text window */
#define MAX_FONT_SIZE 40 /* Largest point size of text */
#define PI 3.141592654
#define BUTTON_TEXT_LEN 20
#define BUFSIZE 1000
#endif
/*********************************************
* X-Windows Specific Preprocessor Directives *
*********************************************/
#ifdef X11
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
/* Uncomment the line below if your X11 header files don't define XPointer */
/* typedef char *XPointer; */
#define MAXPIXEL 15000
#define MINPIXEL -15000
#endif /* X11 Preprocessor Directives */
/*************************************************************
* Microsoft Windows (WIN32) Specific Preprocessor Directives *
*************************************************************/
#ifdef WIN32
#include <windows.h>
// wc
#include <commctrl.h>
#define SELECT_ERROR() { char msg[100]; sprintf(msg, "Error %i: Couldn't select graphics object on line %d of graphics.c\n", GetLastError(), __LINE__); MessageBox(NULL, msg, NULL, MB_OK); exit(-1); }
#define DELETE_ERROR() { char msg[100]; sprintf(msg, "Error %i: Couldn't delete graphics object on line %d of graphics.c\n", GetLastError(), __LINE__); MessageBox(NULL, msg, NULL, MB_OK); exit(-1); }
#define CREATE_ERROR() { char msg[100]; sprintf(msg, "Error %i: Couldn't create graphics object on line %d of graphics.c\n", GetLastError(), __LINE__); MessageBox(NULL, msg, NULL, MB_OK); exit(-1); }
#define DRAW_ERROR() { char msg[100]; sprintf(msg, "Error %i: Couldn't draw graphics object on line %d of graphics.c\n", GetLastError(), __LINE__); MessageBox(NULL, msg, NULL, MB_OK); exit(-1); }
/* Due to funny clipping problems under windows that I suspect are caused by round-off thingys */
#define MAXPIXEL 2000
#define MINPIXEL -2000
/* WC : fix WIN32 zoom-in/out problem */
#define MIN_XMULT 0.08
#define MIN_YMULT 0.08
#define MAX_XMULT 4.0
#define MAX_YMULT 4.0
#define DEGTORAD(x) ((x)/180.*PI)
#define FONTMAG 1.3
#endif /* Win32 preprocessor Directives */
/**********************
* Common Declarations *
**********************/
static int xcoord (float worldx);
static int ycoord (float worldy);
static void force_setcolor(int cindex);
static void force_setlinestyle(int linestyle);
static void force_setlinewidth(int linewidth);
/* WC */
static void force_setfontsize (int pointsize);
static void build_default_menu (void);
typedef struct {
int width;
int height;
int xleft;
int ytop;
void (*fcn) (void (*drawscreen) (void));
#ifdef X11
Window win;
#else
HWND hwnd;
#endif
int istext;
char text[BUTTON_TEXT_LEN];
int ispoly;
int poly[3][2];
int ispressed;
int enabled;
int isseparator;
} t_button;
static const int menu_font_size = 14; /* Font for menus and dialog boxes. */
static t_button *button = NULL; /* [0..num_buttons-1] */
static int num_buttons = 0; /* Number of menu buttons */
static int disp_type; /* Selects SCREEN or POSTSCRIPT */
static int display_width, display_height; /* screen size */
static int top_width, top_height; /* window size */
static float xleft, xright, ytop, ybot; /* world coordinates */
static float saved_xleft, saved_xright, saved_ytop, saved_ybot;
static float ps_left, ps_right, ps_top, ps_bot; /* Figure boundaries for *
* PostScript output, in PostScript coordinates. */
static float ps_xmult, ps_ymult; /* Transformation for PostScript. */
static float xmult, ymult; /* Transformation factors */
static float xdiv, ydiv;
static int currentcolor = BLACK;
static int currentlinestyle = SOLID;
static int currentlinewidth = 0;
static int currentfontsize = 10;
/* For PostScript output */
static FILE *ps;
static int ProceedPressed = FALSE;
static char statusMessage[BUFSIZE] = ""; /* User message to display */
/* WC */
static int background_cindex;
static int font_is_loaded[MAX_FONT_SIZE + 1]; /* 1: loaded, 0: not */
static void load_font(int pointsize);
static int getKeyFlag = 0, getMouseFlag = 0;
void get_mouse(int);
void get_key(int);
void enablebuttons(int);
void draw_pushed_button(int);
void draw_normal();
void draw_xor();
/* Function declarations for button responses */
static void translate_up (void (*drawscreen) (void));
static void translate_left (void (*drawscreen) (void));
static void translate_right (void (*drawscreen) (void));
static void translate_down (void (*drawscreen) (void));
static void zoom_in (void (*drawscreen) (void));
static void zoom_out (void (*drawscreen) (void));
static void zoom_fit (void (*drawscreen) (void));
static void adjustwin (void (*drawscreen) (void));
/* Ameer Abdelhadi: Remove static & move declaration to header */
/* static void postscript (void (*drawscreen) (void)); */
void postscript (void (*drawscreen) (void));
static void proceed (void (*drawscreen) (void));
static void quit (void (*drawscreen) (void));
static void map_button (int bnum);
static void unmap_button (int bnum);
/*************************
* X-Windows Declarations *
*************************/
#ifdef X11
static Display *display;
static int screen_num;
static GC gc, gcxor, gc_menus, current_gc;
static XFontStruct *font_info[MAX_FONT_SIZE+1]; /* Data for each size */
static Window toplevel, menu, textarea; /* various windows */
static Colormap private_cmap; /* "None" unless a private cmap was allocated. */
/* Graphics state. Set start-up defaults here. */
/* Color indices passed back from X Windows. */
static int colors[NUM_COLOR];
/* MAXPIXEL and MINPIXEL are set to prevent what appears to be *
* overflow with very large pixel values on the Sun X Server. */
static Bool test_if_exposed (Display *disp, XEvent *event_ptr,
XPointer dummy);
static void build_textarea (void);
static void drawbut (int bnum);
static int which_button (Window win);
static void turn_on_off (int pressed);
static void drawmenu(void);
#endif /* X11 Declarations */
/*****************************************
* Microsoft Windows (Win32) Declarations *
*****************************************/
#ifdef WIN32
static int win32_line_styles[2] = { PS_SOLID, PS_DASH };
static COLORREF win32_colors[NUM_COLOR] = { RGB(255, 255, 255),
RGB(0, 0, 0), RGB(128, 128, 128), RGB(192, 192, 192), RGB(0, 0, 255),
RGB(0, 255, 0), RGB(255, 255, 0), RGB(0, 255, 255), RGB(255, 0, 0), RGB(0, 128, 0),
RGB(255, 0, 255) };
static TCHAR szAppName[256],
szGraphicsName[] = TEXT("VPR Graphics"),
szStatusName[] = TEXT("VPR Status"),
szButtonsName[] = TEXT("VPR Buttons");
static HPEN hGraphicsPen = 0;
static HBRUSH hGraphicsBrush = 0, hGrayBrush = 0;
static HDC hGraphicsDC = 0, hForegroundDC = 0, hBackgroundDC = 0,
hCurrentDC = 0, /* WC : double-buffer */
hObjtestDC = 0, hAllObjtestDC = 0; /* object test */
/* WC */
static int xormode = 0;
static HFONT hGraphicsFont = 0;
static LOGFONT *font_info[MAX_FONT_SIZE+1]; /* Data for each size */
static HWND hwndTT; // handle to the tooltip control
static HWND hMainWnd, hGraphicsWnd, hButtonsWnd, hStatusWnd;
static LRESULT CALLBACK GraphicsWND(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK StatusWND(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK ButtonsWND(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK MainWND(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static cxClient, cyClient;
static int windowAdjustFlag = 0, adjustButton = -1;
static RECT adjustRect, updateRect;
//static HBITMAP buttonImages[4];
static void (*clb_click)(float x, float y, int flags);
static void (*mousemove_ptr)(float x, float y);
static void (*keypress_ptr)(int i);
static void (*cleanup_ptr)(void);
static void (*drawscreen_ptr)(void);
static boolean InEventLoop = FALSE;
void drawtobuffer();
void drawtoscreen();
void displaybuffer();
#endif /* Win32 Declarations */
/*********************
* Common Definitions *
*********************/
/* Translates from my internal coordinates to real-world coordinates *
* in the x direction. Add 0.5 at end for extra half-pixel accuracy. */
static int
xcoord (float worldx)
{
int winx;
winx = (int) ((worldx-xleft)*xmult + 0.5);
/* Avoids overflow in the Window routines. This will allow horizontal *
* and vertical lines to be drawn correctly regardless of zooming, but *
* will cause diagonal lines that go way off screen to change their *
* slope as you zoom in. The only way I can think of to completely fix *
* this problem is to do all the clipping in advance in floating point, *
* then convert to integers and call Windows. This is a lot of extra *
* coding, and means that coordinates will be clipped twice, even though *
* this "Super Zoom" problem won't occur unless users zoom way in on *
* the graphics. */
winx = max (winx, MINPIXEL);
winx = min (winx, MAXPIXEL);
return (winx);
}
/* Translates from my internal coordinates to real-world coordinates *
* in the y direction. Add 0.5 at end for extra half-pixel accuracy. */
static int
ycoord (float worldy)
{
int winy;
winy = (int) ((worldy-ytop)*ymult + 0.5);
/* Avoid overflow in the X/Win32 Window routines. */
winy = max (winy, MINPIXEL);
winy = min (winy, MAXPIXEL);
return (winy);
}
/* Tells the graphics engine to redraw the graphics display since information has changed */
void
invalidate_screen(void)
{
#ifdef X11
/*
clearscreen();
redraw_screen();
*/
#else /* Win32 */
if(!InvalidateRect(hGraphicsWnd, NULL, /*TRUE*/FALSE))
DRAW_ERROR();
if(!UpdateWindow(hGraphicsWnd))
DRAW_ERROR();
#endif
}
/* Sets the current colour to cindex, regardless of its value */
static void
force_setcolor (int cindex)
{
static char *ps_cnames[NUM_COLOR] = {(char*)"white", (char*)"black", (char*)"grey55", (char*)"grey75",
(char*)"blue", (char*)"green", (char*)"yellow", (char*)"cyan", (char*)"red", (char*)"darkgreen", (char*)"magenta"};
/*ameer: unused
int linestyle;
*/
#ifdef WIN32
LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = win32_colors[cindex];
lb.lbHatch = (LONG)NULL;
linestyle = currentlinewidth != 1 ? PS_SOLID : win32_line_styles[currentlinestyle];
#endif
currentcolor = cindex;
if (disp_type == SCREEN) {
#ifdef X11
XSetForeground (display, current_gc, colors[cindex]);
#else /* Win32 */
// if(!SelectObject(hGraphicsDC, GetStockObject(NULL_PEN)))
// SELECT_ERROR();
if(!DeleteObject(hGraphicsPen))
DELETE_ERROR();
hGraphicsPen = ExtCreatePen(PS_GEOMETRIC | linestyle |
PS_ENDCAP_FLAT, currentlinewidth, &lb, (LONG)NULL, NULL);
if(!hGraphicsPen)
CREATE_ERROR();
// if(!SelectObject(hGraphicsDC, GetStockObject(NULL_BRUSH)))
// SELECT_ERROR();
if(!DeleteObject(hGraphicsBrush))
DELETE_ERROR();
hGraphicsBrush = CreateSolidBrush(win32_colors[currentcolor]);
if(!hGraphicsBrush)
CREATE_ERROR();
#endif
}
else {
fprintf (ps,"%s\n", ps_cnames[cindex]);
}
}
/* Sets the current colour to cindex if necessary */
void
setcolor (int cindex)
{
if (currentcolor != cindex)
force_setcolor (cindex);
}
/* Sets the current linestyle to linestyle.
* Note SOLID is 0 and DASHED is 1 for linestyle. */
static void
force_setlinestyle (int linestyle)
{
/* PostScript, X commands needed, respectively. */
static char *ps_text[2] = {(char*)"linesolid", (char*)"linedashed"};
#ifdef X11
static int x_vals[2] = {LineSolid, LineOnOffDash};
currentlinestyle = linestyle;
#else
LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = win32_colors[currentcolor];
lb.lbHatch = (LONG)NULL;
currentlinestyle = linestyle;
linestyle = currentlinewidth != 1 ? PS_SOLID : win32_line_styles[currentlinestyle];
#endif
if (disp_type == SCREEN) {
#ifdef X11
XSetLineAttributes (display, current_gc, currentlinewidth, x_vals[linestyle],
CapButt, JoinMiter);
#else /* Win32 */
// if(!SelectObject(hGraphicsDC, GetStockObject(NULL_PEN)))
// SELECT_ERROR();
if(!DeleteObject(hGraphicsPen))
DELETE_ERROR();
hGraphicsPen = ExtCreatePen(PS_GEOMETRIC | linestyle |
PS_ENDCAP_FLAT, currentlinewidth, &lb, (LONG)NULL, NULL);
if(!hGraphicsPen)
CREATE_ERROR();
#endif
}
else {
fprintf(ps,"%s\n", ps_text[linestyle]);
}
}
void
setlinestyle (int linestyle)
{
if (linestyle != currentlinestyle)
force_setlinestyle (linestyle);
}
/* Sets current linewidth
* linewidth should be greater than or equal to 0 to make any sense. */
static void
force_setlinewidth (int linewidth)
{
#ifdef X11
static int x_vals[2] = {LineSolid, LineOnOffDash};
#else
int linestyle;
LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = win32_colors[currentcolor];
lb.lbHatch = (LONG)NULL;
linestyle = currentlinewidth != 1 ? PS_SOLID : win32_line_styles[currentlinestyle];
#endif
currentlinewidth = linewidth;
if (disp_type == SCREEN) {
#ifdef X11
XSetLineAttributes (display, current_gc, linewidth, x_vals[currentlinestyle],
CapButt, JoinMiter);
#else /* Win32 */
// if(!SelectObject(hGraphicsDC, GetStockObject(NULL_PEN)))
// SELECT_ERROR();
if(!DeleteObject(hGraphicsPen))
DELETE_ERROR();
hGraphicsPen = ExtCreatePen(PS_GEOMETRIC | linestyle |
PS_ENDCAP_FLAT, currentlinewidth, &lb, (LONG)NULL, NULL);
if(!hGraphicsPen)
CREATE_ERROR();
#endif
}
else {
fprintf(ps,"%d setlinewidth\n", linewidth);
}
}
void
setlinewidth (int linewidth)
{
if (linewidth != currentlinewidth)
force_setlinewidth (linewidth);
}
static void
force_setfontsize (int pointsize)
{
/* Valid point sizes are between 1 and MAX_FONT_SIZE */
if (pointsize < 1)
pointsize = 1;
#ifdef WIN32
pointsize = (int)((float)pointsize * FONTMAG);
#endif
if (pointsize > MAX_FONT_SIZE)
pointsize = MAX_FONT_SIZE;
currentfontsize = pointsize;
if (disp_type == SCREEN) {
#ifdef X11
if (!font_is_loaded[pointsize]) {
load_font (pointsize);
font_is_loaded[pointsize] = 1;
}
XSetFont(display, current_gc, font_info[pointsize]->fid);
#else /* Win32 */
/* WC */
if (!font_is_loaded[pointsize]) {
load_font (pointsize);
font_is_loaded[pointsize] = 1;
}
// if(!SelectObject(hGraphicsDC, GetStockObject(DEFAULT_GUI_FONT)))
// SELECT_ERROR();
if(!DeleteObject(hGraphicsFont))
DELETE_ERROR();
hGraphicsFont = CreateFontIndirect(font_info[pointsize]);
if(!hGraphicsFont)
CREATE_ERROR();
#endif
}
else {
/* PostScript: set up font and centering function */
fprintf(ps,"%d setfontsize\n",pointsize);
}
}
/* For efficiency, this routine doesn't do anything if no change is *
* implied. If you want to force the graphics context or PS file *
* to have font info set, call force_setfontsize (this is necessary *
* in initialization and X11 / Postscript switches). */
void
setfontsize (int pointsize)
{
if (pointsize != currentfontsize)
force_setfontsize (pointsize);
}
/* Puts a triangle in the poly array for button[bnum] */
static void
setpoly (int bnum, int xc, int yc, int r, float theta)
{
int i;
button[bnum].istext = 0;
button[bnum].ispoly = 1;
for (i=0;i<3;i++) {
button[bnum].poly[i][0] = (int) (xc + r*cos(theta) + 0.5);
button[bnum].poly[i][1] = (int) (yc + r*sin(theta) + 0.5);
theta += (float)(2*PI/3);
}
}
/* Maps a button onto the screen and set it up for input, etc. */
static void
map_button (int bnum)
{
button[bnum].ispressed = 0;
if (!button[bnum].isseparator) {
#ifdef X11
button[bnum].win = XCreateSimpleWindow(display,menu,
button[bnum].xleft, button[bnum].ytop, button[bnum].width,
button[bnum].height, 0, colors[WHITE], colors[LIGHTGREY]);
XMapWindow (display, button[bnum].win);
XSelectInput (display, button[bnum].win, ButtonPressMask);
#else
// if(1 || button[bnum].istext) {
button[bnum].hwnd = CreateWindow( TEXT("button"), TEXT(button[bnum].text),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, button[bnum].xleft, button[bnum].ytop,
button[bnum].width, button[bnum].height, hButtonsWnd, (HMENU)(200+bnum),
(HINSTANCE) GetWindowLong(hMainWnd, GWL_HINSTANCE), NULL);
/* } else {
if(!button[bnum].ispoly)
DRAW_ERROR();
button[bnum].hwnd = CreateWindow( TEXT("button"), NULL,
WS_CHILD | WS_VISIBLE | BS_BITMAP, button[bnum].xleft, button[bnum].ytop,
button[bnum].width, button[bnum].height, hButtonsWnd, (HMENU)(200+bnum),
(HINSTANCE) GetWindowLong(hMainWnd, GWL_HINSTANCE), NULL);
SendMessage(button[bnum].hwnd, BM_SETIMAGE, IMAGE_BITMAP, hBitmap);
hdc = GetDC(button[bnum].hwnd);
hdcMem = CreateCompatibleDC(hdc);
Create
CreateWindow
*/
// }
if(!InvalidateRect(hButtonsWnd, NULL, TRUE))
DRAW_ERROR();
if(!UpdateWindow(hButtonsWnd))
DRAW_ERROR();
#endif
}
else {
#ifdef WIN32
/* if(!MoveToEx (hdc, button[i].xleft, button[i].ytop, NULL))
DRAW_ERROR();
if(!LineTo (hdc, button[i].xleft + button[i].width, button[i].ytop))
DRAW_ERROR();*/
if(!InvalidateRect(hButtonsWnd, NULL, TRUE))
DRAW_ERROR();
if(!UpdateWindow(hButtonsWnd))
DRAW_ERROR();
#endif
}
}
static void
unmap_button (int bnum)
{
/* Unmaps a button from the screen. */
if (!button[bnum].isseparator) {
#ifdef X11
XUnmapWindow (display, button[bnum].win);
#else
if(!DestroyWindow(button[bnum].hwnd))
DRAW_ERROR();
if(!InvalidateRect(hButtonsWnd, NULL, TRUE))
DRAW_ERROR();
if(!UpdateWindow(hButtonsWnd))
DRAW_ERROR();
#endif
}
}
/* Creates a new button below the button containing prev_button_text. *
* The text and button function are set according to button_text and *
* button_func, respectively. */
void create_button (char *prev_button_text , char *button_text,
void (*button_func) (void (*drawscreen) (void)))
{
int i, bnum, space, bheight, isseparator = 0;
space = 8;
/* Only allow new buttons that are text (not poly) types. */
bnum = -1;
for (i=4;i<num_buttons;i++) {
if (button[i].istext == 1 &&
strcmp (button[i].text, prev_button_text) == 0) {
bnum = i + 1;
break;
}
}
if (bnum == -1) {
printf ("Error in create_button: button with text %s not found.\n",
prev_button_text);
exit (1);
}
button = (t_button *) safeRealloc (button, (num_buttons+1) * sizeof (t_button));
/* NB: Requirement that you specify the button that this button goes under *
* guarantees that button[num_buttons-2] exists and is a text button. */
if (!strncmp(button_text, "---", 3)) {
bheight = 2;
isseparator = 1;
}
else
bheight = 26;
for (i=num_buttons;i>bnum;i--) {
button[i].xleft = button[i-1].xleft;
button[i].ytop = button[i-1].ytop + bheight + space;
button[i].height = button[i-1].height;
button[i].width = button[i-1].width;
button[i].ispoly = button[i-1].ispoly;
button[i].istext = button[i-1].istext;
strcpy (button[i].text, button[i-1].text);
button[i].fcn = button[i-1].fcn;
button[i].ispressed = button[i-1].ispressed;
button[i].enabled = button[i-1].enabled;
button[i].isseparator = button[i-1].isseparator;
unmap_button (i-1);
}
i = bnum;
button[i].xleft = 6;
button[i].ytop = button[i-1].ytop + button[i-1].height + space;
button[i].height = bheight;
button[i].width = 90;
button[i].ispoly = 0;
button[i].istext = 1;
strncpy (button[i].text, button_text, BUTTON_TEXT_LEN);
button[i].fcn = button_func;
button[i].ispressed = 0;
button[i].enabled = 1;
button[i].isseparator = isseparator;
num_buttons++;
/* ameer: first statement is not needed
for (i; i<num_buttons;i++)
changed into: */
for (; i<num_buttons;i++)
map_button (i);
}
/* Destroys the button with text button_text. */
void
destroy_button (char *button_text)
{
int i, bnum, space, bheight, isseparator = 0;
bnum = -1;
space = 8;
for (i=4;i<num_buttons;i++) {
if (button[i].istext == 1 &&
strcmp (button[i].text, button_text) == 0) {
bnum = i;
break;
}
}
if (bnum == -1) {
printf ("Error in destroy_button: button with text %s not found.\n",
button_text);
exit (1);
}
if (!strncmp(button_text, "---", 3)) {
bheight = 2;
isseparator = 1;
}
else
bheight = 26;
for (i=bnum+1;i<num_buttons;i++) {
button[i-1].xleft = button[i].xleft;
button[i-1].ytop = button[i].ytop - bheight - space;
button[i-1].height = button[i].height;
button[i-1].width = button[i].width;
button[i-1].ispoly = button[i].ispoly;
button[i-1].istext = button[i].istext;
strcpy (button[i-1].text, button[i].text);
button[i-1].fcn = button[i].fcn;
button[i-1].ispressed = button[i].ispressed;
button[i-1].enabled = button[i].enabled;
button[i-1].isseparator = button[i].isseparator;
unmap_button (i);
}
unmap_button(bnum);
button = (t_button *) safeRealloc (button, (num_buttons-1) * sizeof (t_button));
num_buttons--;
for (i=bnum; i<num_buttons;i++)
map_button (i);
}
/* Open the toplevel window, get the colors, 2 graphics *
* contexts, load a font, and set up the toplevel window *
* Calls build_default_menu to set up the default menu. */
void
init_graphics (char *window_name, int cindex, void (*cleanup)(void))
{
#ifdef X11
char *display_name = NULL;
int x, y; /* window position */
unsigned int border_width = 2; /* ignored by OpenWindows */
XTextProperty windowName;
/* X Windows' names for my colours. */
char *cnames[NUM_COLOR] = {(char*)"white", (char*)"black", (char*)"grey55", (char*)"grey75", (char*)"blue",
(char*)"green", (char*)"yellow", (char*)"cyan", (char*)"red", (char*)"RGBi:0.0/0.5/0.0", (char*)"magenta" };
XColor exact_def;
Colormap cmap;
unsigned long valuemask = 0; /* ignore XGCvalues and use defaults */
XGCValues values;
XEvent event;
int i;
for (i=0;i<=MAX_FONT_SIZE;i++)
font_is_loaded[i] = 0; /* No fonts loaded yet. */
disp_type = SCREEN; /* Graphics go to screen, not ps */
/* connect to X server */
if ( (display=XOpenDisplay(display_name)) == NULL )
{
fprintf( stderr, "Cannot connect to X server %s\n",
XDisplayName(display_name));
exit( -1 );
}
/* get screen size from display structure macro */
screen_num = DefaultScreen(display);
display_width = DisplayWidth(display, screen_num);
display_height = DisplayHeight(display, screen_num);
x = y = 0;
top_width = 2 * display_width / 3;
top_height = 4 * display_height / 5;
cmap = DefaultColormap(display, screen_num);
private_cmap = None;
for (i=0;i<NUM_COLOR;i++) {
if (!XParseColor(display,cmap,cnames[i],&exact_def)) {
fprintf(stderr, "Color name %s not in database", cnames[i]);
exit(-1);
}
if (!XAllocColor(display, cmap, &exact_def)) {
fprintf(stderr, "Couldn't allocate color %s.\n",cnames[i]);
if (private_cmap == None) {
fprintf(stderr, "Will try to allocate a private colourmap.\n");
fprintf(stderr, "Colours will only display correctly when your "
"cursor is in the graphics window.\n"
"Exit other colour applications and rerun this "
"program if you don't like that.\n\n");
private_cmap = XCopyColormapAndFree (display, cmap);
cmap = private_cmap;
if (!XAllocColor (display, cmap, &exact_def)) {
fprintf (stderr, "Couldn't allocate color %s as private.\n",
cnames[i]);
exit (1);
}
}
else {
fprintf (stderr, "Couldn't allocate color %s as private.\n",
cnames[i]);
exit (1);
}
}
colors[i] = exact_def.pixel;
}
toplevel = XCreateSimpleWindow(display,RootWindow(display,screen_num),
x, y, top_width, top_height, border_width, colors[BLACK],
colors[cindex]);
if (private_cmap != None)
XSetWindowColormap (display, toplevel, private_cmap);
/* hints stuff deleted. */
XSelectInput (display, toplevel, ExposureMask | StructureNotifyMask |
ButtonPressMask | PointerMotionMask | KeyPressMask);
/* Create default Graphics Contexts. valuemask = 0 -> use defaults. */
current_gc = gc = XCreateGC(display, toplevel, valuemask, &values);
gc_menus = XCreateGC(display, toplevel, valuemask, &values);