misc: sprintf be gone
[vpp.git] / src / tools / g2 / menu1.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2006-2016 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <gtk/gtk.h>
19 #define GTK_ENABLE_BROKEN // DGMS
20 #include <gtk/gtktext.h>
21 #include <stdlib.h>
22 #include "g2.h"
23 #include <string.h>
24
25 /*
26  * locals
27  */
28 static GtkWidget *s_mainmenubar;
29 static GtkWidget *s_filemenu;
30 static GtkWidget *s_readdefs;
31 static GtkWidget *s_readevents;
32 static GtkWidget *s_readeventsclock;
33 static GtkWidget *s_readcpel;
34 static GtkWidget *s_readclib;
35 static GtkWidget *s_print;
36 static GtkWidget *s_quit;
37
38 static GtkWidget *s_mainfilemenu;
39 static GtkWidget *s_help_general;
40 static GtkWidget *s_help_about;
41 static GtkWidget *s_mainhelpmenu;
42 static GtkWidget *s_helpmenu;
43
44 static GtkWidget *s_filesel;
45 static GtkWidget *s_eventsel;
46
47 typedef struct md_ {
48     GtkWidget *entry;
49     GtkWidget *label;
50     GtkWidget *dialog;
51     boolean (*callback)(char *);
52     char *retry_text;
53 } md_t;
54
55 char *general_help = "\n"
56 "G2 is a performance event visualization tool.\n"
57 "\n"
58 "To view CPEL-format event data:\n"
59 "g2 --cpel <filename>\n"
60 "or use the File Menu->Read CPEL file option.\n"
61 "\n"
62 "To view vppinfra-format (.../open-repo/vppinfra/vppinfra/elog.h) event data:\n"
63 "g2 --clib <filename>\n"
64 "or use the File Menu->Read clib file option.\n"
65 "\n"
66 "To toggle event detail boxes, left-mouse-click on an event.\n"
67 "\n"
68 "To zoom to an area, depress the left mouse button. Move the\n"
69 "mouse. Release the mouse.\n"
70 "\n"
71 "To use the time ruler, depress the right mouse button.  Move the\n"
72 "mouse. Release when done.\n"
73 "\n"
74 "To push a track to the bottom, <ctrl><left-mouse>\n"
75 "\n"
76 "To pull a track to the top, <shift><left-mouse>\n"
77 "\n"
78 "To selectively color/uncolor a track, <ctrl><shift><left-mouse>\n"
79 "\n"
80 "To make the mouse scrollwheel faster, press <shift>\n"
81 "\n"
82 "Hotkeys, supposedly Quake-like:\n"
83 "      w - zoom-in\n"
84 "      s - zoom-out\n"
85 "      a - pan-left\n"
86 "      d - pan-right\n"
87 "      r - pan-up\n"
88 "      f - pan-down\n"
89 "      t - less traces\n"
90 "      g - more traces\n"
91 "\n"
92 "      e - toggle summary-mode\n"
93 "      c - toggle color-mode\n"
94 "\n"
95 "      x - take snapshot\n"
96 "      z - go to next snapshot\n"
97 "      p - put snapshots to snapshots.g2 \n"
98 "      l - load snapshots from snapshots.g2\n"
99 "\n"
100 "<ctrl>q - quit\n"
101 "Send comments / bug reports to the \"fd.io\" mailing list.\n";
102
103 /****************************************************************************
104 * debug_dialog_callback
105 ****************************************************************************/
106
107 boolean debug_dialog_callback (char *s)
108 {
109     g_print("Dialog result: %s", s);
110     return (TRUE);
111 }
112
113 /****************************************************************************
114 * get_dialog_value
115 ****************************************************************************/
116
117 static void get_dialog_value (GtkWidget *dialog, gpointer user_data)
118 {
119     md_t *md = (md_t *)user_data;
120     char * cb_arg;
121
122     cb_arg = (char *) gtk_entry_get_text(GTK_ENTRY(md->entry));
123
124     if ((*md->callback)(cb_arg)) {
125         gtk_grab_remove(md->dialog);
126         gtk_widget_destroy(md->dialog);
127     } else {
128         gtk_label_set_text (GTK_LABEL(md->label), md->retry_text);
129     }
130 }
131
132 /****************************************************************************
133 * modal_dialog
134 ****************************************************************************/
135
136 void modal_dialog (char *label_text, char *retry_text, char *default_value,
137                    boolean (*cb)(char *))
138 {
139     GtkWidget *dialog, *label, *ok_button, *entry;
140     static md_t dlg;
141     md_t *md = &dlg;
142
143     dialog = gtk_dialog_new();
144     label = gtk_label_new(label_text);
145
146     entry = gtk_entry_new();
147     if (default_value)
148         gtk_entry_set_text(GTK_ENTRY(entry), default_value);
149
150     ok_button = gtk_button_new_with_label("OK");
151
152     md->entry = entry;
153     md->label = label;
154     md->retry_text = retry_text;
155     md->dialog = dialog;
156     if (cb)
157         md->callback = cb;
158     else
159         md->callback = debug_dialog_callback;
160
161     gtk_signal_connect (GTK_OBJECT (ok_button), "clicked",
162                         GTK_SIGNAL_FUNC(get_dialog_value), (gpointer) md);
163
164     gtk_signal_connect (GTK_OBJECT (entry), "activate",
165                         GTK_SIGNAL_FUNC(get_dialog_value), (gpointer) md);
166
167     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
168                       entry);
169
170     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
171                       ok_button);
172     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
173     gtk_widget_show_all(dialog);
174     gtk_widget_grab_focus(entry);
175     gtk_grab_add(dialog);
176 }
177
178 /****************************************************************************
179 * get_eventdef_name
180 ****************************************************************************/
181
182 static void get_eventdef_name (GtkFileSelection *sel, gpointer user_data)
183 {
184     char *filename = (char *) gtk_file_selection_get_filename (
185         GTK_FILE_SELECTION(s_filesel));
186     read_event_definitions(filename);
187     set_window_title(filename);
188 }
189
190 /****************************************************************************
191 * read_eventdef_callback
192 ****************************************************************************/
193
194 static void read_eventdef_callback(GtkToggleButton *item, gpointer data)
195 {
196
197     s_filesel = gtk_file_selection_new("Read Event Definitions From...");
198
199     gtk_file_selection_set_filename(GTK_FILE_SELECTION(s_filesel),
200                                     "../h/elog.h");
201
202     gtk_signal_connect (GTK_OBJECT (
203         GTK_FILE_SELECTION(s_filesel)->ok_button),
204                         "clicked",
205                         GTK_SIGNAL_FUNC(get_eventdef_name), NULL);
206
207     gtk_signal_connect_object (GTK_OBJECT (
208         GTK_FILE_SELECTION(s_filesel)->ok_button),
209                                "clicked",
210                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
211                                (gpointer) s_filesel);
212
213     gtk_signal_connect_object (GTK_OBJECT (
214         GTK_FILE_SELECTION(s_filesel)->cancel_button),
215                                "clicked",
216                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
217                                (gpointer) s_filesel);
218     gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_filesel));
219     gtk_widget_show (s_filesel);
220 }
221
222 /****************************************************************************
223 * get_events_name
224 ****************************************************************************/
225
226 static void get_events_name (GtkFileSelection *sel, gpointer user_data)
227 {
228     char *filename = (char *) gtk_file_selection_get_filename (
229         GTK_FILE_SELECTION(s_eventsel));
230     read_events(filename);
231     view1_display_when_idle();
232 }
233
234
235 /****************************************************************************
236 * get_ticks_per_ns
237 ****************************************************************************/
238
239 static boolean get_ticks_per_ns (char *value)
240 {
241     double rv;
242
243     rv = atof (value);
244
245     if (rv == 0.0 || rv > 100000)
246         return(FALSE);
247
248     ticks_per_ns = rv;
249     ticks_per_ns_set = TRUE;
250
251     gtk_widget_show(s_eventsel);
252     return(TRUE);
253 }
254
255 /****************************************************************************
256 * read_events_callback
257 ****************************************************************************/
258
259 static void read_events_callback(GtkToggleButton *item, gpointer data)
260 {
261     char tmpbuf [32];
262
263     s_eventsel = gtk_file_selection_new("Read Events From...");
264
265     gtk_signal_connect (GTK_OBJECT (
266         GTK_FILE_SELECTION(s_eventsel)->ok_button),
267                         "clicked",
268                         GTK_SIGNAL_FUNC(get_events_name), NULL);
269
270     gtk_signal_connect_object (GTK_OBJECT (
271         GTK_FILE_SELECTION(s_eventsel)->ok_button),
272                                "clicked",
273                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
274                                (gpointer) s_eventsel);
275
276     gtk_signal_connect_object (GTK_OBJECT (
277         GTK_FILE_SELECTION(s_eventsel)->cancel_button),
278                                "clicked",
279                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
280                                (gpointer) s_eventsel);
281     gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_eventsel));
282
283     if (ticks_per_ns_set)
284         gtk_widget_show (s_eventsel);
285     else {
286         snprintf(tmpbuf, sizeof(tmpbuf), "%.3f", ticks_per_ns);
287         modal_dialog ("Please enter clock ticks per nanosecond",
288                       "Invalid: Please enter clock ticks per nanosecond",
289                       tmpbuf, get_ticks_per_ns);
290     }
291 }
292
293 /****************************************************************************
294 * read_eventclock_callback
295 ****************************************************************************/
296
297 static void read_eventsclock_callback(GtkToggleButton *item, gpointer data)
298 {
299     ticks_per_ns_set = FALSE;
300     read_events_callback(item, data);
301 }
302
303 /****************************************************************************
304 * infobox_size_request
305 ****************************************************************************/
306
307 void infobox_size_request (GtkWidget *widget, GtkRequisition *req,
308                            gpointer user_data)
309 {
310     char *text = (char *)user_data;
311     char *cp;
312     int widest_line_in_chars;
313     int w;
314     int nlines;
315
316     /*
317      * You'd think that the string extent function would work here.
318      * You'd be wrong.
319      */
320     nlines = w = widest_line_in_chars = 0;
321     for (cp = text; *cp; cp++) {
322         if (*cp == '\n') {
323             if (w > widest_line_in_chars) {
324                 widest_line_in_chars = w;
325             }
326             w = 0;
327             nlines++;
328         }
329         w++;
330     }
331
332     nlines++;
333
334     req->width = (widest_line_in_chars * 8) + 20;
335     req->height = (nlines * 13) + 10;
336 }
337
338 /****************************************************************************
339 * infobox
340 ****************************************************************************/
341
342 void infobox(char *label_text, char *text)
343 {
344     GtkWidget *dialog, *label, *ok_button, *entry;
345     GtkWidget *box;
346
347     dialog = gtk_dialog_new();
348     label = gtk_label_new(label_text);
349
350     entry = gtk_text_new(NULL, NULL);
351
352     gtk_signal_connect (GTK_OBJECT (entry), "size-request",
353                         GTK_SIGNAL_FUNC(infobox_size_request),
354                         (gpointer) text);
355
356     gtk_text_insert(GTK_TEXT(entry), g_font, &fg_black, &bg_white,
357                     text, -1);
358
359     gtk_text_set_editable(GTK_TEXT(entry), FALSE);
360
361     ok_button = gtk_button_new_with_label("OK");
362
363     gtk_signal_connect_object (GTK_OBJECT (ok_button), "clicked",
364                                GTK_SIGNAL_FUNC(gtk_widget_destroy),
365                                (gpointer) GTK_OBJECT(dialog));
366
367     box = gtk_vbox_new(FALSE, 5);
368
369
370     gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
371     gtk_box_pack_start(GTK_BOX(box), ok_button, FALSE, FALSE, 0);
372
373     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
374                       box);
375
376     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
377     gtk_widget_show_all(dialog);
378 }
379
380 /****************************************************************************
381 * help_general_callback
382 ****************************************************************************/
383
384 static void help_general_callback(GtkToggleButton *item, gpointer data)
385 {
386     infobox("General Help", general_help);
387 }
388
389 /****************************************************************************
390 * help_about_callback
391 ****************************************************************************/
392
393 static void help_about_callback(GtkToggleButton *item, gpointer data)
394 {
395     char tmpbuf [1024];
396     snprintf (tmpbuf, sizeof(tmpbuf), "G2 -- Graphical Event Viewer\n\n");
397     view1_about(tmpbuf);
398     pointsel_about(tmpbuf);
399     events_about(tmpbuf);
400     snprintf (tmpbuf+strlen(tmpbuf), sizeof(tmpbuf) - strlen(tmpbuf),
401              "\n%s\n", version_string);
402     snprintf (tmpbuf+strlen(tmpbuf), sizeof(tmpbuf) - strlen(tmpbuf),
403              "%s\n", minor_v_string);
404     infobox("About", tmpbuf);
405 }
406
407
408 /****************************************************************************
409 * get_cpel_name
410 ****************************************************************************/
411
412 static void get_cpel_name (GtkFileSelection *sel, gpointer user_data)
413 {
414     char *filename = (char *)gtk_file_selection_get_filename (
415         GTK_FILE_SELECTION(s_filesel));
416     read_cpel_file(filename);
417     set_window_title(filename);
418 }
419
420 /****************************************************************************
421 * get_clib_name
422 ****************************************************************************/
423
424 static void get_clib_name (GtkFileSelection *sel, gpointer user_data)
425 {
426     char *filename = (char *) gtk_file_selection_get_filename (
427         GTK_FILE_SELECTION(s_filesel));
428     read_clib_file(filename);
429     set_window_title(filename);
430 }
431
432 /****************************************************************************
433 * read_cpel_callback
434 ****************************************************************************/
435
436 static void read_cpel_callback(GtkToggleButton *item, gpointer data)
437 {
438
439     s_filesel = gtk_file_selection_new("Read CPEL data from...");
440
441     gtk_file_selection_set_filename(GTK_FILE_SELECTION(s_filesel),
442                                     "cpel.out");
443
444     gtk_signal_connect (GTK_OBJECT (
445         GTK_FILE_SELECTION(s_filesel)->ok_button),
446                         "clicked",
447                         GTK_SIGNAL_FUNC(get_cpel_name), NULL);
448
449     gtk_signal_connect_object (GTK_OBJECT (
450         GTK_FILE_SELECTION(s_filesel)->ok_button),
451                                "clicked",
452                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
453                                (gpointer) s_filesel);
454
455     gtk_signal_connect_object (GTK_OBJECT (
456         GTK_FILE_SELECTION(s_filesel)->cancel_button),
457                                "clicked",
458                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
459                                (gpointer) s_filesel);
460     gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_filesel));
461     gtk_widget_show (s_filesel);
462 }
463
464 /****************************************************************************
465 * read_clib_callback
466 ****************************************************************************/
467
468 static void read_clib_callback(GtkToggleButton *item, gpointer data)
469 {
470
471     s_filesel = gtk_file_selection_new("Read clib data From...");
472
473     gtk_file_selection_set_filename(GTK_FILE_SELECTION(s_filesel),
474                                     "clib.out");
475
476     gtk_signal_connect (GTK_OBJECT (
477         GTK_FILE_SELECTION(s_filesel)->ok_button),
478                         "clicked",
479                         GTK_SIGNAL_FUNC(get_clib_name), NULL);
480
481     gtk_signal_connect_object (GTK_OBJECT (
482         GTK_FILE_SELECTION(s_filesel)->ok_button),
483                                "clicked",
484                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
485                                (gpointer) s_filesel);
486
487     gtk_signal_connect_object (GTK_OBJECT (
488         GTK_FILE_SELECTION(s_filesel)->cancel_button),
489                                "clicked",
490                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
491                                (gpointer) s_filesel);
492     gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_filesel));
493     gtk_widget_show (s_filesel);
494 }
495
496 /****************************************************************************
497 * menu1_init
498 ****************************************************************************/
499
500 void menu1_init(void)
501 {
502
503     s_filemenu = gtk_menu_new();
504
505     s_readcpel = gtk_menu_item_new_with_label
506         ("Read CPEL file");
507     gtk_menu_append(GTK_MENU(s_filemenu), s_readcpel);
508     gtk_signal_connect(GTK_OBJECT(s_readcpel), "activate",
509                        GTK_SIGNAL_FUNC(read_cpel_callback), 0);
510
511     s_readclib = gtk_menu_item_new_with_label
512         ("Read CLIB file");
513     gtk_menu_append(GTK_MENU(s_filemenu), s_readclib);
514     gtk_signal_connect(GTK_OBJECT(s_readclib), "activate",
515                        GTK_SIGNAL_FUNC(read_clib_callback), 0);
516
517     s_readdefs = gtk_menu_item_new_with_label ("Read Event Definitions");
518     gtk_menu_append(GTK_MENU(s_filemenu), s_readdefs);
519     gtk_signal_connect(GTK_OBJECT(s_readdefs), "activate",
520                        GTK_SIGNAL_FUNC(read_eventdef_callback), 0);
521
522     s_readevents = gtk_menu_item_new_with_label ("Read Event Log");
523     gtk_menu_append(GTK_MENU(s_filemenu), s_readevents);
524     gtk_signal_connect(GTK_OBJECT(s_readevents), "activate",
525                        GTK_SIGNAL_FUNC(read_events_callback), 0);
526
527     s_readeventsclock = gtk_menu_item_new_with_label
528         ("Read Event Log with Different Clock Rate");
529     gtk_menu_append(GTK_MENU(s_filemenu), s_readeventsclock);
530     gtk_signal_connect(GTK_OBJECT(s_readeventsclock), "activate",
531                        GTK_SIGNAL_FUNC(read_eventsclock_callback), 0);
532
533     s_print = gtk_menu_item_new_with_label ("Print");
534     gtk_menu_append(GTK_MENU(s_filemenu), s_print);
535     gtk_signal_connect(GTK_OBJECT(s_print), "activate",
536                        GTK_SIGNAL_FUNC(view1_print_callback), 0);
537
538     s_quit = gtk_menu_item_new_with_label ("Exit");
539     gtk_menu_append(GTK_MENU(s_filemenu), s_quit);
540     gtk_signal_connect(GTK_OBJECT(s_quit), "activate",
541                        GTK_SIGNAL_FUNC(gtk_main_quit), 0);
542
543     s_mainfilemenu = gtk_menu_item_new_with_label("File");
544     gtk_menu_item_set_submenu(GTK_MENU_ITEM(s_mainfilemenu), s_filemenu);
545
546     s_helpmenu = gtk_menu_new();
547
548     s_help_general = gtk_menu_item_new_with_label ("General");
549     gtk_menu_append(GTK_MENU(s_helpmenu), s_help_general);
550     gtk_signal_connect(GTK_OBJECT(s_help_general), "activate",
551                        GTK_SIGNAL_FUNC(help_general_callback), 0);
552
553     s_help_about = gtk_menu_item_new_with_label ("About");
554     gtk_menu_append(GTK_MENU(s_helpmenu), s_help_about);
555     gtk_signal_connect(GTK_OBJECT(s_help_about), "activate",
556                        GTK_SIGNAL_FUNC(help_about_callback), 0);
557
558     s_mainhelpmenu = gtk_menu_item_new_with_label("Help");
559     gtk_menu_item_set_submenu(GTK_MENU_ITEM(s_mainhelpmenu), s_helpmenu);
560
561     s_mainmenubar = gtk_menu_bar_new();
562     gtk_menu_bar_append(GTK_MENU_BAR(s_mainmenubar), s_mainfilemenu);
563     gtk_menu_bar_append(GTK_MENU_BAR(s_mainmenubar), s_mainhelpmenu);
564     gtk_widget_show_all(s_mainmenubar);
565
566     gtk_box_pack_start(GTK_BOX(g_mainvbox), s_mainmenubar, FALSE, FALSE, 0);
567 }