]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/frame.cpp
zlib objects linked together with wxBase
[wxWidgets.git] / src / gtk1 / frame.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: frame.cpp
3// Purpose:
4// Author: Robert Roebling
a81258be 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling
19717c50 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
7c0ea335
VZ
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
c801d85f 18#ifdef __GNUG__
fe4e9e6c 19 #pragma implementation "frame.h"
c801d85f
KB
20#endif
21
22#include "wx/frame.h"
23#include "wx/dialog.h"
24#include "wx/control.h"
25#include "wx/app.h"
cf4219e7 26#include "wx/menu.h"
dcf924a3 27#if wxUSE_TOOLBAR
7c0ea335 28 #include "wx/toolbar.h"
dcf924a3
RR
29#endif
30#if wxUSE_STATUSBAR
7c0ea335 31 #include "wx/statusbr.h"
dcf924a3 32#endif
362c6693 33#include "wx/dcclient.h"
83624f79 34
55703c91
RR
35#include <glib.h>
36#include <gdk/gdk.h>
37#include <gtk/gtk.h>
38#include <gdk/gdkkeysyms.h>
39#include <gdk/gdkx.h>
40
c801d85f
KB
41#include "wx/gtk/win_gtk.h"
42
7c0ea335 43// ----------------------------------------------------------------------------
2f2aa628 44// constants
7c0ea335 45// ----------------------------------------------------------------------------
2f2aa628 46
907789a0 47const int wxMENU_HEIGHT = 27;
c67daf87 48const int wxSTATUS_HEIGHT = 25;
41ca191f 49const int wxPLACE_HOLDER = 0;
c801d85f 50
7c0ea335 51// ----------------------------------------------------------------------------
acfd422a 52// idle system
7c0ea335 53// ----------------------------------------------------------------------------
acfd422a
RR
54
55extern void wxapp_install_idle_handler();
56extern bool g_isIdle;
2d68e1b4 57extern int g_openDialogs;
acfd422a 58
7c0ea335
VZ
59// ----------------------------------------------------------------------------
60// event tables
61// ----------------------------------------------------------------------------
62
63IMPLEMENT_DYNAMIC_CLASS(wxFrame,wxWindow)
64
65// ----------------------------------------------------------------------------
2f2aa628 66// data
7c0ea335 67// ----------------------------------------------------------------------------
2f2aa628 68
c801d85f
KB
69extern wxList wxPendingDelete;
70
7c0ea335 71// ----------------------------------------------------------------------------
2e563988 72// debug
7c0ea335 73// ----------------------------------------------------------------------------
2e563988
RR
74
75#ifdef __WXDEBUG__
76
77extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window );
78
79#endif
80
7c0ea335
VZ
81// ============================================================================
82// implementation
83// ============================================================================
84
85// ----------------------------------------------------------------------------
86// GTK callbacks
87// ----------------------------------------------------------------------------
88
69ffe1d2
RR
89//-----------------------------------------------------------------------------
90// "focus" from m_window
91//-----------------------------------------------------------------------------
92
93static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
94{
95 if (g_isIdle)
96 wxapp_install_idle_handler();
97
98 // This disables GTK's tab traversal
99 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus" );
100 return TRUE;
101}
102
c801d85f 103//-----------------------------------------------------------------------------
2f2aa628 104// "size_allocate"
c801d85f 105//-----------------------------------------------------------------------------
c801d85f 106
2f2aa628 107static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxFrame *win )
ed7a557b 108{
88ac883a 109 if (g_isIdle)
121a3581 110 wxapp_install_idle_handler();
acfd422a 111
54517652
RR
112 if (!win->m_hasVMT)
113 return;
8bbe427f 114
121a3581
RR
115 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
116 {
54517652
RR
117/*
118 wxPrintf( "OnSize from " );
119 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
120 wxPrintf( win->GetClassInfo()->GetClassName() );
121 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
122 (int)alloc->y,
123 (int)alloc->width,
124 (int)alloc->height );
125*/
7beba2fc 126
121a3581
RR
127 win->m_width = alloc->width;
128 win->m_height = alloc->height;
8cb9f0d0 129 win->m_queuedFullRedraw = TRUE;
5b8a521e 130 win->GtkUpdateSize();
121a3581 131 }
362c6693 132}
c801d85f
KB
133
134//-----------------------------------------------------------------------------
2f2aa628
RR
135// "delete_event"
136//-----------------------------------------------------------------------------
c801d85f 137
2f2aa628 138static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxFrame *win )
ed7a557b 139{
88ac883a 140 if (g_isIdle)
121a3581 141 wxapp_install_idle_handler();
ed7a557b 142
a56fcaaf 143 if ((g_openDialogs == 0) && (win->IsEnabled()))
2d68e1b4 144 win->Close();
c801d85f 145
fb1585ae 146 return TRUE;
362c6693 147}
c801d85f 148
16bcc879
RR
149//-----------------------------------------------------------------------------
150// "child_attached" of menu bar
151//-----------------------------------------------------------------------------
152
153static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
154{
a2053b27 155 if (!win->m_hasVMT) return;
88ac883a 156
16bcc879 157 win->m_menuBarDetached = FALSE;
5b8a521e 158 win->GtkUpdateSize();
16bcc879
RR
159}
160
161//-----------------------------------------------------------------------------
162// "child_detached" of menu bar
163//-----------------------------------------------------------------------------
164
165static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
166{
a2053b27 167 if (!win->m_hasVMT) return;
88ac883a 168
16bcc879 169 win->m_menuBarDetached = TRUE;
5b8a521e 170 win->GtkUpdateSize();
16bcc879
RR
171}
172
88ac883a 173#if wxUSE_TOOLBAR
16bcc879
RR
174//-----------------------------------------------------------------------------
175// "child_attached" of tool bar
176//-----------------------------------------------------------------------------
177
178static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
179{
a2053b27 180 if (!win->m_hasVMT) return;
88ac883a 181
16bcc879 182 win->m_toolBarDetached = FALSE;
88ac883a 183
5b8a521e 184 win->GtkUpdateSize();
16bcc879
RR
185}
186
187//-----------------------------------------------------------------------------
188// "child_detached" of tool bar
189//-----------------------------------------------------------------------------
190
5e0201ea 191static void gtk_toolbar_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
16bcc879 192{
88ac883a 193 if (g_isIdle)
801aa178 194 wxapp_install_idle_handler();
acfd422a 195
a2053b27 196 if (!win->m_hasVMT) return;
88ac883a 197
16bcc879 198 win->m_toolBarDetached = TRUE;
5b8a521e 199 win->GtkUpdateSize();
16bcc879 200}
88ac883a 201#endif // wxUSE_TOOLBAR
16bcc879 202
47908e25 203//-----------------------------------------------------------------------------
2f2aa628
RR
204// "configure_event"
205//-----------------------------------------------------------------------------
47908e25 206
7beba2fc 207static gint
2d68e1b4 208#if (GTK_MINOR_VERSION > 0)
c693edf3
RR
209gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxFrame *win )
210#else
211gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *event, wxFrame *win )
212#endif
47908e25 213{
7beba2fc 214 if (g_isIdle)
121a3581 215 wxapp_install_idle_handler();
acfd422a 216
7c0ea335 217 if (!win->m_hasVMT)
2d68e1b4 218 return FALSE;
81855216 219
2d68e1b4 220#if (GTK_MINOR_VERSION > 0)
dfc3d7e0
RR
221 int x = 0;
222 int y = 0;
223 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
dfc3d7e0
RR
224 win->m_x = x;
225 win->m_y = y;
c693edf3
RR
226#else
227 win->m_x = event->x;
228 win->m_y = event->y;
229#endif
8bbe427f 230
a2053b27 231 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
36b3b54a
RR
232 mevent.SetEventObject( win );
233 win->GetEventHandler()->ProcessEvent( mevent );
234
fb1585ae 235 return FALSE;
362c6693 236}
47908e25 237
2b07d713
RR
238//-----------------------------------------------------------------------------
239// "realize" from m_widget
240//-----------------------------------------------------------------------------
241
88ac883a 242/* we cannot MWM hints and icons before the widget has been realized,
2b07d713
RR
243 so we do this directly after realization */
244
88ac883a 245static gint
2e5c594e 246gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win )
2b07d713 247{
88ac883a 248 if (g_isIdle)
121a3581 249 wxapp_install_idle_handler();
acfd422a 250
80629c8b 251 if ((win->m_miniEdge > 0) || (win->HasFlag(wxSIMPLE_BORDER)))
15b24b14 252 {
80629c8b 253 /* This is a mini-frame or a borderless frame. */
81855216
RR
254 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)0 );
255 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)0 );
15b24b14 256 }
81855216 257 else
aa64626e 258 {
81855216
RR
259 /* All this is for Motif Window Manager "hints" and is supposed to be
260 recognized by other WM as well. Not tested. */
261 long decor = (long) GDK_DECOR_BORDER;
262 long func = (long) GDK_FUNC_MOVE;
263
264 if ((win->GetWindowStyle() & wxCAPTION) != 0)
265 decor |= GDK_DECOR_TITLE;
266 if ((win->GetWindowStyle() & wxSYSTEM_MENU) != 0)
267 {
268 decor |= GDK_DECOR_MENU;
269 func |= GDK_FUNC_CLOSE;
270 }
271 if ((win->GetWindowStyle() & wxMINIMIZE_BOX) != 0)
272 {
273 func |= GDK_FUNC_MINIMIZE;
274 decor |= GDK_DECOR_MINIMIZE;
275 }
276 if ((win->GetWindowStyle() & wxMAXIMIZE_BOX) != 0)
277 {
278 func |= GDK_FUNC_MAXIMIZE;
279 decor |= GDK_DECOR_MAXIMIZE;
280 }
281 if ((win->GetWindowStyle() & wxRESIZE_BORDER) != 0)
282 {
283 func |= GDK_FUNC_RESIZE;
284 decor |= GDK_DECOR_RESIZEH;
285 }
286
287 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor);
288 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func);
aa64626e
KB
289 }
290
2b07d713 291 /* GTK's shrinking/growing policy */
f03fc89f 292 if ((win->GetWindowStyle() & wxRESIZE_BORDER) == 0)
a2053b27 293 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
2b07d713 294 else
a2053b27 295 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
88ac883a 296
738f9e5a 297 /* set size hints */
8487f887 298 gint flag = 0; // GDK_HINT_POS;
738f9e5a
RR
299 if ((win->GetMinWidth() != -1) || (win->GetMinHeight() != -1)) flag |= GDK_HINT_MIN_SIZE;
300 if ((win->GetMaxWidth() != -1) || (win->GetMaxHeight() != -1)) flag |= GDK_HINT_MAX_SIZE;
301 if (flag)
302 {
7beba2fc
VZ
303 gdk_window_set_hints( win->m_widget->window,
304 win->m_x, win->m_y,
305 win->GetMinWidth(), win->GetMinHeight(),
306 win->GetMaxWidth(), win->GetMaxHeight(),
307 flag );
738f9e5a 308 }
7beba2fc 309
58dea4b0 310 /* reset the icon */
7c0ea335
VZ
311 wxIcon iconOld = win->GetIcon();
312 if ( iconOld != wxNullIcon )
58dea4b0 313 {
7c0ea335
VZ
314 wxIcon icon( iconOld );
315 win->SetIcon( wxNullIcon );
f03fc89f 316 win->SetIcon( icon );
58dea4b0 317 }
88ac883a 318
2e563988
RR
319 /* we set the focus to the child that accepts the focus. this
320 doesn't really have to be done in "realize" but why not? */
f03fc89f 321 wxWindowList::Node *node = win->GetChildren().GetFirst();
2e563988
RR
322 while (node)
323 {
f03fc89f
VZ
324 wxWindow *child = node->GetData();
325 if (child->AcceptsFocus())
326 {
327 child->SetFocus();
328 break;
329 }
88ac883a 330
f03fc89f 331 node = node->GetNext();
2e563988 332 }
88ac883a 333
227e5e99
RR
334 return FALSE;
335}
88ac883a 336
7c0ea335
VZ
337// ----------------------------------------------------------------------------
338// wxFrame itself
339// ----------------------------------------------------------------------------
340
f362b96d
RR
341//-----------------------------------------------------------------------------
342// InsertChild for wxFrame
343//-----------------------------------------------------------------------------
344
345/* Callback for wxFrame. This very strange beast has to be used because
346 * C++ has no virtual methods in a constructor. We have to emulate a
347 * virtual function here as wxWindows requires different ways to insert
348 * a child in container classes. */
349
6bc8a1c8 350static void wxInsertChildInFrame( wxFrame* parent, wxWindow* child )
f362b96d 351{
5fd11f09 352 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
7beba2fc 353
6bc8a1c8 354 if (!parent->m_insertInClientArea)
f362b96d
RR
355 {
356 /* these are outside the client area */
f03fc89f 357 wxFrame* frame = (wxFrame*) parent;
da048e3d 358 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
a2053b27
RR
359 GTK_WIDGET(child->m_widget),
360 child->m_x,
361 child->m_y,
362 child->m_width,
363 child->m_height );
88ac883a 364
caf51f95 365#if wxUSE_TOOLBAR_NATIVE
f03fc89f
VZ
366 /* we connect to these events for recalculating the client area
367 space when the toolbar is floating */
368 if (wxIS_KIND_OF(child,wxToolBar))
369 {
370 wxToolBar *toolBar = (wxToolBar*) child;
371 if (toolBar->GetWindowStyle() & wxTB_DOCKABLE)
372 {
a2053b27 373 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_attached",
41ca191f 374 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback), (gpointer)parent );
88ac883a 375
a2053b27 376 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_detached",
41ca191f 377 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback), (gpointer)parent );
f03fc89f
VZ
378 }
379 }
88ac883a 380#endif // wxUSE_TOOLBAR
f362b96d
RR
381 }
382 else
383 {
384 /* these are inside the client area */
da048e3d 385 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
a2053b27
RR
386 GTK_WIDGET(child->m_widget),
387 child->m_x,
388 child->m_y,
389 child->m_width,
390 child->m_height );
f362b96d
RR
391 }
392
f362b96d 393 /* resize on OnInternalIdle */
5b8a521e 394 parent->GtkUpdateSize();
f362b96d
RR
395}
396
7c0ea335
VZ
397// ----------------------------------------------------------------------------
398// wxFrame creation
399// ----------------------------------------------------------------------------
c801d85f 400
ddb6bc71 401void wxFrame::Init()
c801d85f 402{
fb1585ae 403 m_sizeSet = FALSE;
b2b3ccc5
RR
404 m_miniEdge = 0;
405 m_miniTitle = 0;
ab2b3dd4 406 m_mainWidget = (GtkWidget*) NULL;
16bcc879
RR
407 m_menuBarDetached = FALSE;
408 m_toolBarDetached = FALSE;
6bc8a1c8 409 m_insertInClientArea = TRUE;
8cb9f0d0 410 m_isFrame = FALSE;
362c6693 411}
c801d85f 412
7c0ea335
VZ
413bool wxFrame::Create( wxWindow *parent,
414 wxWindowID id,
415 const wxString &title,
416 const wxPoint &pos,
417 const wxSize &size,
418 long style,
419 const wxString &name )
c801d85f 420{
a802c3a1 421 wxTopLevelWindows.Append( this );
8bbe427f 422
fb1585ae 423 m_needParent = FALSE;
8cb9f0d0 424 m_isFrame = TRUE;
ed7a557b 425
4dcaf11a
RR
426 if (!PreCreation( parent, pos, size ) ||
427 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
428 {
223d09f6 429 wxFAIL_MSG( wxT("wxFrame creation failed") );
7beba2fc 430 return FALSE;
4dcaf11a 431 }
c801d85f 432
fb1585ae 433 m_title = title;
88ac883a 434
6bc8a1c8 435 m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame;
ed7a557b 436
faecf4cb 437 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
8bbe427f 438
fb1585ae 439 m_widget = gtk_window_new( win_type );
88ac883a 440
80629c8b
RR
441 if ((m_parent) && (HasFlag(wxFRAME_FLOAT_ON_PARENT)) && (GTK_IS_WINDOW(m_parent->m_widget)))
442 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
443
de1c750f
RR
444 if (!name.IsEmpty())
445 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
8bbe427f 446
2e563988 447#ifdef __WXDEBUG__
223d09f6 448 debug_focus_in( m_widget, wxT("wxFrame::m_widget"), name );
2e563988
RR
449#endif
450
ed9b9841 451 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
fb1585ae 452 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ed7a557b 453
fb1585ae
RR
454 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
455 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
ed7a557b 456
f362b96d 457 /* m_mainWidget holds the toolbar, the menubar and the client area */
da048e3d 458 m_mainWidget = gtk_pizza_new();
f362b96d
RR
459 gtk_widget_show( m_mainWidget );
460 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
461 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
88ac883a 462
2e563988 463#ifdef __WXDEBUG__
223d09f6 464 debug_focus_in( m_mainWidget, wxT("wxFrame::m_mainWidget"), name );
2e563988
RR
465#endif
466
f362b96d 467 /* m_wxwindow only represents the client area without toolbar and menubar */
da048e3d 468 m_wxwindow = gtk_pizza_new();
fb1585ae 469 gtk_widget_show( m_wxwindow );
f362b96d 470 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
88ac883a 471
2e563988 472#ifdef __WXDEBUG__
223d09f6 473 debug_focus_in( m_wxwindow, wxT("wxFrame::m_wxwindow"), name );
2e563988
RR
474#endif
475
476 /* we donm't allow the frame to get the focus as otherwise
477 the frame will grabit at arbitrary fcous changes. */
478 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
ed7a557b 479
de8113d9
RR
480 if (m_parent) m_parent->AddChild( this );
481
54517652
RR
482 /* the user resized the frame by dragging etc. */
483 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
484 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
485
de8113d9
RR
486 PostCreation();
487
15909a16
RR
488 if ((m_x != -1) || (m_y != -1))
489 gtk_widget_set_uposition( m_widget, m_x, m_y );
490 gtk_widget_set_usize( m_widget, m_width, m_height );
491
58dea4b0 492 /* we cannot set MWM hints and icons before the widget has
2b07d713
RR
493 been realized, so we do this directly after realization */
494 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
f03fc89f 495 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
88ac883a 496
ab2b3dd4 497 /* the only way to get the window size is to connect to this event */
fb1585ae
RR
498 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
499 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
8bbe427f 500
69ffe1d2
RR
501 /* disable native tab traversal */
502 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
503 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
504
fb1585ae 505 return TRUE;
362c6693 506}
c801d85f 507
19717c50 508wxFrame::~wxFrame()
c801d85f 509{
31c6b4fc 510 m_isBeingDeleted = TRUE;
88ac883a 511
7c0ea335 512 DeleteAllBars();
ed7a557b 513
fb1585ae 514 wxTopLevelWindows.DeleteObject( this );
2b854a32 515
0d2a2b60 516 if (wxTheApp->GetTopWindow() == this)
0d2a2b60 517 wxTheApp->SetTopWindow( (wxWindow*) NULL );
2b854a32 518
f59d80ca
RR
519 if ((wxTopLevelWindows.Number() == 0) &&
520 (wxTheApp->GetExitOnFrameDelete()))
521 {
0d2a2b60 522 wxTheApp->ExitMainLoop();
f59d80ca 523 }
362c6693 524}
ed7a557b 525
7c0ea335
VZ
526// ----------------------------------------------------------------------------
527// overridden wxWindow methods
528// ----------------------------------------------------------------------------
529
debe6624 530bool wxFrame::Show( bool show )
c801d85f 531{
223d09f6 532 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 533
35178437 534 if (show && !m_sizeSet)
fb1585ae 535 {
e27ce4e9
RR
536 /* by calling GtkOnSize here, we don't have to call
537 either after showing the frame, which would entail
f362b96d 538 much ugly flicker or from within the size_allocate
e27ce4e9 539 handler, because GTK 1.1.X forbids that. */
8bbe427f 540
35178437 541 GtkOnSize( m_x, m_y, m_width, m_height );
fb1585ae 542 }
8bbe427f 543
fb1585ae 544 return wxWindow::Show( show );
362c6693 545}
c801d85f 546
23efdd02
RR
547void wxFrame::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
548{
549 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrame") );
550}
551
bfc6fde4 552void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
903f689b 553{
223d09f6 554 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 555
ab2b3dd4 556 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
223d09f6 557 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
88ac883a 558
ab2b3dd4 559 /* avoid recursions */
7c0ea335
VZ
560 if (m_resizing)
561 return;
fb1585ae
RR
562 m_resizing = TRUE;
563
564 int old_x = m_x;
565 int old_y = m_y;
7beba2fc 566
fb1585ae
RR
567 int old_width = m_width;
568 int old_height = m_height;
8bbe427f 569
85ad5eb5 570 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
fb1585ae
RR
571 {
572 if (x != -1) m_x = x;
573 if (y != -1) m_y = y;
574 if (width != -1) m_width = width;
575 if (height != -1) m_height = height;
576 }
577 else
578 {
579 m_x = x;
580 m_y = y;
581 m_width = width;
582 m_height = height;
583 }
584
11e1c70d 585/*
fb1585ae
RR
586 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
587 {
588 if (width == -1) m_width = 80;
589 }
590
591 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
592 {
593 if (height == -1) m_height = 26;
594 }
11e1c70d 595*/
8bbe427f 596
fb1585ae
RR
597 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
598 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
0c77152e
RR
599 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
600 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
fb1585ae
RR
601
602 if ((m_x != -1) || (m_y != -1))
603 {
8bbe427f 604 if ((m_x != old_x) || (m_y != old_y))
0138c2de 605 {
8487f887 606 gtk_widget_set_uposition( m_widget, m_x, m_y );
0138c2de 607 }
fb1585ae 608 }
8bbe427f 609
fb1585ae
RR
610 if ((m_width != old_width) || (m_height != old_height))
611 {
15909a16
RR
612 gtk_widget_set_usize( m_widget, m_width, m_height );
613
ab2b3dd4 614 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
f03fc89f
VZ
615 done either directly before the frame is shown or in idle time
616 so that different calls to SetSize() don't lead to flicker. */
de8113d9 617 m_sizeSet = FALSE;
fb1585ae 618 }
8bbe427f 619
fb1585ae 620 m_resizing = FALSE;
903f689b
RR
621}
622
f9241296 623void wxFrame::DoGetClientSize( int *width, int *height ) const
c801d85f 624{
223d09f6 625 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 626
f9241296 627 wxWindow::DoGetClientSize( width, height );
fb1585ae 628 if (height)
46dc76ba 629 {
41ca191f
RR
630 /* menu bar */
631 if (m_frameMenuBar)
f03fc89f 632 {
88ac883a 633 if (!m_menuBarDetached)
f03fc89f
VZ
634 (*height) -= wxMENU_HEIGHT;
635 else
636 (*height) -= wxPLACE_HOLDER;
637 }
88ac883a 638
dcf924a3 639#if wxUSE_STATUSBAR
f03fc89f 640 /* status bar */
fb1585ae 641 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
93fa69f8 642#endif // wxUSE_STATUSBAR
88ac883a 643
dcf924a3 644#if wxUSE_TOOLBAR
f03fc89f 645 /* tool bar */
fb1585ae
RR
646 if (m_frameToolBar)
647 {
93fa69f8 648 if (m_toolBarDetached)
f03fc89f 649 {
93fa69f8 650 *height -= wxPLACE_HOLDER;
f03fc89f
VZ
651 }
652 else
93fa69f8
VZ
653 {
654 int x, y;
655 m_frameToolBar->GetSize( &x, &y );
656 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
657 {
658 *width -= x;
659 }
660 else
661 {
662 *height -= y;
663 }
664 }
fb1585ae 665 }
93fa69f8 666#endif // wxUSE_TOOLBAR
88ac883a 667
f03fc89f 668 /* mini edge */
93fa69f8 669 *height -= m_miniEdge*2 + m_miniTitle;
b2b3ccc5
RR
670 }
671 if (width)
672 {
93fa69f8 673 *width -= m_miniEdge*2;
46dc76ba 674 }
362c6693 675}
c801d85f 676
bfc6fde4 677void wxFrame::DoSetClientSize( int width, int height )
b593568e 678{
223d09f6 679 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 680
41ca191f
RR
681 /* menu bar */
682 if (m_frameMenuBar)
f03fc89f 683 {
88ac883a 684 if (!m_menuBarDetached)
f03fc89f
VZ
685 height += wxMENU_HEIGHT;
686 else
687 height += wxPLACE_HOLDER;
688 }
88ac883a 689
dcf924a3 690#if wxUSE_STATUSBAR
f03fc89f 691 /* status bar */
41ca191f 692 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
dcf924a3 693#endif
88ac883a 694
dcf924a3 695#if wxUSE_TOOLBAR
f03fc89f 696 /* tool bar */
41ca191f
RR
697 if (m_frameToolBar)
698 {
93fa69f8 699 if (m_toolBarDetached)
f03fc89f 700 {
93fa69f8 701 height += wxPLACE_HOLDER;
f03fc89f
VZ
702 }
703 else
93fa69f8
VZ
704 {
705 int x, y;
706 m_frameToolBar->GetSize( &x, &y );
707 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
708 {
709 width += x;
710 }
711 else
712 {
713 height += y;
714 }
715 }
41ca191f 716 }
dcf924a3 717#endif
88ac883a 718
3017f78d 719 DoSetSize( -1, -1, width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0 );
362c6693 720}
b593568e 721
7c0ea335
VZ
722void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
723 int width, int height )
c801d85f 724{
f5368809
RR
725 // due to a bug in gtk, x,y are always 0
726 // m_x = x;
727 // m_y = y;
728
ab2b3dd4 729 /* avoid recursions */
e52f60e6
RR
730 if (m_resizing) return;
731 m_resizing = TRUE;
8bbe427f 732
ab2b3dd4 733 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
223d09f6 734 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
88ac883a 735
f5368809
RR
736 m_width = width;
737 m_height = height;
7beba2fc 738
ab2b3dd4 739 /* space occupied by m_frameToolBar and m_frameMenuBar */
93fa69f8
VZ
740 int client_area_x_offset = 0,
741 client_area_y_offset = 0;
8bbe427f 742
ab2b3dd4
RR
743 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
744 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
745 set in wxFrame::Create so it is used to check what kind of frame we
746 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
747 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
748 importantly) m_mainWidget */
88ac883a 749
ab2b3dd4 750 if (m_mainWidget)
f5368809 751 {
ab2b3dd4
RR
752 /* check if size is in legal range */
753 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
754 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
755 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
756 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
757
758 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
759 * menubar, the toolbar and the client area, which is represented by
760 * m_wxwindow.
761 * this hurts in the eye, but I don't want to call SetSize()
762 * because I don't want to call any non-native functions here. */
88ac883a 763
ab2b3dd4
RR
764 if (m_frameMenuBar)
765 {
766 int xx = m_miniEdge;
767 int yy = m_miniEdge + m_miniTitle;
768 int ww = m_width - 2*m_miniEdge;
41ca191f 769 int hh = wxMENU_HEIGHT;
f03fc89f 770 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
121a3581
RR
771 m_frameMenuBar->m_x = xx;
772 m_frameMenuBar->m_y = yy;
773 m_frameMenuBar->m_width = ww;
774 m_frameMenuBar->m_height = hh;
da048e3d 775 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
88ac883a 776 m_frameMenuBar->m_widget,
f03fc89f
VZ
777 xx, yy, ww, hh );
778 client_area_y_offset += hh;
ab2b3dd4 779 }
88ac883a 780
dcf924a3 781#if wxUSE_TOOLBAR
11e1c70d 782 if ((m_frameToolBar) &&
7beba2fc 783 (m_frameToolBar->m_widget->parent == m_mainWidget))
ab2b3dd4
RR
784 {
785 int xx = m_miniEdge;
786 int yy = m_miniEdge + m_miniTitle;
41ca191f 787 if (m_frameMenuBar)
f03fc89f 788 {
88ac883a
VZ
789 if (!m_menuBarDetached)
790 yy += wxMENU_HEIGHT;
791 else
f03fc89f
VZ
792 yy += wxPLACE_HOLDER;
793 }
93fa69f8 794
121a3581
RR
795 m_frameToolBar->m_x = xx;
796 m_frameToolBar->m_y = yy;
93fa69f8
VZ
797
798 /* don't change the toolbar's reported height/width */
799 int ww, hh;
800 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
801 {
802 ww = m_toolBarDetached ? wxPLACE_HOLDER
803 : m_frameToolBar->m_width;
804 hh = m_height - 2*m_miniEdge;
805
806 client_area_x_offset += ww;
807 }
808 else
809 {
810 ww = m_width - 2*m_miniEdge;
811 hh = m_toolBarDetached ? wxPLACE_HOLDER
812 : m_frameToolBar->m_height;
813
814 client_area_y_offset += hh;
815 }
816
da048e3d 817 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
88ac883a 818 m_frameToolBar->m_widget,
f03fc89f 819 xx, yy, ww, hh );
ab2b3dd4 820 }
93fa69f8 821#endif // wxUSE_TOOLBAR
88ac883a 822
93fa69f8 823 int client_x = client_area_x_offset + m_miniEdge;
f03fc89f 824 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
93fa69f8 825 int client_w = m_width - client_area_x_offset - 2*m_miniEdge;
f03fc89f 826 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
da048e3d 827 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
88ac883a 828 m_wxwindow,
f03fc89f 829 client_x, client_y, client_w, client_h );
32a95f9f
RR
830 }
831 else
832 {
833 /* if there is no m_mainWidget between m_widget and m_wxwindow there
f03fc89f 834 is no need to set the size or position of m_wxwindow. */
f5368809 835 }
88ac883a 836
dcf924a3 837#if wxUSE_STATUSBAR
f5368809
RR
838 if (m_frameStatusBar)
839 {
b2b3ccc5 840 int xx = 0 + m_miniEdge;
f362b96d 841 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
ac57418f
RR
842 int ww = m_width - 2*m_miniEdge;
843 int hh = wxSTATUS_HEIGHT;
121a3581
RR
844 m_frameStatusBar->m_x = xx;
845 m_frameStatusBar->m_y = yy;
846 m_frameStatusBar->m_width = ww;
847 m_frameStatusBar->m_height = hh;
da048e3d 848 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
7c0ea335
VZ
849 m_frameStatusBar->m_widget,
850 xx, yy, ww, hh );
b6fa52db 851 gtk_widget_draw( m_frameStatusBar->m_widget, (GdkRectangle*) NULL );
f5368809 852 }
dcf924a3 853#endif
8bbe427f 854
de8113d9 855 /* we actually set the size of a frame here and no-where else */
15909a16 856// gtk_widget_set_usize( m_widget, m_width, m_height );
88ac883a 857
54517652 858 m_sizeSet = TRUE;
7beba2fc 859
54517652 860 // send size event to frame
43a18898
RR
861 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
862 event.SetEventObject( this );
e52f60e6 863 GetEventHandler()->ProcessEvent( event );
8bbe427f 864
54517652 865 // send size event to status bar
5aa5e35a
RR
866 if (m_frameStatusBar)
867 {
a2053b27 868 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
5aa5e35a
RR
869 event2.SetEventObject( m_frameStatusBar );
870 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
871 }
884470b1 872
e52f60e6
RR
873 m_resizing = FALSE;
874}
875
ca26177c
RR
876void wxFrame::MakeModal( bool modal )
877{
878 if (modal)
ca26177c 879 gtk_grab_add( m_widget );
ca26177c 880 else
c25ccf85 881 gtk_grab_remove( m_widget );
ca26177c
RR
882}
883
9390a202 884void wxFrame::OnInternalIdle()
e52f60e6 885{
1b3667ab 886 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
54517652 887 {
e52f60e6 888 GtkOnSize( m_x, m_y, m_width, m_height );
7beba2fc
VZ
889
890 // we'll come back later
54517652
RR
891 if (g_isIdle)
892 wxapp_install_idle_handler();
7beba2fc 893 return;
54517652 894 }
88ac883a 895
082b2798 896 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
dcf924a3 897#if wxUSE_TOOLBAR
082b2798 898 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
dcf924a3
RR
899#endif
900#if wxUSE_STATUSBAR
082b2798 901 if (m_frameStatusBar) m_frameStatusBar->OnInternalIdle();
dcf924a3 902#endif
5e014a0c
RR
903
904 wxWindow::OnInternalIdle();
362c6693 905}
c801d85f 906
7c0ea335
VZ
907// ----------------------------------------------------------------------------
908// menu/tool/status bar stuff
909// ----------------------------------------------------------------------------
c801d85f 910
c801d85f
KB
911void wxFrame::SetMenuBar( wxMenuBar *menuBar )
912{
223d09f6
KB
913 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
914 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
8bbe427f 915
186baeb2
RR
916 if (menuBar == m_frameMenuBar)
917 return;
918
919 if (m_frameMenuBar)
920 {
921 m_frameMenuBar->UnsetInvokingWindow( this );
922
923 if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE)
924 {
925 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
926 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
927
928 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
929 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
930 }
931
932 gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
933 gtk_widget_ref( m_frameMenuBar->m_widget );
934 gtk_widget_unparent( m_frameMenuBar->m_widget );
935 }
936
f5368809 937 m_frameMenuBar = menuBar;
8bbe427f 938
f5368809 939 if (m_frameMenuBar)
30dea054 940 {
5bd9e519 941 m_frameMenuBar->SetInvokingWindow( this );
8bbe427f 942
186baeb2
RR
943 m_frameMenuBar->SetParent(this);
944 gtk_pizza_put( GTK_PIZZA(m_mainWidget),
88ac883a
VZ
945 m_frameMenuBar->m_widget,
946 m_frameMenuBar->m_x,
a2053b27
RR
947 m_frameMenuBar->m_y,
948 m_frameMenuBar->m_width,
949 m_frameMenuBar->m_height );
88ac883a 950
186baeb2
RR
951 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
952 {
953 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
954 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
7beba2fc 955
186baeb2
RR
956 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
957 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
f5368809 958 }
186baeb2
RR
959
960 m_frameMenuBar->Show( TRUE );
716b7364 961 }
8bbe427f 962
1e133b7d 963 /* resize window in OnInternalIdle */
5b077d48 964 m_sizeSet = FALSE;
362c6693 965}
c801d85f 966
88ac883a 967#if wxUSE_TOOLBAR
6bc8a1c8 968wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
46dc76ba 969{
223d09f6 970 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 971
6bc8a1c8 972 m_insertInClientArea = FALSE;
88ac883a 973
7c0ea335 974 m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name );
8bbe427f 975
7c0ea335
VZ
976 if (m_frameToolBar)
977 GetChildren().DeleteObject( m_frameToolBar );
88ac883a 978
6bc8a1c8 979 m_insertInClientArea = TRUE;
8bbe427f 980
5b077d48 981 m_sizeSet = FALSE;
8bbe427f 982
f5368809 983 return m_frameToolBar;
362c6693 984}
46dc76ba 985
7beba2fc
VZ
986void wxFrame::SetToolBar(wxToolBar *toolbar)
987{
7c0ea335
VZ
988 wxFrameBase::SetToolBar(toolbar);
989
307f16e8
RR
990 if (m_frameToolBar)
991 {
992 /* insert into toolbar area if not already there */
3017f78d
RR
993 if ((m_frameToolBar->m_widget->parent) &&
994 (m_frameToolBar->m_widget->parent != m_mainWidget))
307f16e8 995 {
3017f78d 996 GetChildren().DeleteObject( m_frameToolBar );
7beba2fc
VZ
997
998 gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
5b8a521e 999 GtkUpdateSize();
7beba2fc 1000 }
307f16e8
RR
1001 }
1002}
1003
88ac883a 1004#endif // wxUSE_TOOLBAR
46dc76ba 1005
88ac883a 1006#if wxUSE_STATUSBAR
8bbe427f 1007
7c0ea335
VZ
1008wxStatusBar* wxFrame::CreateStatusBar(int number,
1009 long style,
1010 wxWindowID id,
1011 const wxString& name)
c801d85f 1012{
223d09f6 1013 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 1014
7c0ea335
VZ
1015 // because it will change when toolbar is added
1016 m_sizeSet = FALSE;
c801d85f 1017
7c0ea335 1018 return wxFrameBase::CreateStatusBar( number, style, id, name );
362c6693
RR
1019}
1020
8febdd39
RR
1021void wxFrame::PositionStatusBar()
1022{
1023 if ( !m_frameStatusBar )
1024 return;
1025
1026 m_sizeSet = FALSE;
1027}
88ac883a 1028#endif // wxUSE_STATUSBAR
c801d85f 1029
7c0ea335
VZ
1030// ----------------------------------------------------------------------------
1031// frame title/icon
1032// ----------------------------------------------------------------------------
c801d85f 1033
c801d85f
KB
1034void wxFrame::SetTitle( const wxString &title )
1035{
223d09f6 1036 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 1037
f5368809 1038 m_title = title;
ed9b9841 1039 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
362c6693 1040}
c801d85f 1041
d355d3fe
RR
1042void wxFrame::SetIcon( const wxIcon &icon )
1043{
223d09f6 1044 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 1045
7c0ea335 1046 wxFrameBase::SetIcon(icon);
8bbe427f 1047
7c0ea335
VZ
1048 if ( !m_icon.Ok() )
1049 return;
1050
1051 if (!m_widget->window)
1052 return;
58dea4b0 1053
f5368809
RR
1054 wxMask *mask = icon.GetMask();
1055 GdkBitmap *bm = (GdkBitmap *) NULL;
1056 if (mask) bm = mask->GetBitmap();
8bbe427f 1057
f5368809 1058 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
d355d3fe 1059}
b2b3ccc5 1060
7c0ea335
VZ
1061// ----------------------------------------------------------------------------
1062// frame state: maximized/iconized/normal (TODO)
1063// ----------------------------------------------------------------------------
1064
7beba2fc 1065void wxFrame::Maximize(bool WXUNUSED(maximize))
cd25b18c
RR
1066{
1067}
1068
7c0ea335
VZ
1069bool wxFrame::IsMaximized() const
1070{
1071 return FALSE;
1072}
1073
7beba2fc 1074void wxFrame::Restore()
cd25b18c
RR
1075{
1076}
1077
7beba2fc
VZ
1078void wxFrame::Iconize( bool iconize )
1079{
cd25b18c
RR
1080 if (iconize)
1081 {
1082 XIconifyWindow( GDK_WINDOW_XDISPLAY( m_widget->window ),
7beba2fc
VZ
1083 GDK_WINDOW_XWINDOW( m_widget->window ),
1084 DefaultScreen( GDK_DISPLAY() ) );
cd25b18c
RR
1085 }
1086}
1087
7beba2fc
VZ
1088bool wxFrame::IsIconized() const
1089{
1090 return FALSE;
cd25b18c 1091}