Add member timestamp and cpuid to LttvTracesetPosition to improve the comparaison...
[lttv.git] / lttv / modules / gui / lttvwindow / lttvwindow / lttvwindow.c
CommitLineData
501e4e70 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 XangXiu Yang
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19/*! \file lttvwindow.c
20 * \brief API used by the graphical viewers to interact with their tab.
21 *
22 * Main window (gui module) is the place to contain and display viewers.
23 * Viewers (lttv plugins) interact with tab and main window through this API
24 * and events sent by gtk.
25 * This header file should be included in each graphic module.
26 * This library is used by graphical modules to interact with their tab and
27 * main window.
28 *
29 */
30
4e4d11b3 31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
501e4e70 35#include <ltt/ltt.h>
36#include <lttv/lttv.h>
37#include <lttv/state.h>
9a366873 38#include <lttv/traceset.h>
451aaf27 39#ifdef BABEL_CLEANUP
501e4e70 40#include <lttv/stats.h>
451aaf27 41#endif /* BABEL_CLEANUP */
501e4e70 42#include <lttvwindow/mainwindow.h>
9a366873 43#include <lttvwindow/mainwindow-private.h>
501e4e70 44#include <lttvwindow/lttvwindow.h>
45#include <lttvwindow/toolbar.h>
46#include <lttvwindow/menu.h>
47#include <lttvwindow/callbacks.h> // for execute_events_requests
48#include <lttvwindow/support.h>
49
501e4e70 50/**
51 * Internal function parts
52 */
53
54extern GSList * g_main_window_list;
55
f9240312 56__EXPORT gint lttvwindow_preempt_count = 0;
3c456a8a 57
b052368a 58/* set_time_window
59 *
60 * It updates the time window of the tab, then calls the updatetimewindow
61 * hooks of each viewer.
62 *
63 * This is called whenever the scrollbar value changes.
64 */
501e4e70 65
66void set_time_window(Tab *tab, const TimeWindow *time_window)
67{
68 LttvAttributeValue value;
69 LttvHooks * tmp;
8f318283 70 gboolean retval;
501e4e70 71
72 TimeWindowNotifyData time_window_notify_data;
73 TimeWindow old_time_window = tab->time_window;
74 time_window_notify_data.old_time_window = &old_time_window;
75 tab->time_window = *time_window;
76 time_window_notify_data.new_time_window =
77 &(tab->time_window);
78
8f318283
BP
79 retval= lttv_iattribute_find_by_path(tab->attributes,
80 "hooks/updatetimewindow", LTTV_POINTER, &value);
81 g_assert(retval);
501e4e70 82 tmp = (LttvHooks*)*(value.v_pointer);
b052368a 83 if(tmp != NULL) lttv_hooks_call(tmp, &time_window_notify_data);
501e4e70 84
b052368a 85 //gtk_multi_vpaned_set_adjust(tab->multi_vpaned, new_time_window, FALSE);
501e4e70 86
87}
88
db8bc917 89/* set_current_time
90 *
91 * It updates the current time of the tab, then calls the updatetimewindow
92 * hooks of each viewer.
93 *
94 * This is called whenever the current time value changes.
95 */
96
97void set_current_time(Tab *tab, const LttTime *current_time)
98{
99 LttvAttributeValue value;
100 LttvHooks * tmp;
8f318283 101 gboolean retval;
db8bc917 102
103 tab->current_time = *current_time;
104
8f318283
BP
105 retval= lttv_iattribute_find_by_path(tab->attributes,
106 "hooks/updatecurrenttime", LTTV_POINTER, &value);
107 g_assert(retval);
db8bc917 108 tmp = (LttvHooks*)*(value.v_pointer);
109 if(tmp != NULL) lttv_hooks_call(tmp, &tab->current_time);
110}
111
5290ec02 112/* set_current_position
113 *
114 * It updates the current time of the tab, then calls the updatetimewindow
115 * hooks of each viewer.
116 *
117 * This is called whenever the current time value changes.
118 */
119
451aaf27 120void set_current_position(Tab *tab, const LttvTracesetPosition *pos)
5290ec02 121{
122 LttvAttributeValue value;
123 LttvHooks * tmp;
8f318283 124 gboolean retval;
5290ec02 125
9a366873 126 tab->current_time = lttv_traceset_position_get_time(pos);
5290ec02 127
8f318283
BP
128 retval= lttv_iattribute_find_by_path(tab->attributes,
129 "hooks/updatecurrentposition", LTTV_POINTER, &value);
130 g_assert(retval);
5290ec02 131 tmp = (LttvHooks*)*(value.v_pointer);
8d8c5ea7
AM
132 if (tmp != NULL) {
133 lttv_hooks_call(tmp, (void *) pos);
134 }
5290ec02 135}
136
501e4e70 137void add_toolbar_constructor(MainWindow *mw, LttvToolbarClosure *toolbar_c)
138{
139 LttvIAttribute *attributes = mw->attributes;
140 LttvAttributeValue value;
141 LttvToolbars * instance_toolbar;
142 lttvwindow_viewer_constructor constructor;
143 GtkWidget * tool_menu_title_menu, *new_widget, *pixmap;
144 GdkPixbuf *pixbuf;
8f318283 145 gboolean retval;
501e4e70 146
8f318283
BP
147 retval= lttv_iattribute_find_by_path(attributes, "viewers/toolbar",
148 LTTV_POINTER, &value);
149 g_assert(retval);
501e4e70 150 if(*(value.v_pointer) == NULL)
151 *(value.v_pointer) = lttv_toolbars_new();
152 instance_toolbar = (LttvToolbars*)*(value.v_pointer);
153
154 constructor = toolbar_c->con;
155 tool_menu_title_menu = lookup_widget(mw->mwindow,"MToolbar1");
156 pixbuf = gdk_pixbuf_new_from_xpm_data((const char**)toolbar_c->pixmap);
157 pixmap = gtk_image_new_from_pixbuf(pixbuf);
158 new_widget =
159 gtk_toolbar_append_element (GTK_TOOLBAR (tool_menu_title_menu),
160 GTK_TOOLBAR_CHILD_BUTTON,
161 NULL,
162 "",
163 toolbar_c->tooltip, NULL,
164 pixmap, NULL, NULL);
165 gtk_label_set_use_underline(
166 GTK_LABEL (((GtkToolbarChild*) (
167 g_list_last (GTK_TOOLBAR
168 (tool_menu_title_menu)->children)->data))->label),
169 TRUE);
170 gtk_container_set_border_width (GTK_CONTAINER (new_widget), 1);
171 g_signal_connect ((gpointer) new_widget,
172 "clicked",
173 G_CALLBACK (insert_viewer_wrap),
174 constructor);
175 gtk_widget_show (new_widget);
176
177 lttv_toolbars_add(instance_toolbar, toolbar_c->con,
178 toolbar_c->tooltip,
179 toolbar_c->pixmap,
180 new_widget);
181
182}
183
184void add_menu_constructor(MainWindow *mw, LttvMenuClosure *menu_c)
185{
186 LttvIAttribute *attributes = mw->attributes;
187 LttvAttributeValue value;
188 LttvToolbars * instance_menu;
189 lttvwindow_viewer_constructor constructor;
190 GtkWidget * tool_menu_title_menu, *new_widget;
8f318283 191 gboolean retval;
501e4e70 192
8f318283
BP
193 retval= lttv_iattribute_find_by_path(attributes, "viewers/menu",
194 LTTV_POINTER, &value);
195 g_assert(retval);
501e4e70 196 if(*(value.v_pointer) == NULL)
197 *(value.v_pointer) = lttv_menus_new();
198 instance_menu = (LttvMenus*)*(value.v_pointer);
199
200
201 constructor = menu_c->con;
202 tool_menu_title_menu = lookup_widget(mw->mwindow,"ToolMenuTitle_menu");
203 new_widget =
204 gtk_menu_item_new_with_mnemonic (menu_c->menu_text);
205 gtk_container_add (GTK_CONTAINER (tool_menu_title_menu),
206 new_widget);
207 g_signal_connect ((gpointer) new_widget, "activate",
208 G_CALLBACK (insert_viewer_wrap),
209 constructor);
210 gtk_widget_show (new_widget);
211 lttv_menus_add(instance_menu, menu_c->con,
212 menu_c->menu_path,
213 menu_c->menu_text,
214 new_widget);
215}
216
217void remove_toolbar_constructor(MainWindow *mw, lttvwindow_viewer_constructor viewer_constructor)
218{
219 LttvIAttribute *attributes = mw->attributes;
220 LttvAttributeValue value;
221 LttvToolbars * instance_toolbar;
501e4e70 222 GtkWidget * tool_menu_title_menu, *widget;
8f318283 223 gboolean retval;
501e4e70 224
8f318283
BP
225 retval= lttv_iattribute_find_by_path(attributes, "viewers/toolbar",
226 LTTV_POINTER, &value);
227 g_assert(retval);
501e4e70 228 if(*(value.v_pointer) == NULL)
229 *(value.v_pointer) = lttv_toolbars_new();
230 instance_toolbar = (LttvToolbars*)*(value.v_pointer);
231
232 tool_menu_title_menu = lookup_widget(mw->mwindow,"MToolbar1");
233 widget = lttv_menus_remove(instance_toolbar, viewer_constructor);
234 gtk_container_remove (GTK_CONTAINER (tool_menu_title_menu),
235 widget);
236}
237
238
239void remove_menu_constructor(MainWindow *mw, lttvwindow_viewer_constructor viewer_constructor)
240{
241 LttvIAttribute *attributes = mw->attributes;
242 LttvAttributeValue value;
243 LttvMenus * instance_menu;
501e4e70 244 GtkWidget * tool_menu_title_menu, *widget;
8f318283 245 gboolean retval;
501e4e70 246
8f318283
BP
247 retval= lttv_iattribute_find_by_path(attributes, "viewers/menu",
248 LTTV_POINTER, &value);
249 g_assert(retval);
501e4e70 250 if(*(value.v_pointer) == NULL)
251 *(value.v_pointer) = lttv_menus_new();
252 instance_menu = (LttvMenus*)*(value.v_pointer);
253
254 widget = lttv_menus_remove(instance_menu, viewer_constructor);
255 tool_menu_title_menu = lookup_widget(mw->mwindow,"ToolMenuTitle_menu");
256 gtk_container_remove (GTK_CONTAINER (tool_menu_title_menu), widget);
257}
258
259
260/**
261 * API parts
262 */
263
264
265/**
266 * Function to register a view constructor so that main window can generate
267 * a menu item and a toolbar item for the viewer in order to generate a new
268 * instance easily. A menu entry and toolbar item will be added to each main
269 * window.
270 *
271 * It should be called by init function of the module.
272 *
e025a729 273 * @param name name of the viewer
501e4e70 274 * @param menu_path path of the menu item.
275 * @param menu_text text of the menu item.
276 * @param pixmap Image shown on the toolbar item.
277 * @param tooltip tooltip of the toolbar item.
278 * @param view_constructor constructor of the viewer.
279 */
280
f9240312 281__EXPORT void lttvwindow_register_constructor
e025a729 282 (char * name,
283 char * menu_path,
501e4e70 284 char * menu_text,
285 char ** pixmap,
286 char * tooltip,
287 lttvwindow_viewer_constructor view_constructor)
288{
289 LttvIAttribute *attributes_global = LTTV_IATTRIBUTE(lttv_global_attributes());
290 LttvToolbars * toolbar;
291 LttvMenus * menu;
292 LttvToolbarClosure toolbar_c;
293 LttvMenuClosure menu_c;
294 LttvAttributeValue value;
8f318283 295 gboolean retval;
501e4e70 296
e025a729 297 if(view_constructor == NULL) return;
298
501e4e70 299 if(pixmap != NULL) {
8f318283
BP
300 retval= lttv_iattribute_find_by_path(attributes_global, "viewers/toolbar",
301 LTTV_POINTER, &value);
302 g_assert(retval);
501e4e70 303 toolbar = (LttvToolbars*)*(value.v_pointer);
304
305 if(toolbar == NULL) {
306 toolbar = lttv_toolbars_new();
307 *(value.v_pointer) = toolbar;
308 }
309 toolbar_c = lttv_toolbars_add(toolbar, view_constructor, tooltip, pixmap,
310 NULL);
311
312 g_slist_foreach(g_main_window_list,
313 (gpointer)add_toolbar_constructor,
314 &toolbar_c);
315 }
316
317 if(menu_path != NULL) {
8f318283
BP
318 retval= lttv_iattribute_find_by_path(attributes_global, "viewers/menu",
319 LTTV_POINTER, &value);
320 g_assert(retval);
501e4e70 321 menu = (LttvMenus*)*(value.v_pointer);
322
323 if(menu == NULL) {
324 menu = lttv_menus_new();
325 *(value.v_pointer) = menu;
326 }
327 menu_c = lttv_menus_add(menu, view_constructor, menu_path, menu_text,NULL);
328
329 g_slist_foreach(g_main_window_list,
330 (gpointer)add_menu_constructor,
331 &menu_c);
332 }
e025a729 333 {
334 LttvAttribute *attribute;
96c9eb79 335 gboolean result;
336
337 attribute = LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
338 LTTV_IATTRIBUTE(attributes_global),
339 LTTV_VIEWER_CONSTRUCTORS));
340 g_assert(attribute);
e025a729 341
96c9eb79 342 result = lttv_iattribute_find_by_path(LTTV_IATTRIBUTE(attribute),
343 name, LTTV_POINTER, &value);
344 g_assert(result);
e025a729 345
346 *(value.v_pointer) = view_constructor;
347
348 }
501e4e70 349}
350
351
352/**
353 * Function to unregister the viewer's constructor, release the space
354 * occupied by menu_path, menu_text, pixmap, tooltip and constructor of the
355 * viewer.
356 *
357 * It will be called when a module is unloaded.
358 *
359 * @param view_constructor constructor of the viewer.
360 */
361
362
f9240312 363__EXPORT void lttvwindow_unregister_constructor
501e4e70 364 (lttvwindow_viewer_constructor view_constructor)
365{
366 LttvIAttribute *attributes_global = LTTV_IATTRIBUTE(lttv_global_attributes());
367 LttvToolbars * toolbar;
368 LttvMenus * menu;
369 LttvAttributeValue value;
8f318283
BP
370 gboolean is_named;
371 gboolean retval;
501e4e70 372
8f318283
BP
373 retval= lttv_iattribute_find_by_path(attributes_global, "viewers/toolbar",
374 LTTV_POINTER, &value);
375 g_assert(retval);
501e4e70 376 toolbar = (LttvToolbars*)*(value.v_pointer);
377
378 if(toolbar != NULL) {
379 g_slist_foreach(g_main_window_list,
380 (gpointer)remove_toolbar_constructor,
381 view_constructor);
382 lttv_toolbars_remove(toolbar, view_constructor);
383 }
384
8f318283
BP
385 retval= lttv_iattribute_find_by_path(attributes_global, "viewers/menu",
386 LTTV_POINTER, &value);
387 g_assert(retval);
501e4e70 388 menu = (LttvMenus*)*(value.v_pointer);
389
390 if(menu != NULL) {
391 g_slist_foreach(g_main_window_list,
392 (gpointer)remove_menu_constructor,
393 view_constructor);
394 lttv_menus_remove(menu, view_constructor);
395 }
e025a729 396
397 {
398 LttvAttribute *attribute;
96c9eb79 399 attribute = LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
400 LTTV_IATTRIBUTE(attributes_global),
401 LTTV_VIEWER_CONSTRUCTORS));
402 g_assert(attribute);
e025a729 403
404 guint num = lttv_iattribute_get_number(LTTV_IATTRIBUTE(attribute));
405 guint i;
406 LttvAttributeName name;
407 LttvAttributeValue value;
408 LttvAttributeType type;
409
410 for(i=0;i<num;i++) {
c0cb4d12 411 type = lttv_iattribute_get(LTTV_IATTRIBUTE(attribute), i, &name, &value,
412 &is_named);
e025a729 413 g_assert(type == LTTV_POINTER);
414 if(*(value.v_pointer) == view_constructor) {
415 lttv_iattribute_remove(LTTV_IATTRIBUTE(attribute), i);
416 break;
417 }
418 }
419 }
501e4e70 420}
421
422
423/**
424 * Function to register a hook function for a viewer to set/update its
425 * time interval.
426 * @param tab viewer's tab
427 * @param hook hook function of the viewer.
428 * @param hook_data hook data associated with the hook function.
429 */
f9240312 430__EXPORT void lttvwindow_register_time_window_notify(Tab *tab,
501e4e70 431 LttvHook hook, gpointer hook_data)
432{
433 LttvAttributeValue value;
434 LttvHooks * tmp;
8f318283
BP
435 gboolean retval;
436
437 retval= lttv_iattribute_find_by_path(tab->attributes,
438 "hooks/updatetimewindow", LTTV_POINTER, &value);
439 g_assert(retval);
501e4e70 440 tmp = (LttvHooks*)*(value.v_pointer);
441 if(tmp == NULL){
442 tmp = lttv_hooks_new();
443 *(value.v_pointer) = tmp;
444 }
445 lttv_hooks_add(tmp, hook,hook_data, LTTV_PRIO_DEFAULT);
446}
447
448
449/**
450 * Function to unregister a viewer's hook function which is used to
451 * set/update the time interval of the viewer.
452 * @param tab viewer's tab
453 * @param hook hook function of the viewer.
454 * @param hook_data hook data associated with the hook function.
455 */
456
f9240312 457__EXPORT void lttvwindow_unregister_time_window_notify(Tab *tab,
501e4e70 458 LttvHook hook, gpointer hook_data)
459{
460 LttvAttributeValue value;
461 LttvHooks * tmp;
8f318283
BP
462 gboolean retval;
463
464 retval= lttv_iattribute_find_by_path(tab->attributes,
465 "hooks/updatetimewindow", LTTV_POINTER, &value);
466 g_assert(retval);
1e3594a3
YB
467 tmp = (LttvHooks*)*(value.v_pointer);
468 if(tmp == NULL) return;
469 lttv_hooks_remove_data(tmp, hook, hook_data);
470}
471
472/**
473 * Function to register a hook function for a viewer to set/update its
474 * allowed time span.
475 * @param tab viewer's tab
476 * @param hook hook function of the viewer.
477 * @param hook_data hook data associated with the hook function.
478 */
68764dff 479__EXPORT void lttvwindow_register_timespan_notify(Tab *tab,
1e3594a3
YB
480 LttvHook hook, gpointer hook_data)
481{
482 LttvAttributeValue value;
483 LttvHooks * tmp;
484 gboolean retval;
485
486 retval= lttv_iattribute_find_by_path(tab->attributes,
487 "hooks/updatetimespan", LTTV_POINTER, &value);
488 g_assert(retval);
489 tmp = (LttvHooks*)*(value.v_pointer);
490 if(tmp == NULL){
491 tmp = lttv_hooks_new();
492 *(value.v_pointer) = tmp;
493 }
494 lttv_hooks_add(tmp, hook,hook_data, LTTV_PRIO_DEFAULT);
495}
496/**
497 * Function to unregister a viewer's hook function which is used to
498 * set/update the time span allowed for the viewer.
499 * @param tab viewer's tab
500 * @param hook hook function of the viewer.
501 * @param hook_data hook data associated with the hook function.
502 */
503
68764dff 504__EXPORT void lttvwindow_unregister_timespan_notify(Tab *tab,
1e3594a3
YB
505 LttvHook hook, gpointer hook_data)
506{
507 LttvAttributeValue value;
508 LttvHooks * tmp;
509 gboolean retval;
510
511 retval= lttv_iattribute_find_by_path(tab->attributes,
512 "hooks/updatetimespan", LTTV_POINTER, &value);
513 g_assert(retval);
501e4e70 514 tmp = (LttvHooks*)*(value.v_pointer);
515 if(tmp == NULL) return;
516 lttv_hooks_remove_data(tmp, hook, hook_data);
517}
518
519/**
520 * Function to register a hook function for a viewer to set/update its
521 * traceset.
522 * @param tab viewer's tab
523 * @param hook hook function of the viewer.
524 * @param hook_data hook data associated with the hook function.
525 */
526
f9240312 527__EXPORT void lttvwindow_register_traceset_notify(Tab *tab,
501e4e70 528 LttvHook hook, gpointer hook_data)
529{
530 LttvAttributeValue value;
531 LttvHooks * tmp;
8f318283
BP
532 gboolean retval;
533
534 retval= lttv_iattribute_find_by_path(tab->attributes,
535 "hooks/updatetraceset", LTTV_POINTER, &value);
536 g_assert(retval);
501e4e70 537 tmp = (LttvHooks*)*(value.v_pointer);
538 if(tmp == NULL){
539 tmp = lttv_hooks_new();
540 *(value.v_pointer) = tmp;
541 }
542 lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
543}
544
545
546/**
547 * Function to unregister a viewer's hook function which is used to
548 * set/update the traceset of the viewer.
549 * @param tab viewer's tab
550 * @param hook hook function of the viewer.
551 * @param hook_data hook data associated with the hook function.
552 */
553
f9240312 554__EXPORT void lttvwindow_unregister_traceset_notify(Tab *tab,
501e4e70 555 LttvHook hook, gpointer hook_data)
556{
557 LttvAttributeValue value;
558 LttvHooks * tmp;
8f318283
BP
559 gboolean retval;
560
561 retval= lttv_iattribute_find_by_path(tab->attributes,
562 "hooks/updatetraceset", LTTV_POINTER, &value);
563 g_assert(retval);
501e4e70 564 tmp = (LttvHooks*)*(value.v_pointer);
565 if(tmp == NULL) return;
566 lttv_hooks_remove_data(tmp, hook, hook_data);
567}
568
9878c8a4 569/**
570 * Function to register a hook function for a viewer be completely redrawn.
571 *
572 * @param tab viewer's tab
573 * @param hook hook function of the viewer.
574 * @param hook_data hook data associated with the hook function.
575 */
576
f9240312 577__EXPORT void lttvwindow_register_redraw_notify(Tab *tab,
9878c8a4 578 LttvHook hook, gpointer hook_data)
579{
580 LttvAttributeValue value;
581 LttvHooks * tmp;
8f318283
BP
582 gboolean retval;
583
584 retval= lttv_iattribute_find_by_path(tab->attributes, "hooks/redraw",
585 LTTV_POINTER, &value);
586 g_assert(retval);
9878c8a4 587 tmp = (LttvHooks*)*(value.v_pointer);
588 if(tmp == NULL){
589 tmp = lttv_hooks_new();
590 *(value.v_pointer) = tmp;
591 }
592 lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
593}
594
595
596/**
597 * Function to unregister a hook function for a viewer be completely redrawn.
598 *
599 * @param tab viewer's tab
600 * @param hook hook function of the viewer.
601 * @param hook_data hook data associated with the hook function.
602 */
603
f9240312 604__EXPORT void lttvwindow_unregister_redraw_notify(Tab *tab,
9878c8a4 605 LttvHook hook, gpointer hook_data)
606{
607 LttvAttributeValue value;
608 LttvHooks * tmp;
8f318283
BP
609 gboolean retval;
610
611 retval= lttv_iattribute_find_by_path(tab->attributes, "hooks/redraw",
612 LTTV_POINTER, &value);
613 g_assert(retval);
9878c8a4 614 tmp = (LttvHooks*)*(value.v_pointer);
615 if(tmp == NULL) return;
616 lttv_hooks_remove_data(tmp, hook, hook_data);
617}
618
619/**
620 * Function to register a hook function for a viewer to re-do the events
621 * requests for the needed interval.
622 *
623 * This action is typically done after a "stop".
624 *
625 * The typical hook will remove all current requests for the viewer
626 * and make requests for missing information.
627 *
628 * @param tab viewer's tab
629 * @param hook hook function of the viewer.
630 * @param hook_data hook data associated with the hook function.
631 */
632
f9240312 633__EXPORT void lttvwindow_register_continue_notify(Tab *tab,
9878c8a4 634 LttvHook hook, gpointer hook_data)
635{
636 LttvAttributeValue value;
637 LttvHooks * tmp;
8f318283
BP
638 gboolean retval;
639
640 retval= lttv_iattribute_find_by_path(tab->attributes, "hooks/continue",
641 LTTV_POINTER, &value);
642 g_assert(retval);
9878c8a4 643 tmp = (LttvHooks*)*(value.v_pointer);
644 if(tmp == NULL){
645 tmp = lttv_hooks_new();
646 *(value.v_pointer) = tmp;
647 }
648 lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
649}
650
651
652/**
653 * Function to unregister a hook function for a viewer to re-do the events
654 * requests for the needed interval.
655 *
656 * @param tab viewer's tab
657 * @param hook hook function of the viewer.
658 * @param hook_data hook data associated with the hook function.
659 */
660
f9240312 661__EXPORT void lttvwindow_unregister_continue_notify(Tab *tab,
9878c8a4 662 LttvHook hook, gpointer hook_data)
663{
664 LttvAttributeValue value;
665 LttvHooks * tmp;
8f318283
BP
666 gboolean retval;
667
668 retval= lttv_iattribute_find_by_path(tab->attributes, "hooks/continue",
669 LTTV_POINTER, &value);
670 g_assert(retval);
9878c8a4 671 tmp = (LttvHooks*)*(value.v_pointer);
672 if(tmp == NULL) return;
673 lttv_hooks_remove_data(tmp, hook, hook_data);
674}
675
676
501e4e70 677/**
678 * Function to register a hook function for a viewer to set/update its
679 * filter.
680 * @param tab viewer's tab
681 * @param hook hook function of the viewer.
682 * @param hook_data hook data associated with the hook function.
683 */
684
f9240312 685__EXPORT void lttvwindow_register_filter_notify(Tab *tab,
501e4e70 686 LttvHook hook, gpointer hook_data)
687{
688 LttvAttributeValue value;
689 LttvHooks * tmp;
8f318283
BP
690 gboolean retval;
691
692 retval= lttv_iattribute_find_by_path(tab->attributes, "hooks/updatefilter",
693 LTTV_POINTER, &value);
694 g_assert(retval);
501e4e70 695 tmp = (LttvHooks*)*(value.v_pointer);
696 if(tmp == NULL){
697 tmp = lttv_hooks_new();
698 *(value.v_pointer) = tmp;
699 }
700 lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
701}
702
703
704/**
705 * Function to unregister a viewer's hook function which is used to
706 * set/update the filter of the viewer.
707 * @param tab viewer's tab
708 * @param hook hook function of the viewer.
709 * @param hook_data hook data associated with the hook function.
710 */
711
f9240312 712__EXPORT void lttvwindow_unregister_filter_notify(Tab *tab,
501e4e70 713 LttvHook hook,
714 gpointer hook_data)
715{
716 LttvAttributeValue value;
717 LttvHooks * tmp;
8f318283
BP
718 gboolean retval;
719
720 retval= lttv_iattribute_find_by_path(tab->attributes, "hooks/updatefilter",
721 LTTV_POINTER, &value);
722 g_assert(retval);
501e4e70 723 tmp = (LttvHooks*)*(value.v_pointer);
724 if(tmp == NULL) return;
725 lttv_hooks_remove_data(tmp, hook, hook_data);
726}
727
728/**
5290ec02 729 * function to register a hook function for a viewer to set/update its
501e4e70 730 * current time.
731 * @param tab viewer's tab
732 * @param hook hook function of the viewer.
733 * @param hook_data hook data associated with the hook function.
734 */
735
f9240312 736__EXPORT void lttvwindow_register_current_time_notify(Tab *tab,
501e4e70 737 LttvHook hook, gpointer hook_data)
738{
739 LttvAttributeValue value;
740 LttvHooks * tmp;
8f318283
BP
741 gboolean retval;
742
743 retval= lttv_iattribute_find_by_path(tab->attributes,
744 "hooks/updatecurrenttime", LTTV_POINTER, &value);
745 g_assert(retval);
501e4e70 746 tmp = (LttvHooks*)*(value.v_pointer);
747 if(tmp == NULL){
748 tmp = lttv_hooks_new();
749 *(value.v_pointer) = tmp;
750 }
751 lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
752}
753
754
755/**
5290ec02 756 * function to unregister a viewer's hook function which is used to
501e4e70 757 * set/update the current time of the viewer.
758 * @param tab viewer's tab
759 * @param hook hook function of the viewer.
760 * @param hook_data hook data associated with the hook function.
761 */
762
f9240312 763__EXPORT void lttvwindow_unregister_current_time_notify(Tab *tab,
501e4e70 764 LttvHook hook, gpointer hook_data)
765{
766 LttvAttributeValue value;
767 LttvHooks * tmp;
8f318283
BP
768 gboolean retval;
769
770 retval= lttv_iattribute_find_by_path(tab->attributes,
771 "hooks/updatecurrenttime", LTTV_POINTER, &value);
772 g_assert(retval);
501e4e70 773 tmp = (LttvHooks*)*(value.v_pointer);
774 if(tmp == NULL) return;
775 lttv_hooks_remove_data(tmp, hook, hook_data);
776}
777
5290ec02 778/**
779 * function to register a hook function for a viewer to set/update its
780 * current position.
781 * @param tab viewer's tab
782 * @param hook hook function of the viewer.
783 * @param hook_data hook data associated with the hook function.
784 */
785
f9240312 786__EXPORT void lttvwindow_register_current_position_notify(Tab *tab,
5290ec02 787 LttvHook hook, gpointer hook_data)
788{
789 LttvAttributeValue value;
790 LttvHooks * tmp;
8f318283
BP
791 gboolean retval;
792
793 retval= lttv_iattribute_find_by_path(tab->attributes,
794 "hooks/updatecurrentposition", LTTV_POINTER, &value);
795 g_assert(retval);
5290ec02 796 tmp = (LttvHooks*)*(value.v_pointer);
797 if(tmp == NULL){
798 tmp = lttv_hooks_new();
799 *(value.v_pointer) = tmp;
800 }
801 lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
802}
803
804
805/**
806 * function to unregister a viewer's hook function which is used to
807 * set/update the current position of the viewer.
808 * @param tab viewer's tab
809 * @param hook hook function of the viewer.
810 * @param hook_data hook data associated with the hook function.
811 */
812
f9240312 813__EXPORT void lttvwindow_unregister_current_position_notify(Tab *tab,
5290ec02 814 LttvHook hook, gpointer hook_data)
815{
816 LttvAttributeValue value;
817 LttvHooks * tmp;
8f318283
BP
818 gboolean retval;
819
820 retval= lttv_iattribute_find_by_path(tab->attributes,
821 "hooks/updatecurrentposition", LTTV_POINTER, &value);
822 g_assert(retval);
5290ec02 823 tmp = (LttvHooks*)*(value.v_pointer);
824 if(tmp == NULL) return;
825 lttv_hooks_remove_data(tmp, hook, hook_data);
826}
827
501e4e70 828
829/**
830 * Function to register a hook function for a viewer to show
831 * the content of the viewer.
832 * @param tab viewer's tab
833 * @param hook hook function of the viewer.
834 * @param hook_data hook data associated with the hook function.
835 */
836
837void lttvwindow_register_show_notify(Tab *tab,
838 LttvHook hook, gpointer hook_data)
839{
840 LttvAttributeValue value;
841 LttvHooks * tmp;
8f318283
BP
842 gboolean retval;
843
844 retval= lttv_iattribute_find_by_path(tab->attributes, "hooks/showviewer",
845 LTTV_POINTER, &value);
846 g_assert(retval);
501e4e70 847 tmp = (LttvHooks*)*(value.v_pointer);
848 if(tmp == NULL){
849 tmp = lttv_hooks_new();
850 *(value.v_pointer) = tmp;
851 }
852 lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
853}
854
855
856/**
857 * Function to unregister a viewer's hook function which is used to
858 * show the content of the viewer..
859 * @param tab viewer's tab
860 * @param hook hook function of the viewer.
861 * @param hook_data hook data associated with the hook function.
862 */
863
864void lttvwindow_unregister_show_notify(Tab *tab,
865 LttvHook hook, gpointer hook_data)
866{
867 LttvAttributeValue value;
868 LttvHooks * tmp;
8f318283
BP
869 gboolean retval;
870
871 retval= lttv_iattribute_find_by_path(tab->attributes, "hooks/showviewer",
872 LTTV_POINTER, &value);
873 g_assert(retval);
501e4e70 874 tmp = (LttvHooks*)*(value.v_pointer);
875 if(tmp == NULL) return;
876 lttv_hooks_remove_data(tmp, hook, hook_data);
877}
878
879/**
880 * Function to register a hook function for a viewer to set/update the
881 * dividor of the hpane.
882 * @param tab viewer's tab
883 * @param hook hook function of the viewer.
884 * @param hook_data hook data associated with the hook function.
885 */
886
887void lttvwindow_register_dividor(Tab *tab,
888 LttvHook hook, gpointer hook_data)
889{
890 LttvAttributeValue value;
891 LttvHooks * tmp;
8f318283
BP
892 gboolean retval;
893
894 retval= lttv_iattribute_find_by_path(tab->attributes, "hooks/hpanedividor",
895 LTTV_POINTER, &value);
896 g_assert(retval);
501e4e70 897 tmp = (LttvHooks*)*(value.v_pointer);
898 if(tmp == NULL){
899 tmp = lttv_hooks_new();
900 *(value.v_pointer) = tmp;
901 }
902 lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
903}
904
905
906/**
907 * Function to unregister a viewer's hook function which is used to
908 * set/update hpane's dividor of the viewer.
909 * It will be called by the destructor of the viewer.
910 * @param tab viewer's tab
911 * @param hook hook function of the viewer.
912 * @param hook_data hook data associated with the hook function.
913 */
914
915void lttvwindow_unregister_dividor(Tab *tab,
916 LttvHook hook, gpointer hook_data)
917{
918 LttvAttributeValue value;
919 LttvHooks * tmp;
8f318283
BP
920 gboolean retval;
921
922 retval= lttv_iattribute_find_by_path(tab->attributes, "hooks/hpanedividor",
923 LTTV_POINTER, &value);
924 g_assert(retval);
501e4e70 925 tmp = (LttvHooks*)*(value.v_pointer);
926 if(tmp == NULL) return;
927 lttv_hooks_remove_data(tmp, hook, hook_data);
928}
929
930
501e4e70 931/**
932 * Function to set the time interval of the current tab.
933 * It will be called by a viewer's signal handle associated with
934 * the move_slider signal
935 * @param tab viewer's tab
936 * @param time_interval a pointer where time interval is stored.
937 */
938
f9240312 939__EXPORT void lttvwindow_report_time_window(Tab *tab,
940 TimeWindow time_window)
501e4e70 941{
b052368a 942 //set_time_window(tab, time_window);
943 //set_time_window_adjustment(tab, time_window);
944
e800cf84 945 time_change_manager(tab, time_window);
946
947
948#if 0
b052368a 949 /* Set scrollbar */
950 LttvTracesetContext *tsc =
951 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
952 TimeInterval time_span = tsc->time_span;
953 GtkAdjustment *adjustment = gtk_range_get_adjustment(GTK_RANGE(tab->scrollbar));
b052368a 954 g_object_set(G_OBJECT(adjustment),
955 "lower",
0c5dbe3b 956 0.0, /* lower */
b052368a 957 "upper",
b9a010a2 958 ltt_time_to_double(
959 ltt_time_sub(time_span.end_time, time_span.start_time))
c74e0cf9 960 , /* upper */
b052368a 961 "step_increment",
962 ltt_time_to_double(time_window->time_width)
963 / SCROLL_STEP_PER_PAGE
c74e0cf9 964 , /* step increment */
b052368a 965 "page_increment",
966 ltt_time_to_double(time_window->time_width)
c74e0cf9 967 , /* page increment */
b052368a 968 "page_size",
969 ltt_time_to_double(time_window->time_width)
c74e0cf9 970 , /* page size */
b052368a 971 NULL);
972 gtk_adjustment_changed(adjustment);
973
974 //g_object_set(G_OBJECT(adjustment),
975 // "value",
976 // ltt_time_to_double(time_window->start_time)
c74e0cf9 977 // , /* value */
b052368a 978 // NULL);
979 /* Note : the set value will call set_time_window if scrollbar value changed
980 */
981 gtk_adjustment_set_value(adjustment,
b9a010a2 982 ltt_time_to_double(
983 ltt_time_sub(time_window->start_time,
984 time_span.start_time))
c74e0cf9 985 );
e800cf84 986#endif //0
501e4e70 987}
988
989
990/**
5290ec02 991 * Function to set the current time of the current tab.
501e4e70 992 * It will be called by a viewer's signal handle associated with
993 * the button-release-event signal
994 * @param tab viewer's tab
995 * @param time a pointer where time is stored.
996 */
997
f9240312 998__EXPORT void lttvwindow_report_current_time(Tab *tab,
e800cf84 999 LttTime time)
501e4e70 1000{
e800cf84 1001 current_time_change_manager(tab, time);
501e4e70 1002}
1003
5290ec02 1004/**
1005 * Function to set the current event of the current tab.
1006 * It will be called by a viewer's signal handle associated with
1007 * the button-release-event signal
1008 * @param tab viewer's tab
1009 * @param time a pointer where time is stored.
1010 */
1011
f9240312 1012__EXPORT void lttvwindow_report_current_position(Tab *tab,
451aaf27 1013 LttvTracesetPosition *pos)
5290ec02 1014{
5290ec02 1015 current_position_change_manager(tab, pos);
1016}
1017
1018
501e4e70 1019/**
1020 * Function to set the position of the hpane's dividor (viewer).
1021 * It will be called by a viewer's signal handle associated with
1022 * the motion_notify_event event/signal
1023 * @param tab viewer's tab
1024 * @param position position of the hpane's dividor.
1025 */
1026
1027void lttvwindow_report_dividor(Tab *tab, gint position)
1028{
1029 LttvAttributeValue value;
1030 LttvHooks * tmp;
8f318283
BP
1031 gboolean retval;
1032
1033 retval= lttv_iattribute_find_by_path(tab->attributes, "hooks/hpanedividor",
1034 LTTV_POINTER, &value);
1035 g_assert(retval);
501e4e70 1036 tmp = (LttvHooks*)*(value.v_pointer);
1037 if(tmp == NULL) return;
1038 lttv_hooks_call(tmp, &position);
1039}
1040
501e4e70 1041/**
1042 * Function to request data in a specific time interval to the main window. The
1043 * event request servicing is differed until the glib idle functions are
1044 * called.
1045 *
1046 * The viewer has to provide hooks that should be associated with the event
1047 * request.
1048 *
1049 * Either start time or start position must be defined in a EventRequest
1050 * structure for it to be valid.
1051 *
1052 * end_time, end_position and num_events can all be defined. The first one
1053 * to occur will be used as end criterion.
1054 *
1055 * @param tab viewer's tab
1056 * @param events_requested the structure of request from.
1057 */
1058
f9240312 1059__EXPORT void lttvwindow_events_request(Tab *tab,
1060 EventsRequest *events_request)
501e4e70 1061{
20fde85f 1062 tab->events_requests = g_slist_append(tab->events_requests, events_request);
501e4e70 1063
1064 if(!tab->events_request_pending)
1065 {
553d1e7b 1066 /* Redraw has +20 priority. We want to let the redraw be done while we do
e140c5b3 1067 * our job. Mathieu : test with high prio higher than events for better
1068 * scrolling. */
c55068ce 1069 /* Mathieu, 2008 : ok, finally, the control flow view needs the cell updates
1070 * to come soon enough so we can have one active cell to get the pixmap
1071 * buffer height from. Therefore, let the gdk events run before the events
1072 * requests.
1073 */
1074 g_idle_add_full((G_PRIORITY_HIGH_IDLE + 21),
1075 //g_idle_add_full((G_PRIORITY_DEFAULT + 2),
501e4e70 1076 (GSourceFunc)execute_events_requests,
1077 tab,
1078 NULL);
1079 tab->events_request_pending = TRUE;
1080 }
1081}
1082
1083
1084/**
1085 * Function to remove data requests related to a viewer.
1086 *
1087 * The existing requests's viewer gpointer is compared to the pointer
1088 * given in argument to establish which data request should be removed.
1089 *
1090 * @param tab the tab the viewer belongs to.
1091 * @param viewer a pointer to the viewer data structure
1092 */
1093
1094gint find_viewer (const EventsRequest *a, gconstpointer b)
1095{
2d262115 1096 return (a->owner != b);
501e4e70 1097}
1098
1099
f9240312 1100__EXPORT void lttvwindow_events_request_remove_all(Tab *tab,
501e4e70 1101 gconstpointer viewer)
1102{
6843100a 1103 GSList *element = tab->events_requests;
501e4e70 1104
1105 while((element =
6843100a 1106 g_slist_find_custom(element, viewer,
501e4e70 1107 (GCompareFunc)find_viewer))
1108 != NULL) {
2d262115 1109 EventsRequest *events_request = (EventsRequest *)element->data;
3bafb436 1110 // Modified so a viewer being destroyed won't have its after_request
1111 // called. Not so important anyway. Note that a viewer that call this
1112 // remove_all function will not get its after_request called.
1113 //if(events_request->servicing == TRUE) {
1114 // lttv_hooks_call(events_request->after_request, NULL);
1115 //}
c5b5eee1 1116 events_request_free(events_request);
1117 //g_free(events_request);
501e4e70 1118 tab->events_requests = g_slist_remove_link(tab->events_requests, element);
6843100a 1119 element = g_slist_next(element);
1120 if(element == NULL) break; /* end of list */
501e4e70 1121 }
b052368a 1122 if(g_slist_length(tab->events_requests) == 0) {
1123 tab->events_request_pending = FALSE;
1124 g_idle_remove_by_data(tab);
1125 }
1126
501e4e70 1127}
1128
efcd775d 1129
1130/**
1131 * Function to see if there are events request pending.
1132 *
1133 * It tells if events requests are pending. Useful for checks in some events,
1134 * i.e. detailed event list scrolling.
1135 *
1136 * @param tab the tab the viewer belongs to.
1137 * @param viewer a pointer to the viewer data structure
1138 * @return : TRUE is events requests are pending, else FALSE.
1139 */
1140
f9240312 1141__EXPORT gboolean lttvwindow_events_request_pending(Tab *tab)
efcd775d 1142{
1143 GSList *element = tab->events_requests;
1144
c73ce169
FD
1145 if(element == NULL){
1146 return FALSE;
1147 }
1148 else {
1149 return TRUE;
1150 }
efcd775d 1151}
1152
1153
50106726 1154/**
1155 * Function to get the current time interval shown on the current tab.
1156 * It will be called by a viewer's hook function to update the
1157 * shown time interval of the viewer and also be called by the constructor
1158 * of the viewer.
1159 * @param tab viewer's tab
1160 * @return time window.
1161 */
1162
f9240312 1163__EXPORT TimeWindow lttvwindow_get_time_window(Tab *tab)
50106726 1164{
1165 return tab->time_window;
1166}
1167
501e4e70 1168
501e4e70 1169/**
1170 * Function to get the current time/event of the current tab.
1171 * It will be called by a viewer's hook function to update the
1172 * current time/event of the viewer.
1173 * @param tab viewer's tab
6ea08962 1174 * @return time
501e4e70 1175 */
1176
f9240312 1177__EXPORT LttTime lttvwindow_get_current_time(Tab *tab)
501e4e70 1178{
6ea08962 1179 return tab->current_time;
501e4e70 1180}
1181
1182
1183/**
1184 * Function to get the filter of the current tab.
501e4e70 1185 * @param filter, a pointer to a filter.
c790dfd9 1186 *
1187 * returns the current filter
501e4e70 1188 */
f9240312 1189__EXPORT LttvFilter *lttvwindow_get_filter(Tab *tab)
501e4e70 1190{
e433e6d6 1191 return g_object_get_data(G_OBJECT(tab->vbox), "filter");
501e4e70 1192}
1193
dc5e5266 1194/**
1195 * Function to set the filter of the current tab.
1196 * It should be called by the filter GUI to tell the
1197 * main window to update the filter tab's lttv_filter.
1198 *
1199 * This function does change the current filter, removing the
1200 * old one when necessary, and call the updatefilter hooks
1201 * of the registered viewers.
1202 *
1203 * @param main_win, the main window the viewer belongs to.
1204 * @param filter, a pointer to a filter.
1205 */
dc5e5266 1206void lttvwindow_report_filter(Tab *tab, LttvFilter *filter)
1207{
1208 LttvAttributeValue value;
1209 LttvHooks * tmp;
8f318283 1210 gboolean retval;
dc5e5266 1211
e433e6d6 1212 //lttv_filter_destroy(tab->filter);
1213 //tab->filter = filter;
dc5e5266 1214
8f318283
BP
1215 retval= lttv_iattribute_find_by_path(tab->attributes, "hooks/updatefilter",
1216 LTTV_POINTER, &value);
1217 g_assert(retval);
dc5e5266 1218 tmp = (LttvHooks*)*(value.v_pointer);
1219 if(tmp == NULL) return;
962e2228 1220 lttv_hooks_call(tmp, filter);
dc5e5266 1221}
1222
451aaf27 1223#ifdef BABEL_CLEANUP
501e4e70 1224
1225/**
1226 * Function to get the stats of the traceset
1227 * @param tab viewer's tab
1228 */
1229
f9240312 1230__EXPORT LttvTracesetStats* lttvwindow_get_traceset_stats(Tab *tab)
501e4e70 1231{
1232 return tab->traceset_info->traceset_context;
1233}
451aaf27 1234#endif /*BABEL_CLEANUP*/
c5b5eee1 1235
9a366873
FD
1236__EXPORT LttvTraceset *lttvwindow_get_traceset(Tab *tab)
1237{
1238 return tab->traceset_info->traceset;
1239}
1240
c5b5eee1 1241void events_request_free(EventsRequest *events_request)
1242{
88bf15f0 1243
c5b5eee1 1244 if(events_request == NULL) return;
1245
1246 if(events_request->start_position != NULL)
88bf15f0 1247 lttv_traceset_destroy_position(events_request->start_position);
c5b5eee1 1248 if(events_request->end_position != NULL)
88bf15f0
FD
1249 lttv_traceset_destroy_position(events_request->end_position);
1250#ifdef BABEL_CLEANUP
1251 if(events_request->hooks != NULL) {
c5b5eee1 1252 GArray *hooks = events_request->hooks;
88bf15f0 1253
04348950 1254 lttv_trace_hook_remove_all(&hooks);
88bf15f0 1255
c5b5eee1 1256 g_array_free(events_request->hooks, TRUE);
88bf15f0 1257
c5b5eee1 1258 }
88bf15f0 1259
c5b5eee1 1260 if(events_request->before_chunk_traceset != NULL)
1261 lttv_hooks_destroy(events_request->before_chunk_traceset);
1262 if(events_request->before_chunk_trace != NULL)
1263 lttv_hooks_destroy(events_request->before_chunk_trace);
1264 if(events_request->before_chunk_tracefile != NULL)
1265 lttv_hooks_destroy(events_request->before_chunk_tracefile);
1266 if(events_request->event != NULL)
1267 lttv_hooks_destroy(events_request->event);
c5b5eee1 1268 if(events_request->after_chunk_tracefile != NULL)
1269 lttv_hooks_destroy(events_request->after_chunk_tracefile);
1270 if(events_request->after_chunk_trace != NULL)
1271 lttv_hooks_destroy(events_request->after_chunk_trace);
1272 if(events_request->after_chunk_traceset != NULL)
1273 lttv_hooks_destroy(events_request->after_chunk_traceset);
1274 if(events_request->before_request != NULL)
1275 lttv_hooks_destroy(events_request->before_request);
1276 if(events_request->after_request != NULL)
1277 lttv_hooks_destroy(events_request->after_request);
9a366873 1278#endif /*BABEL_CLEANUP*/
88bf15f0
FD
1279 g_free(events_request);
1280
1281
c5b5eee1 1282}
1283
1284
f9240312 1285__EXPORT GtkWidget *main_window_get_widget(Tab *tab)
6a4f1205 1286{
93ac601b 1287 return tab->mw->mwindow;
6a4f1205 1288}
1289
This page took 0.144558 seconds and 4 git commands to generate.