1 
2 /******************************************************************************
3 * MODULE     : x_window.cpp
4 * DESCRIPTION: Windows under X11
5 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11 
12 #include "X11/x_window.hpp"
13 #include "message.hpp"
14 #include "boot.hpp"
15 #include "x_picture.hpp"
16 
17 extern int nr_windows;
18 
19 hashmap<Window,pointer> Window_to_window (NULL);
20 
21 /******************************************************************************
22 * Creation and deletion of an x_window
23 ******************************************************************************/
24 
25 void
set_hints(int min_w,int min_h,int max_w,int max_h)26 x_window_rep::set_hints (int min_w, int min_h, int max_w, int max_h) {
27   XSizeHints* size_hints;
28   XWMHints*   wm_hints;
29   XClassHint* class_hints;
30   ASSERT (size_hints= XAllocSizeHints (), "out of memory (X server)");
31   ASSERT (wm_hints= XAllocWMHints (), "out of memory (X server)");
32   ASSERT (class_hints= XAllocClassHint (), "out of memory (X server)");
33 
34   XTextProperty Window_Name;
35   XTextProperty Icon_Name;
36   ASSERT (XStringListToTextProperty (&name, 1, &Window_Name) != 0,
37 	  "out of memory (X server)");
38   ASSERT (XStringListToTextProperty (&name, 1, &Icon_Name) != 0,
39 	  "out of memory (X server)");
40 
41   // time_t start_1= texmacs_time ();
42   Pixmap pm= retrieve_pixmap (load_xpm ("TeXmacs.xpm"));
43   // cout << "Getting pixmap required " << (texmacs_time ()-start_1) << " ms\n";
44 
45   // time_t start_2= texmacs_time ();
46   size_hints->flags       = PPosition | PSize | PMinSize | PMaxSize;
47   size_hints->min_width   = min_w;
48   size_hints->min_height  = min_h;
49   size_hints->max_width   = max_w;
50   size_hints->max_height  = max_h;
51   wm_hints->initial_state = NormalState;
52   wm_hints->input         = true;
53   wm_hints->icon_pixmap   = pm;
54   wm_hints->flags         = StateHint | IconPixmapHint | InputHint;
55   class_hints->res_name   = name;
56   class_hints->res_class  = name;
57 
58   XSetWMProperties (
59     dpy,
60     win,
61     &Window_Name,
62     &Icon_Name,
63     gui->argv,
64     gui->argc,
65     size_hints,
66     wm_hints,
67     class_hints
68   );
69 
70   XFree(size_hints);
71   XFree(wm_hints);
72   XFree(class_hints);
73   XFree(Window_Name.value);
74   XFree(Icon_Name.value);
75   // cout << "Setting hints required " << (texmacs_time ()-start_2) << " ms\n";
76 }
77 
78 void
initialize()79 x_window_rep::initialize () {
80   SI min_w= Min_w, min_h= Min_h;
81   SI def_w= Def_w, def_h= Def_h;
82   SI max_w= Max_w, max_h= Max_h;
83 
84   dpy= gui->dpy;
85   gc = gui->gc;
86   full_screen_flag= false;
87 
88   // time_t start_1= texmacs_time ();
89   ren->set_origin (0, 0);
90   ren->decode (def_w, def_h); def_h= -def_h;
91   ren->decode (min_w, min_h); min_h= -min_h;
92   ren->decode (max_w, max_h); max_h= -max_h;
93   // cout << "Size computation required " << (texmacs_time ()-start_1) << " ms\n";
94 
95   // time_t start_2= texmacs_time ();
96   unsigned long valuemask= CWOverrideRedirect | CWSaveUnder;
97   //unsigned long valuemask= CWOverrideRedirect | CWSaveUnder | CWBackingStore;
98   XSetWindowAttributes setattr;
99   setattr.override_redirect= (name==NULL);
100   setattr.save_under       = True; // (name==NULL);
101   // setattr.backing_store    = Always;
102   // FIXME: backing store does not seem to work correctly
103   if (win_w == 0) win_w= def_w;
104   if (win_h == 0) win_h= def_h;
105   if ((win_x+ win_w) > gui->screen_width) win_x= gui->screen_width- win_w;
106   if (win_x < 0) win_x= 0;
107   if ((win_y+ win_h) > gui->screen_height) win_y= gui->screen_height- win_h;
108   if (win_y < 0) win_y=0;
109   win= XCreateWindow (dpy, gui->root, win_x, win_y, win_w, win_h, 0,
110 		      gui->depth, InputOutput, CopyFromParent,
111 		      valuemask, &setattr);
112   ren->win= (Drawable) win;
113   // cout << "XWindow creation required " << (texmacs_time ()-start_2) << " ms\n";
114 
115   //cout << "Hints: "
116   //     << min_w << ", " << min_h << " --- "
117   //     << def_w << ", " << def_h << " --- "
118   //     << max_w << ", " << max_h << "\n";
119   if (name == NULL) name= const_cast<char*> ("popup");
120   if (the_name == "") {
121     the_name= name;
122     mod_name= name;
123   }
124   set_hints (min_w, min_h, max_w, max_h);
125 
126   unsigned long ic_mask= 0;
127   ic_ok= false;
128   if (gui->im_ok) {
129     ic= XCreateIC (gui->im,
130 		   XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
131 		   XNClientWindow, win,
132 		   NULL);
133     if (ic == NULL)
134       cout << "TeXmacs] Warning: couldn't create input context\n";
135     else {
136       ic_ok= true;
137       XGetICValues (ic, XNFilterEvents, &ic_mask, NULL);
138     }
139   }
140 
141   XSelectInput (dpy, win,
142 		ExposureMask | StructureNotifyMask |
143 		SubstructureNotifyMask | FocusChangeMask |
144 		PointerMotionMask | EnterWindowMask | LeaveWindowMask |
145 		ButtonPressMask | ButtonReleaseMask |
146 		KeyPressMask | ic_mask);
147 
148   Atom wm_protocols     = XInternAtom(dpy, "WM_PROTOCOLS", 1);
149   Atom wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", 1);
150   XSetWMProtocols (dpy, win, &wm_protocols, 1);
151   XSetWMProtocols (dpy, win, &wm_delete_window, 1);
152 
153   nr_windows++;
154   Window_to_window (win)= (void*) this;
155   set_identifier (w, (int) win);
156   notify_position (w, 0, 0);
157   notify_size (w, Def_w, Def_h);
158 }
159 
160 static x_drawable_rep*
new_drawable(x_gui gui,x_window win)161 new_drawable (x_gui gui, x_window win) {
162   // FIXME: for gcc 3.*, use this in order to avoid ambiguity
163   // for tm_new with two arguments
164   return new x_drawable_rep (gui, win);
165   //return tm_new<x_drawable_rep> (gui, win);
166 }
167 
x_window_rep(widget w2,x_gui gui2,char * n2,SI min_w,SI min_h,SI def_w,SI def_h,SI max_w,SI max_h)168 x_window_rep::x_window_rep (widget w2, x_gui gui2, char* n2,
169 			    SI min_w, SI min_h, SI def_w, SI def_h,
170 			    SI max_w, SI max_h):
171   window_rep (), w (w2), gui (gui2),
172   orig_name (n2 == ((char*) NULL)? string ("popup"): n2), name (n2),
173   ren (new_drawable (gui2, this)),
174   Min_w (min_w), Min_h (min_h), Def_w (def_w), Def_h (def_h),
175   Max_w (max_w), Max_h (max_h),
176   win_x (0), win_y (0), win_w (Def_w/PIXEL), win_h (Def_h/PIXEL),
177   kbd_focus (w.rep), has_focus (false)
178 {
179   //cout << "Min " << (min_w >> 8) << ", " << (min_h >> 8) << "\n";
180   //cout << "Def " << (def_w >> 8) << ", " << (def_h >> 8) << "\n";
181   //cout << "Max " << (max_w >> 8) << ", " << (max_h >> 8) << "\n";
182 
183   initialize ();
184   gui->created_window (win);
185 }
186 
~x_window_rep()187 x_window_rep::~x_window_rep () {
188   set_identifier (w, 0);
189 
190   XEvent report;
191   while (XCheckWindowEvent (dpy, win, 0xffffffff, &report));
192 
193   tm_delete (ren);
194   if (ic_ok) XDestroyIC (ic);
195   Window_to_window->reset (win);
196   nr_windows--;
197   XDestroyWindow (dpy, win);
198   gui->deleted_window (win);
199 }
200 
201 widget
get_widget()202 x_window_rep::get_widget () {
203   return w;
204 }
205 
206 void
get_extents(int & w,int & h)207 x_window_rep::get_extents (int& w, int& h) {
208   w= win_w;
209   h= win_h;
210 }
211 
212 Window
get_Window(widget w)213 get_Window (widget w) {
214   int id= get_identifier (w);
215   if (id == 0) {
216     failed_error << "widget = " << w << "\n";
217     FAILED ("widget is not attached to a window");
218   }
219   return (Window) id;
220 }
221 
222 x_window
get_x_window(widget w)223 get_x_window (widget w) {
224   int id= get_identifier (w);
225   if (id == 0) return NULL;
226   else return (x_window) Window_to_window[(Window) id];
227 }
228 
229 int
get_identifier(window w)230 get_identifier (window w) {
231   if (w == NULL) return 0;
232   else return (int) (((x_window) w) -> win);
233 }
234 
235 window
get_window(int id)236 get_window (int id) {
237   if (id == 0) return NULL;
238   else return (window) ((x_window) Window_to_window[(Window) id]);
239 }
240 
241 /******************************************************************************
242 * Window apping and appearance
243 ******************************************************************************/
244 
245 void
get_position(SI & x,SI & y)246 x_window_rep::get_position (SI& x, SI& y) {
247 #ifdef OS_WIN32
248   XGetWindowPos (dpy, win, &win_x, &win_y);
249   x=  win_x*PIXEL;
250   y= -win_y*PIXEL;
251 #else
252   int xx, yy;
253   Window ww;
254   XTranslateCoordinates (dpy, win, gui->root, 0, 0, &xx, &yy, &ww);
255   x=  xx*PIXEL;
256   y= -yy*PIXEL;
257 #endif
258 }
259 
260 void
get_size(SI & ww,SI & hh)261 x_window_rep::get_size (SI& ww, SI& hh) {
262   ww= win_w*PIXEL;
263   hh= win_h*PIXEL;
264 }
265 
266 void
get_size_limits(SI & min_w,SI & min_h,SI & max_w,SI & max_h)267 x_window_rep::get_size_limits (SI& min_w, SI& min_h, SI& max_w, SI& max_h) {
268   min_w= Min_w; min_h= Min_h; max_w= Max_w; max_h= Max_h;
269 }
270 
271 void
set_position(SI x,SI y)272 x_window_rep::set_position (SI x, SI y) {
273   x= x/PIXEL;
274   y= -y/PIXEL;
275   if ((x+ win_w) > gui->screen_width) x= gui->screen_width- win_w;
276   if (x<0) x=0;
277   if ((y+ win_h) > gui->screen_height) y= gui->screen_height- win_h;
278   if (y<0) y=0;
279   XMoveWindow (dpy, win, x, y);
280 }
281 
282 void
set_size(SI w,SI h)283 x_window_rep::set_size (SI w, SI h) {
284   w= w/PIXEL; h= h/PIXEL;
285   //h=-h; ren->decode (w, h);
286   XResizeWindow (dpy, win, w, h);
287 }
288 
289 void
set_size_limits(SI min_w,SI min_h,SI max_w,SI max_h)290 x_window_rep::set_size_limits (SI min_w, SI min_h, SI max_w, SI max_h) {
291   if (min_w == Min_w && min_h == Min_h && max_w == Max_w && max_h == Max_h)
292     return;
293   Min_w= min_w; Min_h= min_h; Max_w= max_w; Max_h= max_h;
294   min_w= min_w/PIXEL; min_h= min_h/PIXEL;
295   max_w= max_w/PIXEL; max_h= max_h/PIXEL;
296 
297   XSizeHints* size_hints;
298   ASSERT (size_hints= XAllocSizeHints (), "out of memory (X server)");
299   size_hints->flags       = PMinSize | PMaxSize;
300   size_hints->min_width   = min_w;
301   size_hints->min_height  = min_h;
302   size_hints->max_width   = max_w;
303   size_hints->max_height  = max_h;
304   XSetWMNormalHints (dpy, win, size_hints);
305   XFree(size_hints);
306 }
307 
308 void
set_name(string name)309 x_window_rep::set_name (string name) {
310   if (the_name != name) {
311     c_string s (name);
312     XStoreName (dpy, win, s);
313     XSetIconName (dpy, win, s);
314     the_name= name;
315     mod_name= name;
316   }
317 }
318 
319 string
get_name()320 x_window_rep::get_name () {
321   return the_name;
322 }
323 
324 void
set_modified(bool flag)325 x_window_rep::set_modified (bool flag) {
326   string name= (flag? (the_name * " *"): the_name);
327   if (mod_name != name) {
328     c_string s (name);
329     XStoreName (dpy, win, s);
330     XSetIconName (dpy, win, s);
331     mod_name= name;
332   }
333 }
334 
335 void
set_visibility(bool flag)336 x_window_rep::set_visibility (bool flag) {
337   if (flag) XMapRaised (dpy, win);
338   else XUnmapWindow (dpy, win);
339 }
340 
341 void
set_full_screen(bool flag)342 x_window_rep::set_full_screen (bool flag) {
343   if (full_screen_flag == flag) return;
344   string old_name= get_name ();
345   if (old_name == "")
346     old_name= as_string (name);
347   if (flag) {
348     save_win= win;
349     name= NULL;
350     save_x= win_x; save_y= win_y;
351     save_w= win_w; save_h= win_h;
352     initialize ();
353     XMoveResizeWindow (dpy, win, 0, 0,
354 		       gui->screen_width, gui->screen_height);
355     move_event   (0, 0);
356     resize_event (gui->screen_width, gui->screen_height);
357     set_visibility (true);
358     XSetInputFocus (dpy, win, PointerRoot, CurrentTime);
359   }
360   else {
361     set_visibility (false);
362     Window_to_window->reset (win);
363     nr_windows--;
364     XDestroyWindow (dpy, win);
365     win= save_win;
366     set_visibility (false);
367     Window_to_window->reset (win);
368     nr_windows--;
369     XDestroyWindow (dpy, win);
370     //FIXME: is this 'as_charp' a possible memory leak?
371     name= as_charp (old_name);
372     win_x= save_x; win_y= save_y;
373     win_w= save_w; win_h= save_h;
374     initialize ();
375     set_visibility (true);
376     XMoveResizeWindow (dpy, win, save_x, save_y, save_w, save_h);
377     resize_event (save_w, save_h);
378     move_event   (save_x, save_y);
379   }
380   set_name (old_name);
381   full_screen_flag= flag;
382 }
383 
384 void
move_event(int x,int y)385 x_window_rep::move_event (int x, int y) {
386   bool flag= (win_x!=x) || (win_y!=y);
387   win_x= x; win_y= y;
388   if (flag) {
389     XWindowAttributes attrs;
390     XGetWindowAttributes (dpy, win, &attrs);
391     int border_x= attrs.x, border_y= attrs.y;
392     notify_position (w, win_x*PIXEL, win_y*PIXEL);
393     if (border_x >= 0 && border_x <= 5 && border_y >= 0 && border_y <= 30) {
394       //cout << "Move to " << x-border_x << ", " << y-border_y << "\n";
395       notify_window_move (orig_name, (x-border_x)*PIXEL, (border_y-y)*PIXEL);
396     }
397   }
398 }
399 
400 void
resize_event(int ww,int hh)401 x_window_rep::resize_event (int ww, int hh) {
402   bool flag= (win_w!=ww) || (win_h!=hh);
403   win_w= ww; win_h= hh;
404   if (flag) {
405     notify_size (w, win_w*PIXEL, win_h*PIXEL);
406     notify_window_resize (orig_name, ww*PIXEL, hh*PIXEL);
407   }
408 }
409 
410 void
destroy_event()411 x_window_rep::destroy_event () {
412   notify_window_destroy (orig_name);
413   send_destroy (w);
414 }
415 
416 /******************************************************************************
417 * Event handling
418 ******************************************************************************/
419 
420 void
invalidate_event(int x1,int y1,int x2,int y2)421 x_window_rep::invalidate_event (int x1, int y1, int x2, int y2) {
422   invalid_regions= invalid_regions | rectangles (rectangle (x1, y1, x2, y2));
423 }
424 
425 void
key_event(string key)426 x_window_rep::key_event (string key) {
427   send_keyboard (kbd_focus, key);
428 }
429 
430 void
focus_in_event()431 x_window_rep::focus_in_event () {
432   if (ic_ok) XSetICFocus (ic);
433   has_focus= true;
434   notify_keyboard_focus (kbd_focus, true);
435   gui->focussed_window (win);
436 }
437 
438 void
focus_out_event()439 x_window_rep::focus_out_event () {
440   if (ic_ok) XUnsetICFocus (ic);
441   has_focus= false;
442   notify_keyboard_focus (kbd_focus, false);
443 }
444 
445 void
mouse_event(string ev,int x,int y,time_t t)446 x_window_rep::mouse_event (string ev, int x, int y, time_t t) {
447   if (is_nil (gui->grab_ptr) || (get_x_window (gui->grab_ptr->item) == NULL)) {
448     ren->set_origin (0, 0);
449     ren->encode (x, y);
450     send_mouse (w, ev, x, y, gui->state, t);
451   }
452   else {
453     x_window grab_win= get_x_window (gui->grab_ptr->item);
454     if (this != grab_win) {
455       x += win_x - grab_win->win_x;
456       y += win_y - grab_win->win_y;
457       // return;
458     }
459     ren->set_origin (0, 0);
460     ren->encode (x, y);
461     send_mouse (gui->grab_ptr->item, ev, x, y, gui->state, t);
462   }
463 }
464 
465 void
repaint_invalid_regions()466 x_window_rep::repaint_invalid_regions () {
467   //if (!is_nil (invalid_regions)) cout << invalid_regions << "\n";
468   //else { cout << "."; cout.flush (); }
469   rectangles new_regions;
470   if (!is_nil (invalid_regions)) {
471     rectangle lub= least_upper_bound (invalid_regions);
472     if (area (lub) < 1.2 * area (invalid_regions))
473       invalid_regions= rectangles (lub);
474   }
475   while (!is_nil (invalid_regions)) {
476     ren->set_origin (0, 0);
477     rectangle r= copy (invalid_regions->item);
478     r= thicken (r, 1, 1);
479     ren->encode (r->x1, r->y1);
480     ren->encode (r->x2, r->y2);
481     ren->set_clipping (r->x1, r->y2, r->x2, r->y1);
482     send_repaint (w, ren, r->x1, r->y2, r->x2, r->y1);
483     if (gui_interrupted ())
484       new_regions= rectangles (invalid_regions->item, new_regions);
485     invalid_regions= invalid_regions->next;
486   }
487   invalid_regions= new_regions;
488 }
489 
490 void
set_keyboard_focus(widget wid,bool get_focus)491 x_window_rep::set_keyboard_focus (widget wid, bool get_focus) {
492   ASSERT (get_focus, "explicit loss of keyboard focus not yet implemented");
493   if (has_focus && (kbd_focus != wid.rep)) {
494     notify_keyboard_focus (kbd_focus, false);
495     notify_keyboard_focus (wid, true);
496   }
497   kbd_focus= wid.rep;
498 }
499 
500 bool
get_keyboard_focus(widget wid)501 x_window_rep::get_keyboard_focus (widget wid) {
502   return has_focus && kbd_focus == wid.rep;
503 }
504 
505 void
set_mouse_grab(widget wid,bool get_grab)506 x_window_rep::set_mouse_grab (widget wid, bool get_grab) {
507   if (get_grab) gui->obtain_mouse_grab (wid);
508   else gui->release_mouse_grab ();
509 }
510 
511 bool
get_mouse_grab(widget w)512 x_window_rep::get_mouse_grab (widget w) {
513   return gui->has_mouse_grab (w);
514 }
515 
516 void
set_mouse_pointer(widget wid,string name,string mask)517 x_window_rep::set_mouse_pointer (widget wid, string name, string mask) {
518   if (mask == "") gui->set_mouse_pointer (wid, name);
519   else gui->set_mouse_pointer (wid, name, mask);
520 }
521 
522 /******************************************************************************
523 * Delayed messages
524 ******************************************************************************/
525 
message_rep(widget wid2,string s2,time_t t2)526 message_rep::message_rep (widget wid2, string s2, time_t t2):
527   wid (wid2), s (s2), t (t2) {}
message(widget wid,string s,time_t t)528 message::message (widget wid, string s, time_t t):
529   rep (tm_new<message_rep> (wid, s, t)) {}
530 
531 tm_ostream&
operator <<(tm_ostream & out,message m)532 operator << (tm_ostream& out, message m) {
533   return out << "message " << m->s << " to " << m->wid
534 	     << "at time " << m->t << "\n";
535 }
536 
537 static list<message>
insert_message(list<message> l,widget wid,string s,time_t cur,time_t t)538 insert_message (list<message> l, widget wid, string s, time_t cur, time_t t) {
539   if (is_nil (l)) return list<message> (message (wid, s, t));
540   time_t ref= l->item->t;
541   if ((t-cur) <= (ref-cur)) return list<message> (message (wid, s, t), l);
542   return list<message> (l->item, insert_message (l->next, wid, s, cur, t));
543 }
544 
545 void
delayed_message(widget wid,string s,time_t delay)546 x_window_rep::delayed_message (widget wid, string s, time_t delay) {
547   time_t ct= texmacs_time ();
548   the_gui->messages= insert_message (the_gui->messages, wid, s, ct, ct+ delay);
549 }
550 
551 /******************************************************************************
552 * Routines concerning regions in a window
553 ******************************************************************************/
554 
555 void
translate(SI x1,SI y1,SI x2,SI y2,SI dx,SI dy)556 x_window_rep::translate (SI x1, SI y1, SI x2, SI y2, SI dx, SI dy) {
557   ren->set_origin(0,0);
558   begin_draw ();
559   ren->clip (x1, y1, x2, y2);
560 
561   SI X1= x1+ dx;
562   SI Y2= y2+ dy;
563   ren->decode (x1, y1);
564   ren->decode (x2, y2);
565   ren->decode (X1, Y2);
566   dx= X1- x1;
567   dy= Y2- y2;
568 
569   XEvent report;
570   while (XCheckWindowEvent (dpy, win, ExposureMask, &report))
571     gui->process_event (this, &report);
572 
573   rectangles region (rectangle (x1, y2, x2, y1));
574   rectangles invalid_intern= invalid_regions & region;
575   rectangles invalid_extern= invalid_regions - invalid_intern;
576   invalid_intern = ::translate (invalid_intern, dx, dy) & region;
577   invalid_regions= invalid_extern | invalid_intern;
578 
579   rectangles extra= thicken (region - ::translate (region, dx, dy), 1, 1);
580   invalid_regions= invalid_regions | extra;
581 
582   if (x1<x2 && y2<y1)
583     XCopyArea (dpy, win, win, gc, x1, y2, x2-x1, y1-y2, X1, Y2);
584 
585 
586   ren->unclip ();
587   end_draw ();
588 }
589 
590 void
invalidate(SI x1,SI y1,SI x2,SI y2)591 x_window_rep::invalidate (SI x1, SI y1, SI x2, SI y2) {
592   ren->outer_round (x1, y1, x2, y2);
593   ren->decode (x1, y1);
594   ren->decode (x2, y2);
595   invalidate_event (x1, y2, x2, y1);
596 }
597 
598 bool
is_invalid()599 x_window_rep::is_invalid () {
600   return ! is_nil (invalid_regions);
601 }
602 
603 /******************************************************************************
604 * Interface
605 ******************************************************************************/
606 
607 window
popup_window(widget w,string name,SI min_w,SI min_h,SI def_w,SI def_h,SI max_w,SI max_h)608 popup_window (widget w, string name, SI min_w, SI min_h,
609 	      SI def_w, SI def_h, SI max_w, SI max_h)
610 {
611   window win= tm_new<x_window_rep> (w, the_gui, (char*) NULL,
612 				    min_w, min_h, def_w, def_h, max_w, max_h);
613   return win;
614 }
615 
616 window
plain_window(widget w,string name,SI min_w,SI min_h,SI def_w,SI def_h,SI max_w,SI max_h)617 plain_window (widget w, string name, SI min_w, SI min_h,
618 	      SI def_w, SI def_h, SI max_w, SI max_h)
619 {
620   c_string _name (name);
621   window win= tm_new<x_window_rep> (w, the_gui, _name,
622 				    min_w, min_h, def_w, def_h, max_w, max_h);
623   return win;
624 }
625