OSDN Git Service

6eade637bd457d99e7ae90564a6dc5ffd4b67db7
[gpet/origin.git] / src / menu.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * Gui Policy Editor for TOMOYO Linux
4  *
5  * menu.c
6  * Copyright (C) Yoshihiro Kusuno 2010,2011 <yocto@users.sourceforge.jp>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #include <gtk/gtk.h>
28 #include <glib/gi18n.h>
29
30 #include "gpet.h"
31
32 static void terminate(GtkAction *action, transition_t *transition);
33 static void copy_line(GtkAction *action, transition_t *transition);
34 static void optimize_acl(GtkAction *action, transition_t *transition);
35 static void delete_transition(GtkAction *action, transition_t *transition);
36 static void insert_history_buffer(GtkWidget *view, gchar *entry);
37 static void append_transition(GtkAction *action, transition_t *transition);
38 static void set_transition(GtkAction *action, transition_t *transition);
39 static void manager_transition(GtkAction *action, transition_t *transition);
40 static void memory_transition(GtkAction *action, transition_t *transition);
41 static void show_about_dialog(void);
42 static void Process_state(GtkAction *action, transition_t *transition);
43 static void Detach_acl(GtkAction *action, transition_t *transition);
44
45 static GtkActionEntry entries[] = {
46   {"FileMenu", NULL, N_("_File")},
47   {"EditMenu", NULL, N_("_Edit")},
48   {"ViewMenu", NULL, N_("_View")},
49   {"HelpMenu", NULL, N_("_Help")},
50
51   {"Quit", GTK_STOCK_QUIT, N_("_Quit"), "<control>Q",
52         N_("Quit a program"), G_CALLBACK(terminate)},
53
54   {"Edit", GTK_STOCK_EDIT, N_("S_et"), "<control>E",
55         N_("Set or Edit the selected line"), G_CALLBACK(set_transition)},
56   {"Add", GTK_STOCK_ADD, N_("_Add"), "<control>I",
57         N_("Append line"), G_CALLBACK(append_transition)},
58   {"Delete", GTK_STOCK_DELETE, N_("_Delete"), "<control>D",
59         N_("Delete the selected line"), G_CALLBACK(delete_transition)},
60   {"Copy", GTK_STOCK_COPY, N_("_Copy"), "<control>C",
61         N_("Copy an entry at the cursor position to history buffer"),
62         G_CALLBACK(copy_line)},
63   {"OptimizationSupport", GTK_STOCK_CONVERT,
64         N_("_OptimizationSupport"), "<control>O",
65         N_("Extraction of redundant ACL entries"), G_CALLBACK(optimize_acl)},
66
67   {"Search", GTK_STOCK_FIND, N_("_Search..."), "<control>F",
68         N_("Search for text"), G_CALLBACK(search_input)},
69   {"SearchBack", GTK_STOCK_GO_BACK, N_("Search_Backwards"), "<control><shift>G",
70         N_("Search backwards for the same text"), G_CALLBACK(search_back)},
71   {"SearchFoward", GTK_STOCK_GO_FORWARD, N_("SearchFor_wards"), "<control>G",
72         N_("Search forwards for the same text"), G_CALLBACK(search_forward)},
73
74   {"Refresh", GTK_STOCK_REFRESH, N_("_Refresh"), "<control>R",
75         N_("Refresh to the latest information"), G_CALLBACK(refresh_transition)},
76   {"Manager", GTK_STOCK_DND, N_("_Manager..."), "<control>M",
77         N_("Manager Profile Editor"), G_CALLBACK(manager_transition)},
78   {"Memory", GTK_STOCK_DND, N_("_Statistics..."), "<control>S",
79         N_("Statistics"), G_CALLBACK(memory_transition)},
80
81   {"About", GTK_STOCK_ABOUT, N_("_About"), "<alt>A",
82         N_("About a program"), show_about_dialog}
83 };
84 static guint n_entries = G_N_ELEMENTS(entries);
85
86 static GtkToggleActionEntry toggle_entries[] = {
87   { "Process", GTK_STOCK_MEDIA_RECORD, N_("Process"), "<control>at",
88         N_("Process State Viewer"), G_CALLBACK(Process_state), FALSE},
89   { "ACL", "", N_("Detach ACL"), "",
90         N_("Detach ACL window"), G_CALLBACK(Detach_acl), FALSE},
91 };
92 static guint n_toggle_entries = G_N_ELEMENTS(toggle_entries);
93
94 static const gchar *ui_info =
95 "<ui>"
96 "  <menubar name='MenuBar'>"
97 "    <menu action='FileMenu'>"
98 "      <menuitem action='Quit'/>"
99 "    </menu>"
100
101 "    <menu action='EditMenu'>"
102 "      <menuitem action='Edit'/>"
103 "      <menuitem action='Add'/>"
104 "      <menuitem action='Delete'/>"
105 "      <separator/>"
106 "      <menuitem action='Copy'/>"
107 "      <menuitem action='OptimizationSupport'/>"
108 "      <separator/>"
109 "      <menuitem action='Search'/>"
110 "      <menuitem action='SearchBack'/>"
111 "      <menuitem action='SearchFoward'/>"
112 "    </menu>"
113
114 "    <menu action='ViewMenu'>"
115 "      <menuitem action='Refresh'/>"
116 "      <separator/>"
117 "      <menuitem action='Manager'/>"
118 "      <menuitem action='Memory'/>"
119 "      <separator/>"
120 "      <menuitem action='Process'/>"
121 "      <separator/>"
122 "      <menuitem action='ACL'/>"
123 "    </menu>"
124
125 "    <menu action='HelpMenu'>"
126 "      <menuitem action='About'/>"
127 "    </menu>"
128 "  </menubar>"
129
130 "  <toolbar name='ToolBar'>"
131 "    <toolitem action='Quit'/>"
132 "    <separator/>"
133 "    <toolitem action='Edit'/>"
134 "    <toolitem action='Add'/>"
135 "    <toolitem action='Delete'/>"
136 "    <separator/>"
137 "    <toolitem action='Copy'/>"
138 "    <toolitem action='OptimizationSupport'/>"
139 "    <separator/>"
140 "    <toolitem action='Search'/>"
141 "    <toolitem action='SearchBack'/>"
142 "    <toolitem action='SearchFoward'/>"
143 "    <separator/>"
144 "    <toolitem action='Refresh'/>"
145 "    <separator/>"
146 "    <toolitem action='Process'/>"
147 "    <separator/>"
148 "    <toolitem action='About'/>"
149 "  </toolbar>"
150
151 "  <popup name='PopUp'>"
152 "      <menuitem action='Edit'/>"
153 "      <menuitem action='Add'/>"
154 "      <menuitem action='Delete'/>"
155 "      <separator/>"
156 "      <menuitem action='Copy'/>"
157 "      <menuitem action='OptimizationSupport'/>"
158 "  </popup>"
159 "</ui>";
160
161 GtkWidget *create_menu(GtkWidget *parent, transition_t *transition,
162                                 GtkWidget **toolbar)
163 {
164         GtkUIManager            *ui;
165         GtkActionGroup          *actions;
166         GtkAccelGroup           *accel_group;
167         GError                  *error = NULL;
168         GtkWidget               *popup;
169
170         actions = gtk_action_group_new("Actions");
171         gtk_action_group_set_translation_domain(actions, GETTEXT_PACKAGE);
172         gtk_action_group_add_actions(actions,
173                         entries, n_entries, transition);
174         gtk_action_group_add_toggle_actions(actions,
175                         toggle_entries, n_toggle_entries, transition);
176
177         ui = gtk_ui_manager_new();
178         gtk_ui_manager_insert_action_group(ui, actions, 0);
179
180         gtk_action_set_sensitive(
181                 gtk_action_group_get_action(actions, "Search"), TRUE);
182         gtk_action_set_sensitive(
183                 gtk_action_group_get_action(actions, "SearchBack"), FALSE);
184         gtk_action_set_sensitive(
185                 gtk_action_group_get_action(actions, "SearchFoward"), FALSE);
186         gtk_action_set_sensitive(
187                 gtk_action_group_get_action(actions, "Edit"), FALSE);
188         gtk_action_set_sensitive(gtk_action_group_get_action(
189                                 actions, "OptimizationSupport"), FALSE);
190
191         if (is_offline()) {
192                 gtk_action_set_sensitive(
193                         gtk_action_group_get_action(actions, "Process"), FALSE);
194                 gtk_action_set_sensitive(
195                         gtk_action_group_get_action(actions, "Memory"), FALSE);
196         }
197
198         transition->actions = actions;
199
200 //      gtk_ui_manager_set_add_tearoffs(ui, TRUE);
201         accel_group = gtk_ui_manager_get_accel_group(ui);
202         gtk_window_add_accel_group(GTK_WINDOW(parent), accel_group);
203         if (!gtk_ui_manager_add_ui_from_string(ui, ui_info, -1, NULL)) {
204                 g_message ("building menus failed: %s", error->message);
205                 g_error_free (error);
206         }
207
208         *toolbar = gtk_ui_manager_get_widget(ui, "/ToolBar");
209         gtk_toolbar_set_style(GTK_TOOLBAR(*toolbar), GTK_TOOLBAR_ICONS);
210
211         /* to save gpet.c popup_menu() */
212         popup = gtk_ui_manager_get_widget(ui, "/PopUp");
213         g_object_set_data(G_OBJECT(transition->window), "popup", popup);
214
215         /* to save gpet.c gpet_main() */
216         g_object_set_data(G_OBJECT(transition->window),
217                                                 "AccelGroup", accel_group);
218
219         return gtk_ui_manager_get_widget(ui, "/MenuBar");
220 }
221 /*-------+---------+---------+---------+---------+---------+---------+--------*/
222 void disp_statusbar(transition_t *transition, int scr)
223 {
224         gchar   *status_str = NULL;
225
226         switch (scr) {
227         case CCS_SCREEN_EXCEPTION_LIST :
228                 status_str = g_strdup_printf("Entry[%d]",
229                         transition->exp.count);
230                 break;
231         case CCS_SCREEN_PROFILE_LIST :
232                 status_str = g_strdup_printf("Entry[%d]",
233                         transition->prf.count);
234                 break;
235         case CCS_SCREEN_NS_LIST :
236                 status_str = g_strdup_printf("Entry[%d]",
237                         transition->ns.count);
238                 break;
239         case CCS_SCREEN_DOMAIN_LIST :
240         case CCS_SCREEN_ACL_LIST :
241                 if (transition->task_flag)
242                         status_str = g_strdup_printf("Process[%d] Policy[%d]",
243                                 transition->tsk.count, transition->acl.count);
244                 else
245                         status_str = g_strdup_printf("Domain[%d] Policy[%d]",
246                                 transition->domain_count, transition->acl.count);
247                 break;
248         case CCS_MAXSCREEN :
249                 status_str = g_strdup_printf("Domain[%d]",
250                         transition->domain_count);
251                 break;
252         default :
253                 g_warning("BUG: screen [%d]  file(%s) line(%d)",
254                                 scr, __FILE__, __LINE__);
255                 break;
256         }
257         gtk_statusbar_pop(GTK_STATUSBAR(transition->statusbar),
258                                 transition->contextid);
259         gtk_statusbar_push(GTK_STATUSBAR(transition->statusbar),
260                                 transition->contextid, status_str);
261         g_free(status_str);
262 }
263 /*---------------------------------------------------------------------------*/
264 /* from realpath.c (ccs-patch-1.8.1-20110505) */
265 gchar *encode_to_octal_str(const char *str)
266 {
267         int     i;
268         int     str_len;
269         int     len = 0;
270         const char *p = str;
271         char    *cp;
272         char    *cp0;
273
274         if (!p)
275                 return NULL;
276
277         str_len = strlen(str);
278         for (i = 0; i < str_len; i++) {
279                 const unsigned char c = p[i];
280                 if (c == '\\')
281 //                      len += 2;
282                         len++;
283                 else if (c > ' ' && c < 127)
284                         len++;
285                 else
286                         len += 4;
287         }
288         len++;
289
290         /* Reserve space for appending "/". */
291         cp = g_malloc0(len + 10);
292         if (!cp)
293                 return NULL;
294
295         cp0 = cp;
296         p = str;
297         for (i = 0; i < str_len; i++) {
298                 const unsigned char c = p[i];
299                 if (c == '\\') {
300                         *cp++ = '\\';
301 //                      *cp++ = '\\';
302                 } else if (c > ' ' && c < 127) {
303                         *cp++ = c;
304                 } else {
305                         *cp++ = '\\';
306                         *cp++ = (c >> 6) + '0';
307                         *cp++ = ((c >> 3) & 7) + '0';
308                         *cp++ = (c & 7) + '0';
309                 }
310         }
311         return cp0;
312 }
313
314 static gint encode_copy(gchar *cp, gchar *buff)
315 {
316         gchar           *str;
317         gint            len;
318
319         if (!*cp)
320                 return 0;
321
322         str = encode_to_octal_str(cp);
323         strcpy(buff, str);
324         len = strlen(str) - 1;
325         g_free(str);
326
327         return len;
328 }
329
330 static gchar *escape_str_encode(const char *input)
331 {
332         gchar           *str, *cp0, *cp1;
333         gchar           *tmp, buff[strlen(input)*3+1];
334         gboolean        match = FALSE;
335
336         if (!input)
337                 return NULL;
338
339         cp0 = str = g_strdup(input);
340         tmp = buff;
341         for( ; *cp0; cp0++, tmp++) {
342                 if (*cp0 == '\\' && *(cp0 + 1) == '\'') {
343                         *tmp = *++cp0;
344                 } else if (*cp0 == '\'') {      // start "
345                         cp1 = ++cp0;
346                         for ( ; *cp0; cp0++) {
347                                 if (*cp0 == '\\' && *(cp0 + 1) == '\'') {
348                                         if (cp1 < cp0) {
349                                                 *cp0 = '\0';
350                                                 tmp += encode_copy(cp1, tmp);
351                                                 tmp++;
352                                         } else {
353                                                 *tmp = *(cp0 + 1);
354                                         }
355                                         cp1 = ++cp0;
356                                 } else if (*cp0 == '\'') {      // end "
357                                         *cp0 = '\0';
358                                         match = TRUE;
359                                         break;
360                                 }
361                         }
362
363                         if (match) {
364                                 tmp += encode_copy(cp1, tmp);
365                                 match = FALSE;
366                         } else {
367                                 g_warning(" [\']pair not match!");
368                                 cp0 = cp1;
369                                 *tmp = *cp0;
370                         }
371                 } else {
372                         *tmp = *cp0;
373                 }
374         }
375         *tmp = *cp0;
376
377         g_free(str);
378         return g_strdup(buff);
379 }
380 /*-------+---------+---------+---------+---------+---------+---------+--------*/
381 static void terminate(GtkAction *action, transition_t *transition)
382 {
383         write_config(transition);
384         g_object_unref(transition->actions);
385         gtk_main_quit();
386 }
387 /*-------+---------+---------+---------+---------+---------+---------+--------*/
388 static gulong handler_id = 0UL;
389
390 static gboolean cb_destroy_acl(GtkWidget *widget, GdkEvent *event,
391                                         transition_t *transition)
392 {
393         GtkWidget       *acl_container;
394         GtkPaned        *paned;
395
396         if (handler_id == 0UL)
397                 return FALSE;
398
399         /* get gpet.c main()*/
400         acl_container = g_object_get_data(G_OBJECT(transition->window), "acl_container");
401         paned = g_object_get_data(G_OBJECT(transition->window), "pane");
402
403         g_signal_handler_disconnect(
404                         G_OBJECT(transition->acl_window), handler_id);
405         handler_id = 0UL;
406
407         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(
408                 gtk_action_group_get_action(transition->actions, "ACL")), FALSE);
409         transition->acl_detached = FALSE;
410
411         gtk_widget_reparent(GTK_WIDGET(transition->container),
412                                         GTK_WIDGET(paned));
413
414         gtk_widget_reparent(GTK_WIDGET(acl_container),
415                                         GTK_WIDGET(paned));
416
417         transition->current_page = CCS_SCREEN_DOMAIN_LIST;
418         set_sensitive(transition->actions, transition->task_flag,
419                                                 transition->current_page);
420         refresh_transition(NULL, transition);
421
422         return gtk_widget_hide_on_delete(transition->acl_window);
423 }
424
425 static void Detach_acl(GtkAction *action, transition_t *transition)
426 {
427         GtkWidget       *acl_container;
428         GtkPaned        *paned;
429         /* get gpet.c main()*/
430         acl_container = g_object_get_data(G_OBJECT(transition->window), "acl_container");
431         paned = g_object_get_data(G_OBJECT(transition->window), "pane");
432
433         if (transition->acl_detached) {
434                 cb_destroy_acl(NULL, NULL, transition);
435         } else {
436                 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(
437                         gtk_action_group_get_action(transition->actions, "ACL")), TRUE);
438                 transition->acl_detached = TRUE;
439                 handler_id = g_signal_connect(
440                         G_OBJECT(transition->acl_window), "delete_event",
441                         G_CALLBACK(cb_destroy_acl), transition);
442                 gtk_widget_reparent(GTK_WIDGET(acl_container),
443                                         transition->acl_window);
444                 gtk_widget_show_all(transition->acl_window);
445
446                 gtk_widget_reparent(GTK_WIDGET(transition->container),
447                                         GTK_WIDGET(paned));
448                 transition->current_page = CCS_SCREEN_ACL_LIST;
449                 set_sensitive(transition->actions, transition->task_flag,
450                                                 transition->current_page);
451                 refresh_transition(NULL, transition);
452         }
453 }
454 /*-------+---------+---------+---------+---------+---------+---------+--------*/
455 static void Process_state(GtkAction *action, transition_t *transition)
456 {
457         GtkWidget       *view;
458         GtkWidget       *notebook;
459         GtkWidget       *tab1;
460         gchar           *label_str;
461
462         view = transition->task_flag ?
463                         transition->tsk.treeview : transition->treeview;
464         gtk_container_remove(transition->container, view);
465         g_object_ref(view);
466
467         transition->task_flag = ~transition->task_flag & 1;
468
469         if (transition->task_flag) {
470                 label_str = _("Process State");
471                 view = transition->tsk.treeview;
472         } else {
473                 label_str = _("Domain Transition");
474                 view = transition->treeview;
475         }
476
477         /* from gpet.c:gpet_main()*/
478         notebook = g_object_get_data(
479                                 G_OBJECT(transition->window), "notebook");
480         tab1 = g_object_get_data(
481                                 G_OBJECT(transition->window), "tab1");
482         gtk_notebook_set_tab_label_text(
483                                 GTK_NOTEBOOK(notebook), tab1, label_str);
484         gtk_notebook_set_menu_label_text(
485                                 GTK_NOTEBOOK(notebook), tab1, label_str);
486
487         gtk_container_add(transition->container, view);
488
489         transition->current_page = CCS_SCREEN_DOMAIN_LIST;
490         set_sensitive(transition->actions, transition->task_flag,
491                                                 transition->current_page);
492         if (transition->acl_detached)
493                 g_object_set(G_OBJECT(notebook), "can-focus", FALSE, NULL);
494         else
495                 g_object_set(G_OBJECT(notebook), "can-focus", TRUE, NULL);
496         refresh_transition(action, transition);
497 }
498 /*-------+---------+---------+---------+---------+---------+---------+--------*/
499 void view_cursor_set(GtkWidget *view,
500                         GtkTreePath *path, GtkTreeViewColumn *column)
501 {
502         if (!path) {
503                 path = gtk_tree_path_new_from_indices(0, -1);
504         }
505 #if 0
506         {
507                 gchar *path_str = gtk_tree_path_to_string(path);
508                 DEBUG_PRINT("<%s> TreePath[%s]\n",
509                         g_type_name(G_OBJECT_TYPE(view)), path_str);
510                 g_free(path_str);
511         }
512 #endif
513         gtk_tree_view_set_cursor(GTK_TREE_VIEW(view), path, column, FALSE);
514         gtk_tree_path_free(path);
515         gtk_tree_view_get_cursor(GTK_TREE_VIEW(view), &path, &column);
516         if (!path) {
517                 path = gtk_tree_path_new_from_indices(0, -1);
518                 gtk_tree_view_set_cursor(
519                                 GTK_TREE_VIEW(view), path, column, FALSE);
520         }
521         gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(view), path, NULL,
522                                                 TRUE, 0.5, 0.0);        // ksn
523         gtk_tree_path_free(path);
524 }
525
526 static void clear_acl_view(transition_t *transition)
527 {
528         gtk_entry_set_text(GTK_ENTRY(transition->domainbar), get_ns_name());
529         transition->acl.count = 0;
530         add_list_data(&(transition->acl), CCS_SCREEN_ACL_LIST);
531 }
532
533 void refresh_transition(GtkAction *action, transition_t *transition)
534 {
535         GtkTreePath             *path = NULL;
536         GtkTreeViewColumn       *column = NULL;
537         GtkWidget               *view = NULL;
538
539         DEBUG_PRINT("In  Refresh Page[%d]\n", (int)transition->current_page);
540         switch((int)transition->current_page) {
541         case CCS_SCREEN_EXCEPTION_LIST :
542                 view = transition->exp.listview;
543                 gtk_tree_view_get_cursor(GTK_TREE_VIEW(view),
544                                                         &path, &column);
545                 if (get_exception_policy(
546                     &(transition->exp.list), &(transition->exp.count)))
547                         break;
548                 add_list_data(&(transition->exp), CCS_SCREEN_EXCEPTION_LIST);
549                 set_position_addentry(transition, &path);
550                 disp_statusbar(transition, CCS_SCREEN_EXCEPTION_LIST);
551                 view_cursor_set(view, path, column);
552                 gtk_widget_grab_focus(view);
553                 break;
554         case CCS_SCREEN_PROFILE_LIST :
555                 view = transition->prf.listview;
556                 gtk_tree_view_get_cursor(GTK_TREE_VIEW(view),
557                                                         &path, &column);
558                 if (get_profile(
559                     &(transition->prf.list), &(transition->prf.count)))
560                         break;
561                 add_list_data(&(transition->prf), CCS_SCREEN_PROFILE_LIST);
562                 set_position_addentry(transition, &path);
563                 disp_statusbar(transition, CCS_SCREEN_PROFILE_LIST);
564                 view_cursor_set(view, path, column);
565                 gtk_widget_grab_focus(view);
566                 break;
567         case CCS_SCREEN_NS_LIST :
568                 view = transition->ns.listview;
569                 gtk_tree_view_get_cursor(GTK_TREE_VIEW(view),
570                                                         &path, &column);
571                 if (get_namespace(
572                     &(transition->ns.list), &(transition->ns.count)))
573                         break;
574                 add_list_data(&(transition->ns), CCS_SCREEN_NS_LIST);
575                 set_position_addentry(transition, &path);
576                 disp_statusbar(transition, CCS_SCREEN_NS_LIST);
577                 view_cursor_set(view, path, column);
578                 gtk_widget_grab_focus(view);
579                 break;
580         case CCS_SCREEN_DOMAIN_LIST :
581         case CCS_MAXSCREEN :
582                 view = transition->task_flag ?
583                         transition->tsk.treeview : transition->treeview;
584                 gtk_tree_view_get_cursor(
585                                 GTK_TREE_VIEW(view), &path, &column);
586
587                 gtk_widget_hide(view);
588                 if (transition->task_flag) {
589                         if (get_task_list(&(transition->tsk.task),
590                                                 &(transition->tsk.count)))
591                                 break;
592                         add_task_tree_data(GTK_TREE_VIEW(view), &(transition->tsk));
593                         gtk_tree_view_expand_all(GTK_TREE_VIEW(view));
594                         view_cursor_set(view, path, column);
595                 } else {
596                         if (get_domain_policy(
597                             transition->dp, &(transition->domain_count)))
598                                 break;
599                         add_tree_data(GTK_TREE_VIEW(view), transition->dp);
600                         gtk_tree_view_expand_all(GTK_TREE_VIEW(view));
601                         set_position_addentry(transition, &path);
602                         if (transition->domain_count)
603                                 view_cursor_set(view, path, column);
604                         else
605                                 clear_acl_view(transition);
606                 }
607                 gtk_widget_show(view);
608                 gtk_widget_grab_focus(view);
609                 break;
610         case CCS_SCREEN_ACL_LIST :
611                 view = transition->task_flag ?
612                         transition->tsk.treeview : transition->treeview;
613                 gtk_tree_view_get_cursor(
614                                 GTK_TREE_VIEW(view), &path, &column);
615                 view_cursor_set(view, path, column);
616                 gtk_widget_grab_focus(transition->acl.listview);
617                 break;
618         }
619
620         if (transition->acl_detached) {
621                 DEBUG_PRINT("★Transition[%d] Acl[%d]\n",
622                 gtk_window_has_toplevel_focus(GTK_WINDOW(transition->window)),
623                 gtk_window_has_toplevel_focus(GTK_WINDOW(transition->acl_window)));
624         }
625         DEBUG_PRINT("Out  Refresh Page[%d]\n", (int)transition->current_page);
626 }
627 /*-------+---------+---------+---------+---------+---------+---------+--------*/
628 static void copy_line(GtkAction *action, transition_t *transition)
629 {
630         gint            index;
631         GtkWidget       *view;
632
633         switch((int)transition->current_page) {
634         case CCS_SCREEN_DOMAIN_LIST :
635                 index = get_current_domain_index(transition);
636                 view = transition->treeview;
637                 if (index >= 0)
638                         insert_history_buffer(view, decode_from_octal_str(
639                                 get_domain_name(transition->dp, index)));
640                 break;
641         case CCS_SCREEN_ACL_LIST :
642                 view = transition->acl.listview;
643                 insert_history_buffer(view, get_alias_and_operand(view, TRUE));
644                 break;
645         case CCS_SCREEN_EXCEPTION_LIST :
646                 view = transition->exp.listview;
647                 insert_history_buffer(view, get_alias_and_operand(view, TRUE));
648                 break;
649         case CCS_SCREEN_PROFILE_LIST :
650                 view = transition->prf.listview;
651                 insert_history_buffer(view, get_alias_and_operand(view, FALSE));
652                 break;
653         case CCS_SCREEN_NS_LIST :
654                 view = transition->ns.listview;
655                 insert_history_buffer(view, get_alias_and_operand(view, FALSE));
656                 break;
657         default :
658                 break;
659         }
660 }
661 /*-------+---------+---------+---------+---------+---------+---------+--------*/
662 static void optimize_acl(GtkAction *action, transition_t *transition)
663 {
664         GtkTreeSelection        *selection;
665         GtkTreeModel            *model;
666         gint                    count, current;
667
668         if ((int)transition->current_page != CCS_SCREEN_ACL_LIST)
669                 return;
670
671         selection = gtk_tree_view_get_selection(
672                                 GTK_TREE_VIEW(transition->acl.listview));
673         if (!selection || !(count =
674             gtk_tree_selection_count_selected_rows(selection)))
675                 return;
676         DEBUG_PRINT("count[%d]\n", count);
677
678         // current位置を取得:
679         current = select_list_line(&(transition->acl));
680         if (current < 0)
681                 return;
682
683         get_optimize_acl_list(current,
684                         &(transition->acl.list), transition->acl.count);
685
686         model = gtk_tree_view_get_model(GTK_TREE_VIEW(transition->acl.listview));
687         gtk_tree_model_foreach(model,
688                 (GtkTreeModelForeachFunc)disp_acl_line, &(transition->acl));
689
690 #if 0
691         gint                    index;
692         GtkTreePath             *start_path, *end_path;
693         gint                    start_index, end_index;
694         // 表示処理
695         start_path = end_path = gtk_tree_path_new_from_indices(current, -1);
696         gtk_tree_selection_unselect_range(selection, start_path, end_path);
697
698         for (index = 0; index < transition->acl.count; index++) {
699                 if (transition->acl.list[index].selected)
700                         break;
701         }
702         end_path = NULL;
703         start_path = gtk_tree_path_new_from_indices(index, -1);
704         start_index = end_index = index;
705         count = -1;
706         for ( ; index < transition->acl.count; index++) {
707                 count++;
708                 // 対象データ:ccs_gacl_list[index].selected == 1;
709                 if (!transition->acl.list[index].selected)
710                         continue;
711
712                 //パス取得:
713                 if (index == (start_index + count)) {
714                         end_path = gtk_tree_path_new_from_indices(index, -1);
715                         end_index = index;
716                 } else {
717                         if (!end_path)
718                                 end_path = start_path;
719
720                         // カーソルセット:
721 g_print("start[%d] end[%d]\n", start_index, end_index);
722                         gtk_tree_selection_select_range(
723                                         selection, start_path, end_path);
724
725                         start_path = gtk_tree_path_new_from_indices(index, -1);
726                         start_index = index;
727                         count = 0;
728                         end_path = NULL;
729                 }
730         }
731
732         if (end_path) {
733 g_print("start[%d] end[%d]\n", start_index, end_index);
734                 gtk_tree_selection_select_range(selection, start_path, end_path);
735         }
736 #endif
737 }
738 /*-------+---------+---------+---------+---------+---------+---------+--------*/
739 static gint message_dialog(GtkWidget *parent, gchar *message)
740 {
741         GtkWidget       *dialog;
742         gint            result;
743
744         dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(parent) ,
745                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
746                         GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
747                         NULL);
748         gtk_message_dialog_set_markup(GTK_MESSAGE_DIALOG(dialog), message);
749
750         result = gtk_dialog_run(GTK_DIALOG(dialog));
751         gtk_widget_destroy(dialog);
752
753         return result;
754 }
755
756 static void delete_transition(GtkAction *action, transition_t *transition)
757 {
758         GtkTreeSelection        *selection;
759         gint                    count;
760         GtkWidget               *parent;
761         gchar                   *message = NULL;
762         gint                    ret = 1;
763
764         DEBUG_PRINT("delete : current page[%d]\n", transition->current_page);
765
766         switch((int)transition->current_page) {
767         case CCS_SCREEN_EXCEPTION_LIST :
768                 selection = gtk_tree_view_get_selection(
769                                 GTK_TREE_VIEW(transition->exp.listview));
770                 if (!selection || !(count =
771                     gtk_tree_selection_count_selected_rows(selection)))
772                         break;
773                 DEBUG_PRINT("count[%d]\n", count);
774                 message = count > 1 ?
775                  g_strdup_printf(_(
776                         "<span foreground='red' size='x-large'>"
777                         "<b>Delete</b> the %d selected exception policies?</span>"), count) :
778                  g_strdup_printf(_(
779                         "<span foreground='red' size='x-large'>"
780                         "<b>Delete</b> the selected exception policy?</span>"));
781                 if (GTK_RESPONSE_YES ==
782                     message_dialog(transition->window, message)) {
783                         ret = delete_exp(transition, selection, count);
784                 }
785                 break;
786         case CCS_SCREEN_DOMAIN_LIST :
787         case CCS_MAXSCREEN :
788                 selection = gtk_tree_view_get_selection(
789                                 GTK_TREE_VIEW(transition->treeview));
790                 if (!selection || !(count =
791                     gtk_tree_selection_count_selected_rows(selection)))
792                         break;
793                 DEBUG_PRINT("count[%d]\n", count);
794                 message = count > 1 ?
795                  g_strdup_printf(_(
796                         "<span foreground='red' size='x-large'>"
797                         "<b>Delete</b> the %d selected domains?</span>"), count) :
798                  g_strdup_printf(_(
799                         "<span foreground='red' size='x-large'>"
800                         "<b>Delete</b> the selected domain?</span>"));
801                 if (GTK_RESPONSE_YES ==
802                     message_dialog(transition->window, message)) {
803                         ret = delete_domain(transition, selection, count);
804                 }
805                 break;
806         case CCS_SCREEN_ACL_LIST :
807                 DEBUG_PRINT("Delete ACL\n");
808                 selection = gtk_tree_view_get_selection(
809                                 GTK_TREE_VIEW(transition->acl.listview));
810                 if (!selection || !(count =
811                     gtk_tree_selection_count_selected_rows(selection)))
812                         break;
813                 DEBUG_PRINT("count[%d]\n", count);
814                 parent = transition->acl_detached ?
815                         transition->acl_window : transition->window;
816                 message = count > 1 ?
817                  g_strdup_printf(_(
818                         "<span foreground='blue' size='x-large'>"
819                         "<b>Delete</b> the %d selected policies?</span>"), count) :
820                  g_strdup_printf(_(
821                         "<span foreground='blue' size='x-large'>"
822                         "<b>Delete</b> the selected policy?</span>"));
823                 if (GTK_RESPONSE_YES ==
824                     message_dialog(parent, message)) {
825                         ret = delete_acl(transition, selection, count);
826                 }
827                 break;
828         case CCS_SCREEN_MANAGER_LIST :
829                 DEBUG_PRINT("Delete manager\n");
830                 break;
831         }
832
833         g_free(message);
834
835         if (!ret)
836                 refresh_transition(NULL, transition);
837 }
838 /*-------+---------+---------+---------+---------+---------+---------+--------*/
839 #define COMBO_LIST_LIMIT        20
840 static GList    *combolist = NULL;
841 static gchar    *Last_entry_string = NULL;
842
843 gchar *get_combo_entry_last(void)
844 {
845         gchar           *str, *buff;
846         gchar           *cp;
847
848         buff = g_malloc0(strlen(Last_entry_string) + 1);
849         if (!buff)
850                 return NULL;
851
852         str = buff;
853         for (cp = Last_entry_string; *cp; cp++) {
854                 if (*cp == '\\' && *(cp + 1) == '\'') {
855                         *str++ = *++cp;
856                 } else if (*cp != '\'') {
857                         *str++ = *cp;
858                 }
859         }
860         *str = *cp;
861
862 //g_print("[%s]\n", buff);
863         return buff;
864 }
865
866 static void insert_history_buffer(GtkWidget *view, gchar *entry)
867 {
868         GtkClipboard    *clipboard;
869         GList           *list;
870         guint           len;
871
872         if (!entry)
873                 return;
874
875         /* to system clipboard */
876         clipboard = gtk_widget_get_clipboard(view, GDK_SELECTION_CLIPBOARD);
877         gtk_clipboard_set_text(clipboard, entry, -1);
878
879         for (list = combolist; list; list = g_list_next(list)) {
880                 if (strcmp(entry, (gchar *)list->data) == 0) {
881                         g_free(entry);
882                         return;
883                 }
884         }
885
886         combolist = g_list_insert(combolist, entry, 0);
887         len = g_list_length(combolist);
888         if (len > COMBO_LIST_LIMIT) {
889                 g_free(g_list_nth_data(combolist, len - 1));
890                 combolist = g_list_delete_link(combolist,
891                                         g_list_nth(combolist, len - 1));
892         }
893 }
894
895 static gchar *normalize_strdup(gchar *input)
896 {
897         gchar           *cp;
898         gint            len = strlen(input);
899         gchar           *str, *buff;
900         gboolean        match = FALSE;
901
902         if (len < 1)
903                 return NULL;
904
905         cp = input + len - 1;
906         if (g_ascii_isspace(*cp)) {
907                 while (len && g_ascii_isspace(*cp)) {
908                         cp--;
909                         len--;
910                 }
911         }
912
913         cp = input;
914         while (len && g_ascii_isspace(*cp)) {
915                 cp++;
916                 len--;
917         }
918
919         buff = g_malloc0(len + 1);
920         if (!buff)
921                 return NULL;
922
923         str = buff;
924         while (len && *cp) {
925                 if (*cp == '\\' && *(cp + 1) == '\'') {
926                         *str++ = *cp++;
927                         len--;
928                 } else if (*cp == '\'') {
929                         match = match ? FALSE : TRUE;
930                 } else {
931                         if (!match && g_ascii_isspace(*cp)) {
932                                 while (g_ascii_isspace(*(cp+1))) {
933                                         cp++;
934                                         len--;
935                                 }
936                         }
937                 }
938                 *str++ = *cp++;
939                 len--;
940         }
941         *str = '\0';
942
943 //g_print("%2d[%s]\n", len, buff);
944         return buff;
945 }
946
947 static gint combo_entry_apply(GtkWidget *combo, gchar **new_text)
948 {
949         GtkComboBox     *combobox;
950         GList           *list;
951         gboolean        exist_flag = FALSE;
952
953         combobox = GTK_COMBO_BOX(combo);
954         (*new_text) = gtk_combo_box_get_active_text(combobox);
955         if(!(*new_text) || strcmp(*new_text, "") == 0)
956                 return 1;
957
958         g_free(Last_entry_string);
959         Last_entry_string = normalize_strdup(*new_text);
960         g_free(*new_text);
961         *new_text = g_strdup(Last_entry_string);
962
963         for (list = combolist; list; list = g_list_next(list)) {
964                 if (strcmp(*new_text, (gchar *)list->data) == 0) {
965                         exist_flag = TRUE;
966                         break;
967                 }
968         }
969
970         if (!exist_flag) {
971                 guint len;
972                 combolist = insert_item(combobox, combolist, *new_text, 0);
973                 len = g_list_length(combolist);
974                 if (len > COMBO_LIST_LIMIT) {
975                         combolist = remove_item(combobox, combolist, len - 1);
976                 }
977                 DEBUG_PRINT("Append '%s'.\n", *new_text);
978         }
979
980         return exist_flag ? 1 : 0;
981 }
982
983 static void cb_combo_entry_activate(GtkEntry *entry, GtkWidget *dialog)
984 {
985         const gchar     *input = gtk_entry_get_text(entry);
986
987         if (!input || strcmp(input, "") == 0)
988                 return;
989
990         gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_APPLY);
991 }
992
993 /*---------------------------------------------------------------------------*/
994 static gint append_dialog(transition_t *transition,
995                                 gchar *title, gchar **input)
996 {
997         GtkWidget               *dialog, *parent;
998         GtkWidget               *combo;
999         GList                   *list;
1000         gint                    response, result = 1;
1001
1002         parent = (transition->acl_detached &&
1003                 (int)transition->current_page == CCS_SCREEN_ACL_LIST) ?
1004                         transition->acl_window : transition->window;
1005
1006         dialog = gtk_dialog_new_with_buttons(title,
1007                         GTK_WINDOW(parent),
1008                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1009                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1010                         GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
1011                         NULL);
1012
1013         combo = gtk_combo_box_entry_new_text();
1014         g_signal_connect(G_OBJECT(GTK_BIN(combo)->child) , "activate" ,
1015                         G_CALLBACK(cb_combo_entry_activate), dialog);
1016
1017         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
1018
1019         for (list = combolist; list; list = g_list_next(list)) {
1020                 gtk_combo_box_append_text(
1021                         GTK_COMBO_BOX(combo), (gchar *)list->data);
1022         }
1023
1024         gtk_container_add(
1025                 GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), combo);
1026         gtk_widget_set_size_request(dialog, 600, -1);
1027         gtk_widget_show_all(dialog);
1028
1029         response = gtk_dialog_run(GTK_DIALOG(dialog));
1030         if (response == GTK_RESPONSE_APPLY) {
1031                 gchar *tmp;
1032                 combo_entry_apply(combo, input);
1033                 tmp = escape_str_encode(*input);
1034 //              g_print("[%s]:[%s]\n", *input, tmp);
1035                 g_free(*input);
1036                 *input = tmp;
1037                 result = 0;
1038         }
1039         gtk_widget_destroy(dialog);
1040
1041         return result;
1042 }
1043
1044 static void append_transition(GtkAction *action, transition_t *transition)
1045 {
1046         gchar           *input = NULL;
1047         gint            index, result = 1;
1048         enum addentry_type      type = ADDENTRY_NON;
1049         char            *err_buff = NULL;
1050
1051         switch((int)transition->current_page) {
1052         case CCS_SCREEN_DOMAIN_LIST :
1053                 DEBUG_PRINT("append domain\n");
1054                 result = append_dialog(transition,
1055                                  _("Add Domain"), &input);
1056                 if (!result)
1057                         result = add_domain(input, &err_buff);
1058                 type = ADDENTRY_DOMAIN_LIST;
1059                 break;
1060         case CCS_SCREEN_ACL_LIST :
1061                 DEBUG_PRINT("append acl\n");
1062                 result = append_dialog(transition, _("Add Acl"), &input);
1063                 if (!result) {
1064                         index = get_current_domain_index(transition);
1065                         if (index >= 0)
1066                                 result = add_acl_list(transition->dp,
1067                                                 index, input, &err_buff);
1068                 }
1069                 type = ADDENTRY_ACL_LIST;
1070                 break;
1071         case CCS_SCREEN_EXCEPTION_LIST :
1072                 DEBUG_PRINT("append exception\n");
1073                 result = append_dialog(transition,
1074                                  _("Add Exception"), &input);
1075                 if (!result)
1076                         result = add_exception_policy(input, &err_buff);
1077                 type = ADDENTRY_EXCEPTION_LIST;
1078                 break;
1079         case CCS_SCREEN_PROFILE_LIST :
1080                 DEBUG_PRINT("append profile\n");
1081                 result = append_dialog(transition,
1082                                  _("Add Profile (0 - 255)"), &input);
1083                 if (!result)
1084                         result = add_profile(input, &err_buff);
1085                 type = ADDENTRY_PROFILE_LIST;
1086                 break;
1087         case CCS_SCREEN_NS_LIST :
1088                 DEBUG_PRINT("append namespace\n");
1089                 result = append_dialog(transition,
1090                                  _("Add Namespace"), &input);
1091                 if (!result)
1092                         result = add_namespace(input, &err_buff);
1093                 type = ADDENTRY_NAMESPACE_LIST;
1094                 break;
1095         default :
1096                 DEBUG_PRINT("append ???\n");
1097                 break;
1098         }
1099
1100         if (result) {
1101                 if(err_buff) {
1102                         g_warning("%s", err_buff);
1103                         free(err_buff);
1104                 }
1105                 transition->addentry = ADDENTRY_NON;
1106         } else {
1107                 transition->addentry = type;
1108                 refresh_transition(NULL, transition);
1109         }
1110 }
1111 /*-------+---------+---------+---------+---------+---------+---------+--------*/
1112 enum list_column_pos {
1113         LIST_PROFILE,           // display
1114         PROFILE_NO,             // hidden
1115         N_COLUMNS_LIST
1116 };
1117 static GtkWidget *create_list_profile(void)
1118 {
1119         GtkWidget               *treeview;
1120         GtkListStore            *liststore;
1121         GtkCellRenderer *renderer;
1122         GtkTreeViewColumn       *column;
1123
1124         liststore = gtk_list_store_new(N_COLUMNS_LIST,
1125                                         G_TYPE_STRING, G_TYPE_UINT);
1126         treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(liststore));
1127         g_object_unref(liststore);
1128
1129         renderer = gtk_cell_renderer_text_new();
1130         column = gtk_tree_view_column_new();
1131         gtk_tree_view_column_pack_start(column, renderer, FALSE);
1132         column = gtk_tree_view_column_new_with_attributes("operand",
1133                                 renderer, "text", LIST_PROFILE, NULL);
1134         gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
1135
1136         // ヘッダ表示
1137         gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
1138
1139         return treeview;
1140 }
1141
1142 static void add_list_profile(GtkWidget *listview,
1143                                  generic_list_t *generic)
1144 {
1145         GtkListStore    *store;
1146         GtkTreeIter     iter;
1147         int             i;
1148         gchar           *profile;
1149
1150         store = GTK_LIST_STORE(gtk_tree_view_get_model(
1151                                         GTK_TREE_VIEW(listview)));
1152         gtk_list_store_clear(store);
1153
1154         DEBUG_PRINT("Count[%d]\n", generic->count);
1155         for(i = 0; i < generic->count; i++){
1156                 if (generic->list[i].directive > 255 ||
1157                         !strstr(generic->list[i].operand, "COMMENT="))
1158                         continue;
1159
1160                 DEBUG_PRINT("[%3d]:%3u-%s\n", i,
1161                         generic->list[i].directive, generic->list[i].operand);
1162
1163                 gtk_list_store_append(store, &iter);
1164                 profile = g_strdup_printf("%3u-%s",
1165                                         generic->list[i].directive,
1166                                         generic->list[i].operand);
1167                 gtk_list_store_set(store, &iter,
1168                                 LIST_PROFILE, profile,
1169                                 PROFILE_NO, generic->list[i].directive,
1170                                 -1);
1171                 g_free(profile);
1172         }
1173 }
1174
1175 static gboolean apply_profile(transition_t *transition,
1176                                 GtkTreeSelection *domain_selection,
1177                                 GtkWidget *listview)
1178 {
1179         GtkTreeSelection        *selection;
1180         GtkTreeIter             iter;
1181         GtkTreeModel            *model;
1182         GList                   *list;
1183         guint                   profile_no;
1184         gint                    result;
1185
1186         selection = gtk_tree_view_get_selection(
1187                                                 GTK_TREE_VIEW(listview));
1188         if (selection &&
1189             gtk_tree_selection_count_selected_rows(selection) == 1) {
1190                 list = gtk_tree_selection_get_selected_rows(
1191                                                         selection, NULL);
1192                 model = gtk_tree_view_get_model(GTK_TREE_VIEW(listview));
1193                 gtk_tree_model_get_iter(model, &iter,
1194                                         g_list_first(list)->data);
1195                 gtk_tree_model_get(model, &iter,
1196                                         PROFILE_NO, &profile_no, -1);
1197                 DEBUG_PRINT("Selct Profile [%u]\n", profile_no);
1198                 result = set_domain_profile(transition,
1199                                         domain_selection, profile_no);
1200                 if (!result)
1201                         refresh_transition(NULL, transition);
1202                 return TRUE;
1203         } else {
1204                 return FALSE;
1205         }
1206 }
1207
1208 static void cb_profile_activate(GtkTreeView *treeview, GtkTreePath *treepath,
1209                         GtkTreeViewColumn *treeviewcolumn, GtkWidget *dialog)
1210 {
1211         gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_APPLY);
1212 }
1213
1214 static void set_domain(transition_t *transition)
1215 {
1216         GtkTreeSelection        *domain_selection;
1217         GtkWidget               *dialog;
1218         GtkWidget               *listview;
1219         gint                    count, response;
1220
1221         if (transition->task_flag)
1222                 domain_selection = gtk_tree_view_get_selection(
1223                                 GTK_TREE_VIEW(transition->tsk.treeview));
1224         else
1225                 domain_selection = gtk_tree_view_get_selection(
1226                                 GTK_TREE_VIEW(transition->treeview));
1227
1228         if (!domain_selection || !(count =
1229             gtk_tree_selection_count_selected_rows(domain_selection)))
1230                 return;
1231
1232         dialog = gtk_dialog_new_with_buttons(_("Profile list"),
1233                         GTK_WINDOW(transition->window),
1234                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1235                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1236                         GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
1237                         NULL);
1238
1239         listview = create_list_profile();
1240         g_signal_connect(G_OBJECT(listview), "row-activated",
1241                         G_CALLBACK(cb_profile_activate), dialog);
1242         add_list_profile(listview, &(transition->prf));
1243         view_cursor_set(listview, NULL, NULL);
1244         gtk_container_add(
1245                 GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), listview);
1246         gtk_widget_set_size_request(dialog, 400, 300);
1247         gtk_widget_set_name(dialog, "GpetProfileSelectDialog"); // .gpetrc
1248         gtk_widget_show_all(dialog);
1249
1250 retry_profile:
1251         response = gtk_dialog_run(GTK_DIALOG(dialog));
1252         if (response == GTK_RESPONSE_APPLY) {
1253                 DEBUG_PRINT("Apply button was pressed.\n");
1254                 if (!apply_profile(transition,
1255                                         domain_selection, listview))
1256                         goto retry_profile;
1257         } else if (response == GTK_RESPONSE_CANCEL) {
1258                 DEBUG_PRINT("Cancel button was pressed.\n");
1259         } else {
1260                 DEBUG_PRINT("Another response was recieved.\n");
1261         }
1262         gtk_widget_destroy(dialog);
1263 }
1264
1265 static void cb_profile_entry_activate(GtkEntry *entry, GtkWidget *dialog)
1266 {
1267         const gchar     *input = gtk_entry_get_text(entry);
1268
1269         if (!input || strcmp(input, "") == 0)
1270                 return;
1271
1272         gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_APPLY);
1273 }
1274
1275 static void edit_profile(transition_t *transition)
1276 {
1277         GtkWidget               *dialog;
1278         GtkWidget               *hbox;
1279         GtkWidget               *label;
1280         GtkWidget               *entry;
1281         gchar                   *profile, *label_str, *ptr;
1282         gint                    index, response;
1283
1284         if ((index = select_list_line(&(transition->prf))) < 0)
1285                 return;
1286
1287         entry = gtk_entry_new();
1288
1289         profile = g_strdup(transition->prf.list[index].operand);
1290         ptr = strchr(profile, '=');
1291         if (ptr)
1292                 ptr++;
1293         if (ptr) {
1294                 gtk_entry_set_text(GTK_ENTRY(entry), ptr);
1295                 *ptr = '\0';
1296         }
1297
1298         if (transition->prf.list[index].directive < 256)
1299                 label_str = g_strdup_printf("%3u-%s",
1300                         transition->prf.list[index].directive, profile);
1301         else
1302                 label_str = g_strdup_printf("%s", profile);
1303         label = gtk_label_new(label_str);
1304         g_free(profile);
1305         g_free(label_str);
1306
1307         dialog = gtk_dialog_new_with_buttons(_("Profile Edit"),
1308                         GTK_WINDOW(transition->window),
1309                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1310                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1311                         GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
1312                         NULL);
1313
1314         g_signal_connect(G_OBJECT(entry) , "activate" ,
1315                         G_CALLBACK(cb_profile_entry_activate), dialog);
1316
1317         hbox = gtk_hbox_new(FALSE, 5);
1318         gtk_container_add(
1319                 GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
1320
1321         gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1322         gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
1323
1324         gtk_widget_set_size_request(dialog, 600, -1);
1325         gtk_widget_show_all(dialog);
1326
1327         response = gtk_dialog_run(GTK_DIALOG(dialog));
1328         if (response == GTK_RESPONSE_APPLY) {
1329                 const gchar     *input;
1330                 char            *err_buff = NULL;
1331 //              transition->prf.list[index].selected = 1;
1332                 input = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
1333                 DEBUG_PRINT("Edit profile [%s] index[%d]\n", input, index);
1334                 if (set_profile_level(index, input, &err_buff)) {
1335                         g_warning("%s", err_buff);
1336                         free(err_buff);
1337                 } else {
1338                         refresh_transition(NULL, transition);
1339                 }
1340         }
1341         gtk_widget_destroy(dialog);
1342 }
1343
1344 static void set_transition(GtkAction *action, transition_t *transition)
1345 {
1346         switch((int)transition->current_page) {
1347         case CCS_SCREEN_DOMAIN_LIST :
1348                 DEBUG_PRINT("set profile\n");
1349                 set_domain(transition);
1350                 break;
1351         case CCS_SCREEN_PROFILE_LIST :
1352                 DEBUG_PRINT("edit profile\n");
1353                 edit_profile(transition);
1354                 break;
1355         default :
1356                 DEBUG_PRINT("edit ???\n");
1357                 break;
1358         }
1359 }
1360 /*-------+---------+---------+---------+---------+---------+---------+--------*/
1361 static void manager_transition(GtkAction *action, transition_t *transition)
1362 {
1363         manager_main(transition);
1364 }
1365
1366 static void memory_transition(GtkAction *action, transition_t *transition)
1367 {
1368         memory_main(transition);
1369 }
1370 /*-------+---------+---------+---------+---------+---------+---------+--------*/
1371 GdkPixbuf *get_png_file(void)
1372 {
1373         GdkPixbuf       *pixbuf;
1374         GError          *err = NULL;
1375
1376         pixbuf = gdk_pixbuf_new_from_file(PACKAGE_ICON_DIR "/tomoyo.png", &err);
1377         if (!pixbuf) {
1378                 g_warning("%s", err->message);
1379                 g_error_free(err);
1380         }
1381         return pixbuf;
1382 }
1383
1384 static void show_about_dialog(void)
1385 {
1386         GtkWidget               *dialog;
1387         GtkAboutDialog  *about;
1388         GdkPixbuf               *pixbuf;
1389
1390         const gchar     *authors[] = {
1391                 _("Yoshihiro Kusuno <yocto@users.sourceforge.jp>"),
1392                 _("ccstools --- kumaneko san"),
1393                 NULL};
1394         const gchar     *documenters[] = {_("Yoshihiro Kusuno"), NULL};
1395 //      const gchar     *translators = "none";
1396
1397         dialog = gtk_about_dialog_new();
1398         about = GTK_ABOUT_DIALOG(dialog);
1399         gtk_about_dialog_set_name(about, "gpet");
1400         gtk_about_dialog_set_authors(about, authors);
1401         gtk_about_dialog_set_documenters(about, documenters);
1402 //      gtk_about_dialog_set_translator_credits(about, translators);
1403         gtk_about_dialog_set_version(about, VERSION);
1404         gtk_about_dialog_set_copyright(about,
1405                                 "Copyright(C) 2010,2011 TOMOYO Linux Project");
1406         gtk_about_dialog_set_comments(about,
1407                                 "Gui Policy Editor for TOMOYO Linux 2.4 , 1.8.2"
1408                                 " or AKARI 1.0.17"
1409                                 "\n(based on ccs-editpolicy:ccstools)");
1410         gtk_about_dialog_set_website(about, "http://sourceforge.jp/projects/gpet/");
1411 //      gtk_about_dialog_set_website_label(about, "http://tomoyo.sourceforge.jp/");
1412
1413         pixbuf = get_png_file();
1414         if (pixbuf) {
1415                 gtk_about_dialog_set_logo(about, pixbuf);
1416                 g_object_unref(pixbuf);
1417         }
1418         gtk_container_set_border_width(GTK_CONTAINER(dialog), 5);
1419
1420         gtk_dialog_run(GTK_DIALOG(about));
1421         gtk_widget_destroy(GTK_WIDGET(about));
1422 }