File: window.h

package info (click to toggle)
grafix 1.6-5
  • links: PTS
  • area: main
  • in suites: woody
  • size: 1,156 kB
  • ctags: 1,962
  • sloc: ansic: 20,183; makefile: 186; sh: 3
file content (1001 lines) | stat: -rw-r--r-- 37,035 bytes parent folder | download
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
1001
// window.h : basic include file for the Grafix package
// the "GNU Public Lincense" policy applies to all programs of this package
// (c) Wolfgang Koehler, wolf@first.gmd.de, Dec. 1994
//     Kiefernring 15
//     14478 Potsdam, Germany
//     0331-863238

#if !defined WINDOW_H
#define WINDOW_H
#pragma interface 

#include <X11/Xlib.h>
// #include "X11/Xutil.h"
#include <X11/keysym.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#define FALSE 0
#define TRUE 1

#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))

// since some dumb platforms dont have irint, or rint
#define irint(x) int((x)+0.5)

#define SimpleType 0
#define PulldownType 1

extern void error(char*, ...);

char *ext_string(char * str); // extend str for 1 + 1 space 

GC CreateGC(unsigned long mask, XGCValues * gcv);

void set_color(unsigned long color); // set color for gc_copy 
int alloc_color(unsigned red, unsigned green, unsigned blue);
int alloc_named_color(char *colname);

struct point { int x; int y; };

extern Colormap def_cmap;
extern Display * display;
extern int screen;
extern GC gc_copy, gc_but_xor, gc_clear, gc_inv, gc_rubber; 
// some often used gcs
extern GC button_fg_gc, button_br_gc, button_lw_gc; 
extern Cursor watch_cursor; // for long redraw methods eg. in coordwindows
extern Cursor hs_cursor, vs_cursor; // special cursors for scrollbars
extern XFontStruct * fixed_fn;
// some predifined simple colors : use capitals to avoid name conflicts (NR)
extern unsigned depth, black, white, Red, Green, Blue, Yellow, Violet;
extern Bool True_Color_Visual; // only for TrueColor 
                               // -> XAllocColorCells will not work then 
void handle_event(XEvent &event);

class window;

void safe_delete(window *w); // delete only, if not yet deleted !

struct win_list { // struct to manage a child list of any window
  window *child; 
  int x,y;
  struct win_list *next;
  win_list(window *ch, int x, int y, win_list *rest) : child(ch), x(x), y(y) { next = rest; }
};

struct dhelper; // for dynamic help on EnterCB
class main_window;

class window {
protected:
  int border_width;
  GC gc,text_gc;
  dhelper *dhlp;     // on EnterCB
  window *parentw;   // only for destructors
  long selection_mask; // default mask for SelectInput
  Bool hidden;      // if true not realize the window 
public:  
  Bool is_mapped;   // for fast test if window is mapped
  main_window *mainw; // the main window of this window, direct child of root 
  int width, height;
  int CB_info;   // toggle debug infos on callbacks in this Window
  Window Win;
  int type;      // to distinguish simple <-> pulldown
  win_list *children;        // chained List of children
 
  window(char *DISP = NULL); // constructor for root window
  window(window & parent, int w = 0, int h = 0, int x = 0, int y = 0, int bw = 1);
  // to update children list and fit the parent geometry :
  virtual void add_child(window *ch, int x, int y);
  
  void remove_child(window *ch); // remove from my children list
  virtual ~window();  // virtual destructor
  
  virtual void draw_interior() { }   // is called from Map to draw an image 
  virtual void Map(); 
  void Unmap();
  int map_state(); // returns : IsUnmapped, IsUnviewable, IsViewable 
  Bool toggle_map(); // to toggle mapping state : if mapped -> Unmap (avv)

  void set_backing_store();  // set backing_store = WhenMapped
  void set_save_under();     // save covered region when mapped

  void Realize(); // Realize the whole Window tree from this root
  void RealizeChildren();

  virtual void clear();
  virtual int eff_width() { return width; } // effective breadth minus pictures

  virtual int DrawString(int x, int y, char* string); // returns string length

  int printw(int x, int y, char* fmt, ...); // called like printf, max 1000 !

  // place a string with font (fixed_fn) at x,y (0 = centered)
  void PlaceText(char* string,int x = 0, int y = 0, XFontStruct * fn = fixed_fn);
  virtual void line(int x0, int y0, int x1, int y1);
  virtual void DrawPoint(int x, int y);
  // new help functions : popup on enter-cb
  void add_help(char* help[]);              // given as vector
  void add_help(char* arg1,...);            // as arg list

  virtual void action(char*, char*) {} // action for windows, that shall
  // be managed from radio_button - BPress-CBs

  void WatchCursor(); // set cursor of main_window to watch
  void ResetCursor(); // set back to normal
  virtual void redraw() {}
  virtual void resize(int, int);
  void frame3d(GC left_top, GC right_bot); // 3D-inner-border
  virtual XImage* GetImage() {  // new 5/2000 : for jpeg savings
    return XGetImage(display,Win,0,0,width,height,AllPlanes,ZPixmap);
  }
  void save_jpeg(char* fina, int q = 60); // q = quality
protected:  
  virtual void BPress_CB(XButtonEvent) {} 
  virtual void BPress_1_CB(XButtonEvent) {}
  virtual void BPress_3_CB(XButtonEvent) {} // obsolete (was popup help)
  virtual void BRelease_CB(XButtonEvent) {} 
  virtual void Enter_CB(XCrossingEvent); 
  virtual void Leave_CB(XCrossingEvent) {}
  virtual void Motion_CB(XMotionEvent) {} // pointer movements
  virtual void Expose_CB(XExposeEvent);
  virtual void KeyPress_CB(XKeyEvent) {}
  virtual void Configure_CB(XConfigureEvent) {} // only main_windows
  virtual void ClientMsg_CB(XClientMessageEvent) {} // for msg from w manager

public:  
  void CallBack(XEvent &event) ;
};

// for special applications : in the main_loop use polling 
// extern Bool polling_mode; // use polling instead of XNextEvent
// extern void (*poll_handler)(); // called after each polling 

class main_window : public window {
protected:
  Bool polling_mode; // for special applications: in the main_loop use polling 
  // with the virtual function "polling_handler" instead of XNextEvent
  char *name;
public: 
  int exit_flag; // used in main_loop to break it
  main_window(char *Name, int w, int h, int fix_pos = 2, int x = 0, int y = 0);
  ~main_window();
  void do_popup(int x, int y); // Realize at absolute x,y-coords
  virtual void Configure_CB(XConfigureEvent ev);
  virtual void ClientMsg_CB(XClientMessageEvent ev);
  void set_icon(char ibits[], int iwidth, int iheight);
  void main_loop(); 
  virtual void polling_handler() {}
};

// A window that stores its content in a Pixmap, to enable a quick Expose
// Each drawing operation is done to Pixmap, Map & Expose copy pix -> Win
// 
class pixmap_window : public window {
protected:
  Pixmap pix;  // to store the image and re-map in expose events
public:
  pixmap_window(window & parent, int w = 0, int h = 0, 
	       int x = 0, int y = 0, int bw = 1);
  virtual ~pixmap_window();
  virtual void clear();
  virtual void Map(); // copy pix -> Win
  virtual int DrawString(int x, int y, char * string);
  virtual void line(int x0, int y0, int x1, int y1);
  virtual void DrawPoint(int x, int y);
  virtual void Expose_CB(XExposeEvent ev); 
  virtual void draw_interior() {}
  virtual void redraw() { clear(); Map(); }
  virtual void resize(int,int);  
  virtual XImage* GetImage() {  // new 5/2000 : for jpeg savings
    return XGetImage(display,pix,0,0,width,height,AllPlanes,ZPixmap);
  }
};

// very simple window to place text
class text_win : public window {
char *text;
public:
  text_win(window &parent, char *text, int w,int h, int x, int y, int bw = 0) :
    window(parent,w,h,x,y,bw), text(text) {}
  virtual void redraw() { PlaceText(text);  }
};

// a class for drawing an infoline in a window (max 200 chars), not flickering
class info_window : public pixmap_window {
public:
  char info[200];
  info_window(window &parent,int w, int h, int x, int y) :
    pixmap_window(parent,w,h,x,y) { info[0] = 0; }
  virtual void draw_interior() { PlaceText(info); }
  char* infoend() { return (info + strlen(info)); } // for appending to end
};

// manage position of children
class horizontal_container {
  int min_w, max_w; // minimum & maximum width for children
public:
  int xp, yp; // place position for next child, is updated from children
  int getw(int w) { return ((w > min_w) ? ((w > max_w) ? max_w : w) : min_w) ;}
  horizontal_container(int minw, int maxw) : min_w(minw), max_w(maxw) { xp = yp = 0; }
};

class menu_bar : public window, public horizontal_container {
public:
  menu_bar(window& parent, int w, int h = 20, int x = 0, int y = 0, 
	   int minw = 0, int maxw = 1000, int bw = 1)
  : window(parent,w,h,x,y,bw), horizontal_container(minw,maxw) {}
  virtual void add_child(window *child, int x, int y) { 
    window::add_child(child,x,y); xp += getw(child->width); 
  }
};

class text_popup : public main_window  {
  char ** pop_text;
public: 
  text_popup(char * WMName, int w, int h, char *text[]); 
  void Expose_CB(XExposeEvent ev);
};

// Konstanten zur 3d Darstellung
#define down3d 0 
#define up3d   1 
#define flat3d 2

// draws 3D-borders, mode = up3d, flat3d (background pix), down3d
struct GC3 { GC forgr, bright, dark; }; // 3 GCs for buttons

void color_GC(unsigned short r, unsigned short g, unsigned short b, GC3 *gc3);
void rect3d(Window Win, short x, short y, short w, short h, GC left_top, GC right_bot);
void rect3d(Window Win, int mode, short x, short y, short w, short h); // use default GS-s
void tri3d_s(Window Win, int mode, short x, short y, short w, short h);

// a window with pseudo-3d frames
class plate : public window, protected GC3 { 
  int mode3d;
public:
  plate(window & parent, int w, int h, int x = 0, int y = 0, int mode3d = up3d);
  virtual void redraw();    
  void set_GC(struct GC3 *gc3); // set other than the default light-blue
protected:  
  void frame3d(int mode); // set frame for mode
  virtual void default_frame() { frame3d(mode3d); }
};

class button : public plate {
  //  parent is a pulldown menu -> other dynamic frame mode
  int in_pulldown;
protected:
  // the breadth of strings for  menu_bar (for auto-placement in container)
  int Nwidth(char *str) { return 6*strlen(str) + 6; }
  bool enabled; // active or not
public:
  char * Name;
  void init_button(window *parent);
  button (window & parent, char * Name, int w, int h, int x = 0, int y = 0) :
  plate (parent, w, h, x, y), Name(Name) { init_button(&parent); }

  button (window & parent, char* Name, char** /*help_text*/, int w, int h, int x = 0, int y = 0) : 
  plate (parent, w, h, x, y), Name(Name) { init_button(&parent); }
  
  // autosizing buttons
  button (menu_bar & parent, char * Name) :
   plate (parent, parent.getw(Nwidth(Name)), parent.height, parent.xp, parent.yp), 
   Name(Name) { init_button(&parent); }
  virtual ~button();
  virtual void default_frame() { frame3d(in_pulldown ? flat3d : up3d);  }
  void enter_frame() { frame3d(in_pulldown ? up3d : flat3d); }
  virtual void redraw(); 
  void disable() { enabled = false; redraw(); }
  void enable() { enabled = true; redraw(); }
protected: 
  virtual void Enter_CB(XCrossingEvent ev) { window::Enter_CB(ev); if (enabled) enter_frame(); }
  virtual void Leave_CB(XCrossingEvent ev) { window::Leave_CB(ev); default_frame(); }
  virtual void BPress_CB(XButtonEvent) { if (enabled) frame3d(down3d); }

  virtual void BPress_1_CB(XButtonEvent ) {}
  virtual void BRelease_1_action() {} // hook for callbacks with Button1
  virtual void BRelease_CB(XButtonEvent ev);
};

//                 ##### delete_button #####
// for ordered deleting a window and all of its children recursively
// following events for them are catched by setting the thisW-pointer to NULL
class delete_button : public button { 
window * to_del;
public: 
  delete_button(window & parent, window * to_del, int w, int h, int x, int y): 
    button(parent, "delete", w, h, x, y), to_del(to_del) {}
  delete_button(menu_bar & parent, window * to_del) :
    button(parent, "delete"), to_del(to_del) {}
private:
  void BPress_1_CB(XButtonEvent) { to_del->Unmap(); delete (to_del); }
};

//             **** "quit_button" ****
// exiting main_loop with setting the exit_flag of corr. main_window
class quit_button : public button { 
public: 
  quit_button(window & parent, int w, int h, int x, int y) : 
    button(parent, "quit", w, h, x, y) {}
  quit_button(menu_bar & parent) : button(parent, "quit") {}
private:
  void BPress_1_CB(XButtonEvent) { mainw->exit_flag = TRUE; }
};

// popup_button : realize the popup menu when BPress (make it visibel) 
// if pressed again : make it unvisible 
class popup_button : public button {
protected: 
  main_window * popup_menu; 
public: 
  popup_button(window &parent, main_window * menu, char * Name, 
	       int w, int h, int x, int y) :
    button(parent, Name, w, h, x, y) { popup_menu = menu; }  

  popup_button(menu_bar &parent, main_window * menu, char * Name) :
    button(parent, Name) { popup_menu = menu; } 
protected:
  virtual void BPress_1_CB(XButtonEvent ev);
};

// popup a window with help text and a OK button
// the popup window is created in make_popup from the text array
class help_button : public popup_button {
public: 
  help_button(window & parent, int x, int y, char * text[], int w = 60, int h = 20) :
    popup_button(parent, NULL, "help", w, h , x, y) { make_popup(text); }

  help_button(menu_bar & parent, char * Name, char * text[]) :
    popup_button(parent,NULL, Name) { make_popup(text); }
private:
  void make_popup(char * text[]);
};

// *** "callback_button" class ****
// a button attached with a callback function on BRelease !! event
class callback_button : public button {
  void (*callback) ();
public:
  callback_button (window & parent, char * Name, void (*cb)(), 
		   int w, int h, int x = 0, int y = 0) : 
  button (parent, Name, w, h, x, y), callback(cb) { }
  
  callback_button (menu_bar & parent, char * Name, void (*cb)()) : 
  button (parent, Name), callback(cb) { }

protected:
  virtual void BPress_1_CB(XButtonEvent) { } // do nothing
  virtual void BRelease_1_action()  { (*callback)(); } 
};

// *** "template_button" class ****
// invokes any member function (void) of an instance of class T, or
// a simple function that has T as argument
// ie. the callback-function is of type "void cb(T)"
// example:  void dist(float x) {ww->z +=x;..} 
//            template_button <float> (mb,"Name", dist, 2);

template <class T>
class template_button : public button {
  void (*callback) (T);
  T value;
public:
  template_button (window & parent, char * Name, void (*cb)(T), T val,
		   int w, int h, int x = 0, int y = 0) : 
  button (parent, Name, w, h, x, y), callback(cb) {value = val; }
  
  template_button (menu_bar & parent, char * Name, void (*cb)(T), 
		  T val) : 
  button (parent, Name), callback(cb) { value = val; }

protected:
  virtual void BPress_1_CB(XButtonEvent) { } // do nothing
  virtual void BRelease_1_action()  { (*callback)(value); }
};

//   ***** instance_button : template button for member-functions of class
template <class T>
class instance_button : public button {
  void (T::*member)();
  T *instance;
public:
  instance_button(window &parent, char *Name, void (T::*mem)(), T *inst,
		  int w, int h, int x, int y) :
    button(parent,Name,w,h,x,y) { member = mem; instance = inst; }

  instance_button(menu_bar &parent, char *Name, void (T::*mem)(), T *inst) :
    button(parent,Name) { member = mem; instance = inst; }  
protected:
  virtual void BPress_1_CB(XButtonEvent) { (instance->*member)(); }
  virtual void BRelease_1_action() {} 
};

// *** "function_button" class **** : yet another variant of callbacks
// a button attached with a callback function on BRelease !! events
// the callback_function gets all arguments of the  ellipses
// (pointer or int); max 10 
// default arguments are not prohibited !

#include <stdarg.h>

typedef void (*CB)(...); // type of the callback fn

class function_button : public button {
  CB callback;
  void *values[10]; // the passed values
public:
  function_button (window & parent, char * Name,  
                   int w, int h, int x, int y, CB cb,  ...);

  function_button (menu_bar & parent, char * Name, CB cb, ...);
protected:
  virtual void BPress_1_CB(XButtonEvent) { } // do nothing
  virtual void BRelease_1_action() {
    (*callback)(values[0],values[1],values[2],values[3],values[4],values[5],
		values[6],values[7],values[8],values[9]);} 
};

typedef void (*VVP)(void *); // typecast for callbacks with void* argument
extern void switch_dummy(void *); // default dummy fn : does nothing

// ****** class switch_button *****
// a button with 2 states of display, which switch on click
// the 2. string should be <= the first (= initial)
class switch_button : public button {
  char *Narr[2]; // the two strings for display
  VVP callbck; // the callback to call with instance ptr
  void *instptr;
  Bool *toggle; // the pointer to toggled value
public:  
  switch_button (menu_bar & parent, char *Name1, char *Name2, Bool *toggle,
		 VVP inf = switch_dummy , void * toinf = NULL);
  switch_button (window & parent, char *Name1, char *Name2, Bool *toggle,
		 VVP inf, void * toinf, int w, int h, int x, int y);
  void switch_it();
protected:
  virtual void BPress_1_CB(XButtonEvent) { } // do nothing
  virtual void BRelease_1_action() { switch_it(); }
};

//     ****** class toggle_button : with display of state ****
class toggle_button : public button {
  int *vptr; // the pointer to  toggle-value
  int xright; // place for picture on the right side
  virtual int eff_width() { return (width - xright); } // for PlaceText
public:
  toggle_button(menu_bar &parent, char *Name, int *ref) : 
      button(parent,ext_string(Name)) { vptr = ref ; xright = 12; }
  toggle_button(window &parent, char *Name, int *ref, int w, int h, 
		 int x, int y ) :
      button(parent,Name,w,h,x,y) { vptr = ref; xright = 12; }
  void picture() { // 8x8 Pixel gross
    int offs = (height-8)/2; // distance to top- and bottom border
    rect3d(Win,(*vptr) ? down3d : up3d, width-xright,offs,8,8); }
protected:
  virtual void toggle_cb (int) {}  // can be overloded
  virtual void BRelease_1_action() { 
    *vptr = ! *vptr; picture(); toggle_cb(*vptr); }
  virtual void redraw() { button::redraw(); picture(); }
};

//   ************  frequently used : toggle and redraw a window
class toggle_redraw_button : public toggle_button {
window *win;
public:
  toggle_redraw_button(menu_bar &parent, char * Name, int *ref, window *win):
     toggle_button(parent,Name,ref), win(win) { }
  virtual void toggle_cb(int) { win->redraw(); }
};

// *********************************************************************
//                   PULLDOWN windows
// pulldown window : a window child from root_window, not yet visible, 
// not managed from WM, position is determined from the button at popup time
class radio_button;

class pulldown_window : public main_window {
  radio_button *rold; // the last selected radio_button
public:
  int nb; // number of buttons
  button **rbp; // vektor of (radio)buttons
  pulldown_window (int w, int h, int nb, button **rbp);
  void toggle(radio_button *rb);
  void handler(int x, int y); // to handle X-pointer
};

//     **** "pulldown_button" class *****
// map the window (menu) on root when button is activated (BPress)
// the window is mapped to absolute co-ordinates !
class pulldown_button : public button { 
  pulldown_window  * pulldown_menu; 
  int xright;
  virtual int eff_width() { return (width-xright); }
public:
  pulldown_button (window & parent, pulldown_window * menu, char * Name, 
		   int w, int h, int x, int y);
  pulldown_button(menu_bar & parent, pulldown_window * menu, 
		  char * Name);
  pulldown_button (window & parent, pulldown_window * menu, char * Name, 
		   char ** help_text, int w, int h, int x, int y);
  void picture();
protected:
  virtual void BPress_1_CB(XButtonEvent ev);  
  virtual void BRelease_CB(XButtonEvent) { pulldown_menu->Unmap(); }
  virtual void Leave_CB(XCrossingEvent ev) { // if B1 was not pressed
    if (!(ev.state & Button1Mask)) default_frame(); }
  virtual void redraw() { button::redraw(); picture(); }
};


// creates single button entry with Name and value in a radio_menu
class radio_button : public toggle_button {
  char * value;  // the special value
  char * menu_name ; // the name of the button which pulled this radio_menu
  window * action_win;
public:  
  Bool status; // managed by the parent pulldown_window
  radio_button(pulldown_window &parent, char * MName, 
	       int w, int h, int x, int y, char * val, window * action) 
       : toggle_button(parent,val,&status,w,h,x,y), value(val) {
    menu_name = MName; // Name of menu_button; is passed to action
    action_win = action;
  }
protected:
  virtual void BRelease_1_action() { 
    if (action_win) action_win->action(menu_name, value); 
    ((pulldown_window *) parentw)->toggle(this); // inform parent which is set 
  }
};

// makes a radio-menu (toggle) with  named buttons (name = value : string)
// list : consists of char* : { "value1", "value2",..., 0 }
// action_win : window which "action" method is to call after toggle
// the Name (as pointer) is passed also -> to know which menu was activated
// trick : if w == 0 parent must be menu_bar -> use autoplacement
pulldown_button * make_radio_menu(window &parent, char *Name,
				  char **blist,  window * action_win = 0,
				  int w= 0, int h= 0, int x= 0, int y= 0,
				  int inival = -1);

// inival is the index of the radio_button that is initially set
pulldown_button * make_radio_menu(menu_bar &parent, char *Name,
				  char **blist,  window * action_win = 0,
				  int inival = -1);

// analogous : with help popup
pulldown_button * make_radio_menu(window &parent, char *Name, char **list,
				  char ** help_text, window * action_win = 0,
				  int w= 0, int h= 0, int x= 0, int y= 0,
				  int inival = -1); 

// for callback_buttons : name string, callback function
struct but_cb { char * bname; void (*cb) (); };

// makes pulldown_menu with a list of callback_buttons
// und einem pulldown_button (im parent) der es aktiviert
pulldown_button * make_pulldown_menu(window &parent, char *Name, 
				     int nbuttons, struct but_cb list[],
				     int w= 0, int h= 0 , int x= 0, int y= 0);

// ---------------------- POPUP WINDOWS ------------------------------------

// unmap_button : a special button to Unmap the parent
//                 on BPress, esp. usefull for popup menus
class unmap_button : public button { 
  window * to_unmap;
public: 
  unmap_button(window & parent, char * string,
	       int w, int h, int x, int y) : 
  button(parent,string, w, h, x, y) { to_unmap = &parent;}  
  // 2. constructor, used for unmap_buttons on menu_bars
  unmap_button(menu_bar & parent, char * string, window * unmap) :
    button(parent,string) { to_unmap = unmap;}
private:
  virtual void BPress_1_CB(XButtonEvent) { to_unmap->Unmap(); }
};

// computes for string array: max length of strings && number of strings 
void compute_text_size(char *text[], int &cols, int &lines);

struct f_point { 
  float x, y; 
  f_point() {}
  f_point(float x, float y) : x(x), y(y) {}
};

// define a co-ordinate system in a window 
class coord_window : public pixmap_window {
protected:
  int x0,y0; // window-coordinates of origin
  int w_eff,h_eff; // effective	width and height of coord-sys
  int w_diff,h_diff,rxl,ryd;
  double xl,yd, // WC of left, bottom edge (origin, ia: 0,0)
         xr,yu, // WC of right, top edge (ia: xmax, ymax)
         xf,yf; // transformation factors
public:

  void define_coord(double x1, double y1, double x2, double y2);
  virtual void resize(int, int);

  // compute total window-coordinates from world-values
  int x_window(double x);
  int y_window(double y);
  XPoint p_window(double x, double y); // returns same as XPoint
 
  // back transformation : window coords to world-values
  double x_org(int xw);
  double y_org(int yw);

  // rx : free rand left/right & ry : bottom
  coord_window(window & parent, int w, int h, int x, int y, 
	       int rxl = 5, int rxr = 5, int ryd = 5, int ryu = 5);
 
  // draws line with normed window coordinates
  // ie. origin => (0,0), y grows upwards !!
  void rline(int xp, int yp, int xq, int yq) {
    line(x0 + xp, y0 - yp, x0 + xq, y0 - yq); }
  
  void draw_coords(); // draw coordinate system 
  // draw x-ticks from xl..xo in dx-steps, max n ticks
  void x_ticks(double dx, int n = 1000);
  void y_ticks(double dy, int n = 1000);

  void wline(double x1, double y1, double x2, double y2) {
    line(x_window(x1),y_window(y1),x_window(x2),y_window(y2)); 
  }
  void f_line(f_point p1, f_point p2) { // a line in world coords
    wline(p1.x, p1.y, p2.x, p2.y);
  }
  void rectangle(double x1, double y1, double x2, double y2) {
    wline(x1,y1,x2,y1); wline(x1,y1,x1,y2); 
    wline(x2,y1,x2,y2); wline(x1,y2,x2,y2);
  }

  void graph(int nx, double f[]); 
  void draw_interior() {}

};

// invokes system-call with cmdline-string as argument
class system_button : public button {
char * cmdline;
public: 
  system_button(window &parent,char *Name, char *cmdline, 
	      int w, int h, int x, int y) : 
    button(parent,Name,w,h,x,y), cmdline(cmdline) {}
  virtual void BPress_1_CB(XButtonEvent);
};

// calls 'system("xwd -in wid " + arg)' and produces X-Window-dump of the
// window 'dumpw'; 
// with "arg" the output can be controlled
// eg. "-out -nobdr dump.file" or " | xpr | lpr " as hardcopy 
// with "xwud -in dump.file" or "xpr" to display or print
// eg:  'xwd_button du1(mb,"dump","-nobdrs -out dump.file",pwindow);'
class xwd_button : public button { 
window * dumpw;
char * arg; 
public: 
  xwd_button(window &parent, char *Name, char *arg, window *dumpw,
	      int w, int h, int x, int y) : 
    button(parent,Name,w,h,x,y), dumpw(dumpw), arg(arg) {}
  
  xwd_button(menu_bar &parent,char *Name, char *arg, window *dumpw ) : 
    button(parent,Name), dumpw(dumpw), arg(arg) {}

  void BPress_1_CB(XButtonEvent);
};
 
// **************************************************************
//               SCROLLBARS

// sliders as movable plate for scrollbars
class slider : public plate { 
public: 
  slider(window &parent, int w, int h, int x, int y); 
  virtual void redraw(); // called from Expose_CB
};

// a simple scrollbar without display of the value (should not be used)
// if the 1. constructor (without xanf) is used, the slider must explicitely 
// be set !!

class pure_scrollbar : public plate {
  slider * bar;
protected:
  int sw,sh,sy,xoff,xmax,xspan,xact;
public:
  int nticks; // the number of tick lines (def = 0)
  void set_slider(int x); // fuer Anfang: Setzen des sliders nach x
  void init (); // Setzen der Elemente
  // 1. constructor: without initial value
  pure_scrollbar(window &parent, int w, int h, int x, int y) :
    plate (parent,w,h,x,y,down3d) { init(); }
  // 2. constructor : with initial value 
  pure_scrollbar(window &parent, int w, int h, int x, int y, int xanf) :
    plate (parent,w,h,x,y,down3d) { init(); set_slider(xanf);}

protected:
  // virtual function "callbck" is called from move
  virtual void callbck(int x) { printf(" %d",x); fflush(stdout); } 

  void move(int x); // Bewegen des sliders (x = Pointer) 
  void move_cb(int x); // Bewegen des sliders (x = Pointer) und callbck  

  virtual void redraw();

  // Springen bei Maus-Click button1
  virtual void BPress_1_CB(XButtonEvent ev) { move_cb(ev.x - xoff); }

  // Ziehen, wenn Button1 gedrueckt
  virtual void Motion_CB(XMotionEvent ev) { 
    if (ev.state & Button1Mask) { move_cb(ev.x - xoff); }
  } 
  virtual void resize(int, int);
};

// to display the actual value of a slider
class display_window : public plate { 
char * val; 
public: 
  display_window(window &parent, char *def, int w, int h, int x, int y, 
		 int mode3d) :
    plate(parent,w,h,x,y,mode3d) { val = def; }
  void draw_val() { PlaceText(val); }
  void set_text_mode(int mode); // mode 0 : Loeschen, 1 : Schreiben
  virtual void redraw() { plate::redraw(); draw_val(); }

};

//   ********* class scrollbar ********
// the union "fn_union" is used to access the function pointer 
// for the 2 types of info function, that occur as callbacks
union fn_union {  
  void (*empty)();     // der parameterlose call mode (Form 1)
  void (*vptr)(void*); // der callmode mit void* (Form 2)
  void *value;         // fuer Test auf NULL
};

// 2 constructors : with different callback-forms   
//      1. callback inf() as function without parameters  (old version )
//      2. callback inf(void *), gets the (void*) argument "to_inf" 
//         with this form memberfunctions of other classes can be called 
// "minp, maxp" are the limit values of the scrollbar, which are mapped to
//          [0..xspan] pixels
//          if maxp == 0 (default) the width of the slider is adopted
// "format" serves as transformation value
// "inf"    is an callback, which is called upon each move of the slider 
//          (without arguments), the actual value can be querried from
//          "scrollbar.value" 
// "xstart" is the starting value of the slider

class scrollbar : public pure_scrollbar {
  pure_scrollbar * ps;
  char str[80];
  void *to_inform; // pointer for 2nd form
  fn_union inffn;
protected:
  display_window *disp_win;
  char * format; // the format string for display, like in printf: "Wert = %4x"
  double factor;   // the conversion factor x into pixels = 0..w -> min..max 
public:
  float min, max, value;
private:
  void setval(float x) { // update string and value
    value = x; sprintf(str,format,x); 
  }
  int pwidth(int w) { return (w-60); } // the eff. width of pure_scrollbar
  float pix_to_val(int pix) { return (pix*factor + min); }
  int val_to_pix(float x) { return (irint((x-min)/factor)); }
public:
  void init(window &parent, int w, int h, int x, int y, float minp, float maxp, float xstart);
  // 1. constructor
  scrollbar(window &parent, void (*inf)(), int w, int h, int x, int y, 
	    float minp=0, float maxp=0, float xstart = 0,char *format= "%.0f");
  // 2. constructor
  scrollbar(window &parent, void (*inf)(void*), void * to_inf, int w, int h, int x, int y, 
	    float minp=0, float maxp=0, float xstart=0, char *format= "%.0f");

  // explicite setting of slider and display 
  void change(float x) { move( val_to_pix(x) ); callbck_val(x);}   
  // explicite setting of slider and display (without callback !) 
  void set(float x) { move( val_to_pix(x) ); display_val(x); } 
protected:
  virtual void callbck(int pix) {  // called from move_cb (mouse events)
    callbck_val( pix_to_val(pix) );
  }
  void display_val(float x);          // set and display new x
  virtual void callbck_val(float x);  // called from change : disp_val + callback
  virtual void resize(int, int);
};

// **** class tick_scrollbar ***** : scrollbar with ticks and numbers
// has fixed height (20 + 15 = 35) with ticks and value displays 

#define MAXTCKS 20 // max number of ticks+2 

class tick_scrollbar : public scrollbar {
  text_win *valtxt[MAXTCKS+2]; // display windows for : max 20 ticks !!
  char *strvec; // holds all tick numbers as C-strings 
  char *valstr[MAXTCKS+2]; // pointer to individual tick-string into strvec
  void tickstr();
public:
  tick_scrollbar(window &parent, void (*inf)(void*), void * to_inf,
		 int w, int x, int y, int n_ticks, float minp = 0, 
		 float maxp = 0, float xstart = 0, char *format= "%.0f");
  ~tick_scrollbar();
  void adapt(int maxp, int xstart);
};
  
class play_scrollbar;

// container class for interaction between play_scrollbar and 
// a lattice drawer class 
// methods must be overwritten from derived classes,
// a pointer of this class is given to play_scrollbar as argument
class stepper {
public:
  virtual void seek_step(float v) = 0; // seek and perform actual drawing
  virtual Bool switch_play_mode(void (play_scrollbar::*)(), play_scrollbar*) = 0; 
  // returns actual mode
};

// **** class play_scrollbar ***
// tick_scrollbar, that adds playback- and stepping buttons left and right  
class play_scrollbar : public tick_scrollbar {
  stepper *stp;
  Bool play_mode;
  // button callback functions :
public:
  void step_fwd() { change(value+1); } 
  void step_bck() { change(value-1); } 
  void reset() { change(min); }
  // called when setting the slider, or indirectly from step_xxx
  void updated() { stp->seek_step(value); }
  void switch_play() { play_mode = stp->switch_play_mode(&play_scrollbar::step_fwd, this); }

  play_scrollbar(window &parent, int w, int x, int y, int n_ticks, stepper *stp,
		 int minp = 0, int maxp = 0, int xstart = 0);
};


// class for temporarily set and reset cursor for a window 
// using constructors & destructors
class TempCursor {
 window * win;
 public:
  TempCursor(window *w) {
    win = w;
    XDefineCursor(display, win->Win, watch_cursor);
   }
  ~TempCursor() { XUndefineCursor(display, win->Win); }
};

// ***************************************
// class "edit_window" for editing  of strings, max 200 chars long 
// two virtual fn should be newly defined in derived classes: 
//   enter - action on completion
//   escape - aborting
class edit_window : public plate {
  int cp; // text cursor position in string (0..strlen)
  int xs; // x-pos of string start
protected:
  void mark_cursor();
  virtual void Enter_CB(XCrossingEvent ev);
  virtual void Leave_CB(XCrossingEvent ev);

  void del_char();
  void ins_char(char x);
public:
  char value[200];  
  edit_window(window &parent, char *str, int w,int h, int x, int y);
  virtual void redraw();
  virtual void enter() { printf("%s\n",value); } // to overwrite
  virtual void escape() { memset(value,0,80); cp = 0; } // clears string
  virtual void format_error() { XBell(display,10); }
  void KeyPress_CB(XKeyEvent ev);
};

// class to display a simple analogue clock bound to an external time variable
class clock_win : public pixmap_window {
public:
  int* tptr; // pointer to the time variable (in seconds), 
             // to be updated externally !
  int xc,yc; // centre co-ordinates
  float rh,rm; // rx = radius of minute/hour arrows
  int d; // diameter of the clock
    // *tptr is the timer
  clock_win(window &parent, int *tptr,int w, int h, int x, int y);
  void arrow(double phi, float r);  // display a centered arrow with radius r
  virtual void draw_interior();
  virtual void resize(int w, int h);
  void init();
};

//  ************* twodim_input ***********
// a class used to get a twodim value from a mouse pointer driven slider

class twodim_input;

typedef void (*CBHOOK)(void *,twodim_input *); // the correct type for cbhook 

class twodim_input : public plate {
  plate *bar;
  void *vptr; // the first arg for cbhook -> should be a this-pointer
protected:
  int sw,sh; // slider size
  int sx,sy; // slider offset to borders
public:
  int xact,yact; // actual position (0..*span)
  int xspan,yspan; // span width for movement x,y = [0..zspan]
  // the cbhook should be used to respond on input 
  void (*cbhook)(void*, twodim_input *);

  // swp, shp : width/height of slider; if = 0 : confined in this direction 
  // vptr : passed as 1. argument to cbhook
  twodim_input(window &parent, int w, int h, int x, int y, int swp, int shp,
	       void *vptr = NULL);
protected:
  void set_vars();
  void move(int x, int y);  // called from Events
  virtual void BPress_CB(XButtonEvent ev);
  virtual void Motion_CB(XMotionEvent ev);

public: 
  void set_slider(int x, int y);
  void slider_adapt(int swp,int shp); // called from resize && others 
  void resize(int w, int h);
  void configure(int w, int h, int swp, int shp, int x, int y);
};

// two simple convinience derivations from twodim_input
class horizontal_shifter : public twodim_input {
public:
  horizontal_shifter(window &parent, int w, int h, int x, int y, int sw, 
		     CBHOOK cbh, void *vptr = NULL);
};

class vertical_shifter : public twodim_input {
public:
  vertical_shifter(window &parent, int w, int h, int x, int y, int sh,
		   CBHOOK cbh, void *vptr = NULL); 
};

// scrolled_window has a virtual window which can be shifted with shifters
// arguments are : real width/height, virtual width/height
// (the first window with correct resizing)
// the virtual window must be derived from class virtual_window !!!
class scrolled_window : public window {
  int xp, yp; // actual position
  int hvis,wvis; // visible window size
public:
  // the hook called from shifters : shift drawing_area
  void cbhook(twodim_input *ts); 
  twodim_input *vs, *hs;
  window *clip; // the clipped region
  window *virt_win; // the virtual window
  int hvirt, wvirt; // the virtual size

  scrolled_window(window &parent, int w, int h, int vw, int vh, 
	       int x = 0, int y = 0);
  virtual void resize(int w, int h);
};

// class to enable a convinient linking of virtual window for scrolled_window
// *** an instance must be defined for every scrolled_window *** !!!
class virtual_window  : public window {
public:
  virtual_window(scrolled_window *scr) : 
  window(*(scr->clip), scr->wvirt, scr->hvirt,0,0,0) { // no border
    scr->virt_win = this; 
  }
  virtual void redraw() = 0; // if not defined : useless !!
  virtual void resize(int, int) {} // do nothing !!
};

#endif // WINDOW_H