OSDN Git Service

Ver. 0.3
[gpet/origin.git] / src / search.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  * search.c
6  * Copyright (C) Yoshihiro Kusuno 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 #include "conf.h"
32
33 typedef struct _search_t {
34         transition_t    *tran;
35         GtkWidget       *combo;
36         GtkWidget       *dialog;
37 } search_t;
38
39 #define COMBO_LIST_LIMIT        10
40 static GList            *combolist = NULL;
41 static gchar            *S_entry = NULL;
42
43 enum screen_type_e {
44         SCREEN_DOMAIN_LIST,
45         SCREEN_PROCESS_LIST,
46         SCREEN_ACL_LIST,
47         SCREEN_EXCEPTION_LIST,
48         SCREEN_PROFILE_LIST,
49         SCREEN_MANAGER_LIST,
50         SCREEN_STAT_LIST,
51         MAXSCREEN
52 };
53 static  gint            locate_index[MAXSCREEN+1] = {0, };
54
55 static gint get_locate_index(transition_t *transition)
56 {
57         enum screen_type_e      screen;
58
59         switch((int)transition->current_page) {
60         case CCS_SCREEN_DOMAIN_LIST :
61                 if (transition->task_flag) {
62                         screen = SCREEN_PROCESS_LIST;
63                 } else {
64                         screen = SCREEN_DOMAIN_LIST;
65                 }
66                 break;
67         case CCS_SCREEN_ACL_LIST :
68                 screen = SCREEN_ACL_LIST;
69                 break;
70         case CCS_SCREEN_EXCEPTION_LIST :
71                 screen = SCREEN_EXCEPTION_LIST;
72                 break;
73         case CCS_SCREEN_PROFILE_LIST :
74                 screen = SCREEN_PROFILE_LIST;
75                 break;
76         case CCS_SCREEN_MANAGER_LIST :
77         default :
78                 screen = MAXSCREEN;
79                 break;
80         }
81
82         return locate_index[screen];
83 }
84
85 static void put_locate_index(transition_t *transition, gint index)
86 {
87         enum screen_type_e      screen;
88
89         switch((int)transition->current_page) {
90         case CCS_SCREEN_DOMAIN_LIST :
91                 if (transition->task_flag) {
92                         screen = SCREEN_PROCESS_LIST;
93                 } else {
94                         screen = SCREEN_DOMAIN_LIST;
95                 }
96                 break;
97         case CCS_SCREEN_ACL_LIST :
98                 screen = SCREEN_ACL_LIST;
99                 break;
100         case CCS_SCREEN_EXCEPTION_LIST :
101                 screen = SCREEN_EXCEPTION_LIST;
102                 break;
103         case CCS_SCREEN_PROFILE_LIST :
104                 screen = SCREEN_PROFILE_LIST;
105                 break;
106         case CCS_SCREEN_MANAGER_LIST :
107         default :
108                 screen = MAXSCREEN;
109                 break;
110         }
111
112         locate_index[screen] = index;
113 }
114
115 static gboolean search_pos_list(GtkTreeModel *model, GtkTreePath *path,
116                                 GtkTreeIter *iter, transition_t *transition)
117 {
118         GtkWidget               *view = NULL;
119         GtkTreeSelection        *selection;
120         gint                    index;
121         gchar                   *number = NULL;
122
123
124         switch((int)transition->current_page) {
125         case CCS_SCREEN_DOMAIN_LIST :
126                 if (transition->task_flag) {
127                         view = transition->tsk.treeview;
128                 } else {
129                         view = transition->treeview;
130                 }
131                 gtk_tree_model_get(model, iter, 0, &index, -1);
132                 break;
133         case CCS_SCREEN_ACL_LIST :
134                 view = transition->acl.listview;
135                 gtk_tree_model_get(model, iter, 0, &number, -1);
136                 index = atoi(number);
137                 break;
138         case CCS_SCREEN_EXCEPTION_LIST :
139                 view = transition->exp.listview;
140                 gtk_tree_model_get(model, iter, 0, &number, -1);
141                 index = atoi(number);
142                 break;
143         case CCS_SCREEN_PROFILE_LIST :
144                 view = transition->prf.listview;
145                 gtk_tree_model_get(model, iter, 0, &number, -1);
146                 index = atoi(number);
147                 break;
148         }
149         g_free(number);
150
151         if (index == get_locate_index(transition)) {
152                 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
153                 gtk_tree_selection_select_path(selection, path);
154                 view_cursor_set(view, gtk_tree_path_copy(path), NULL);
155                 return TRUE;
156         } else {
157                 return FALSE;
158         }
159 }
160
161 static gint get_list_count(transition_t *transition)
162 {
163         gint    count;
164
165         switch((int)transition->current_page) {
166         case CCS_SCREEN_DOMAIN_LIST :
167                 if (transition->task_flag) {
168                         count = transition->tsk.count;
169                 } else {
170                         count = transition->dp->list_len;
171                 }
172                 break;
173         case CCS_SCREEN_ACL_LIST :
174                 count = transition->acl.count;
175                 break;
176         case CCS_SCREEN_EXCEPTION_LIST :
177                 count = transition->exp.count;
178                 break;
179         case CCS_SCREEN_PROFILE_LIST :
180                 count = transition->prf.count;
181                 break;
182         case CCS_SCREEN_MANAGER_LIST :
183         default :
184                 count = -1;
185                 break;
186         }
187         return count;
188 }
189
190 static gint get_current_index(transition_t *transition)
191 {
192         gint    index;
193
194         switch((int)transition->current_page) {
195         case CCS_SCREEN_DOMAIN_LIST :
196                 if (transition->task_flag) {
197                         index = get_current_process_index(&(transition->tsk));
198                 } else {
199                         index = get_current_domain_index(transition);
200                 }
201                 break;
202         case CCS_SCREEN_ACL_LIST :
203                 index = select_list_line(&(transition->acl));
204                 break;
205         case CCS_SCREEN_EXCEPTION_LIST :
206                 index = select_list_line(&(transition->exp));
207                 break;
208         case CCS_SCREEN_PROFILE_LIST :
209                 index = select_list_line(&(transition->prf));
210                 break;
211         case CCS_SCREEN_MANAGER_LIST :
212         default :
213                 index = 0;
214                 break;
215         }
216         return index;
217 }
218
219 static void search(transition_t *transition, gboolean forward)
220 {
221         GtkWidget       *view = NULL;
222         gint            index, start_index, count;
223         gchar           *str_p = NULL;
224         gchar           *haystack = NULL;
225         gchar           *tmp_entry, *entry = NULL;
226         search_conf_t   conf;
227
228         if (!S_entry || strcmp(S_entry, "") == 0)
229                 return;
230
231         get_conf_search(&conf);
232
233         tmp_entry = encode_to_octal_str(S_entry);
234         entry = conf.match ? g_strdup(tmp_entry) : g_ascii_strup(tmp_entry, -1);
235         g_free(tmp_entry);
236
237         start_index = index = get_current_index(transition);
238         count = get_list_count(transition);
239         while (entry) {
240                 if (forward) {
241                         index++;
242                         if (count <= index) {
243                                 if (conf.wrap)
244                                         index = 0;
245                                 else
246                                         break;
247                         }
248                 } else {
249                         index--;
250                         if (index < 0) {
251                                 if (conf.wrap)
252                                         index = count - 1;
253                                 else
254                                         break;
255                         }
256                 }
257                 if (index == start_index)
258                         break;
259
260                 switch((int)transition->current_page) {
261                 case CCS_SCREEN_DOMAIN_LIST :
262                         if (transition->task_flag) {
263                                 view = transition->tsk.treeview;
264                                 str_p = transition->tsk.task[index].name;
265                         } else {
266                                 view = transition->treeview;
267                                 str_p = (gchar *)get_domain_last_name(index);
268                         }
269                         break;
270                 case CCS_SCREEN_ACL_LIST :
271                         view = transition->acl.listview;
272                         str_p = g_strdup_printf("%s %s",
273                                         ccs_directives[transition->acl.list
274                                                 [index].directive].alias,
275                                         transition->acl.list[index].operand);
276                         break;
277                 case CCS_SCREEN_EXCEPTION_LIST :
278                         view = transition->exp.listview;
279                         str_p = g_strdup_printf("%s %s",
280                                         ccs_directives[transition->exp.list
281                                                 [index].directive].alias,
282                                         transition->exp.list[index].operand);
283                         break;
284                 case CCS_SCREEN_PROFILE_LIST :
285                         view = transition->prf.listview;
286                         str_p = g_strdup_printf("%u-%s",
287                                           transition->prf.list[index].directive,
288                                           transition->prf.list[index].operand);
289                         break;
290                 case CCS_SCREEN_MANAGER_LIST :
291                 default :
292                         return;
293                         break;
294                 }
295
296                 g_free(haystack);
297                 haystack = conf.match ?
298                                 g_strdup(str_p) : g_ascii_strup(str_p, -1);
299
300                 if (transition->current_page != CCS_SCREEN_DOMAIN_LIST)
301                         g_free(str_p);
302
303                 if(g_strrstr(haystack, entry)) {
304                         GtkTreeModel    *model;
305                         put_locate_index(transition, index);
306                         model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
307                         gtk_tree_model_foreach(model,
308                           (GtkTreeModelForeachFunc)search_pos_list, transition);
309                         g_free(haystack);
310                         break;
311                 }
312         }
313
314         g_free(entry);
315
316         gtk_action_set_sensitive(gtk_action_group_get_action(
317                                 transition->actions, "SearchBack"), TRUE);
318         gtk_action_set_sensitive(gtk_action_group_get_action(
319                                 transition->actions, "SearchFoward"), TRUE);
320 }
321
322 /*-------+---------+---------+---------+---------+---------+---------+--------*/
323 static void cb_combo_changed(GtkComboBox *combobox, gpointer nothing)
324 {
325         GtkTreeModel    *model;
326         GtkTreeIter     iter;
327         gchar           *text;
328
329         model = gtk_combo_box_get_model(combobox);
330         if (gtk_combo_box_get_active_iter(combobox, &iter)) {
331                 gtk_tree_model_get(model, &iter, 0, &text, -1);
332                 g_free(S_entry);
333                 S_entry = text;
334 //              g_print("cb_combo_changed[%s]\n", text);
335         }
336 }
337
338 static void cb_search_entry_activate(GtkEntry *entry, search_t *srch)
339 {
340         GtkComboBox     *combobox;
341         gchar           *new_text;
342         GList           *list;
343         gboolean        exist_flag = FALSE;
344
345         combobox = GTK_COMBO_BOX(srch->combo);
346         new_text = gtk_combo_box_get_active_text(combobox);
347         if (!new_text || strcmp(new_text, "") == 0) {
348                 return;
349         }
350
351         g_free(S_entry);
352         S_entry = g_strdup(new_text);
353 //      g_print("cb_search_entry_activate[%s]\n", new_text);
354
355         for (list = combolist; list; list = g_list_next(list)) {
356                 if (strcmp(new_text, (gchar *)list->data) == 0) {
357                         exist_flag = TRUE;
358                         break;
359                 }
360         }
361
362         if (!exist_flag) {
363                 guint len;
364                 combolist = insert_item(combobox, combolist, new_text, 0);
365                 len = g_list_length(combolist);
366                 if (len > COMBO_LIST_LIMIT) {
367                         combolist = remove_item(combobox, combolist, len - 1);
368                 }
369         }
370
371         if (entry) {
372                 search_conf_t   conf;
373                 search(srch->tran, TRUE);
374                 get_conf_search(&conf);
375                 if (conf.close)
376                         gtk_dialog_response(GTK_DIALOG(srch->dialog),
377                                                         GTK_RESPONSE_CLOSE);
378         }
379 }
380
381 static void cb_btn_prev_clicked(GtkButton *widget , search_t *srch)
382 {
383         search_conf_t   conf;
384         cb_search_entry_activate(NULL, srch);
385         search(srch->tran, FALSE);
386         get_conf_search(&conf);
387         if (conf.close)
388                 gtk_dialog_response(GTK_DIALOG(srch->dialog),
389                                                         GTK_RESPONSE_CLOSE);
390 }
391
392 static void cb_btn_next_clicked(GtkButton *widget , search_t *srch)
393 {
394         search_conf_t   conf;
395         cb_search_entry_activate(NULL, srch);
396         search(srch->tran, TRUE);
397         get_conf_search(&conf);
398         if (conf.close)
399                 gtk_dialog_response(GTK_DIALOG(srch->dialog),
400                                                         GTK_RESPONSE_CLOSE);
401 }
402 /*-------+---------+---------+---------+---------+---------+---------+--------*/
403 GList *insert_item(GtkComboBox  *combobox,
404                         GList *cmblist, const gchar *item_label, gint index)
405 {
406         gtk_combo_box_insert_text(combobox, index, g_strdup(item_label));
407         return g_list_insert(cmblist, g_strdup(item_label), index);
408 }
409
410 GList *remove_item(GtkComboBox *combobox, GList *cmblist, gint index)
411 {
412         gtk_combo_box_remove_text(combobox, index);
413         g_free(g_list_nth_data(cmblist, index));
414         return g_list_delete_link(cmblist, g_list_nth(cmblist, index));
415 }
416
417 static gchar *search_title(transition_t *transition)
418 {
419         gchar           *title;
420
421         switch((int)transition->current_page) {
422         case CCS_SCREEN_DOMAIN_LIST :
423                 if (transition->task_flag) {
424                         title = _("Process Search for :");
425                 } else {
426                         title = _("Domain Search for :");
427                 }
428                 break;
429         case CCS_SCREEN_ACL_LIST :
430                 title = _("ACL Search for :");
431                 break;
432         case CCS_SCREEN_EXCEPTION_LIST :
433                 title = _("Exception Search for :");
434                 break;
435         case CCS_SCREEN_PROFILE_LIST :
436                 title = _("Profile Search for :");
437                 break;
438         case CCS_SCREEN_MANAGER_LIST :
439         default :
440                 title = _("Search for :");
441                 break;
442         }
443         return title;
444 }
445
446 static void cb_toggled_match(GtkToggleButton *widget, search_conf_t *conf)
447 {
448         conf->match = gtk_toggle_button_get_active(widget);
449         put_conf_search(conf);
450 }
451 static void cb_toggled_wrap(GtkToggleButton *widget, search_conf_t *conf)
452 {
453         conf->wrap = gtk_toggle_button_get_active(widget);
454         put_conf_search(conf);
455 }
456 static void cb_toggled_close(GtkToggleButton *widget, search_conf_t *conf)
457 {
458         conf->close = gtk_toggle_button_get_active(widget);
459         put_conf_search(conf);
460 }
461
462 static void create_check_box(GtkWidget *parent, search_conf_t *conf)
463 {
464         GtkWidget               *hbox, *vbox_l, *vbox_r;
465         GtkWidget               *match, *wrap, *close;
466
467         hbox = gtk_hbox_new(FALSE, 15);
468         gtk_box_pack_start(GTK_BOX(parent), hbox, TRUE, TRUE, 10);
469
470         vbox_l = gtk_vbox_new(FALSE, 5);
471         gtk_box_pack_start(GTK_BOX(hbox), vbox_l, TRUE, FALSE, 0);
472         vbox_r = gtk_vbox_new(FALSE, 5);
473         gtk_box_pack_start(GTK_BOX(hbox), vbox_r, TRUE, FALSE, 0);
474
475         match = gtk_check_button_new_with_mnemonic(_("_Match case"));
476         gtk_box_pack_start(GTK_BOX(vbox_l), match, TRUE, FALSE, 0);
477         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(match), conf->match);
478         g_signal_connect(G_OBJECT(match), "toggled",
479                                 G_CALLBACK(cb_toggled_match), conf);
480
481         wrap = gtk_check_button_new_with_mnemonic(_("_Wrap around"));
482         gtk_box_pack_start(GTK_BOX(vbox_l), wrap, TRUE, FALSE, 0);
483         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wrap), conf->wrap);
484         g_signal_connect(G_OBJECT(wrap), "toggled",
485                                         G_CALLBACK(cb_toggled_wrap), conf);
486
487         close = gtk_check_button_new_with_mnemonic(_("Close _dialog"));
488         gtk_box_pack_start(GTK_BOX(vbox_r), close, FALSE, FALSE, 0);
489         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(close), conf->close);
490         g_signal_connect(G_OBJECT(close), "toggled",
491                                         G_CALLBACK(cb_toggled_close), conf);
492
493 /*
494         大文字と小文字を区別する (M)atch case
495         折返しも対象にする (W)rap around
496         enterで閉じる Close (d)ialog
497 */
498 }
499
500 void search_input(GtkAction *action, transition_t *transition)
501 {
502         GtkWidget               *dialog, *parent;
503         GtkWidget               *hbox, *vbox_l, *vbox_r;
504         GtkWidget               *label;
505         GtkWidget               *entry;
506         GtkWidget               *btn_next, *btn_prev;
507         GList                   *list;
508         search_t                srch;
509         search_conf_t           conf;
510         gint                    response;
511
512         parent = (transition->acl_detached &&
513                 (int)transition->current_page == CCS_SCREEN_ACL_LIST) ?
514                         transition->acl_window : transition->window;
515
516         dialog = gtk_dialog_new_with_buttons(_("Find"),
517                         GTK_WINDOW(parent),
518                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
519                         GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
520                         NULL);
521
522         hbox = gtk_hbox_new(FALSE, 5);
523         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
524                                                 hbox, TRUE, TRUE, 0);
525         gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
526
527         vbox_l = gtk_vbox_new(FALSE, 5);
528         gtk_box_pack_start(GTK_BOX(hbox), vbox_l, TRUE, TRUE, 0);
529
530         label = gtk_label_new(NULL);
531         gtk_label_set_markup(GTK_LABEL(label), search_title(transition));
532         gtk_box_pack_start(GTK_BOX(vbox_l), label, FALSE, FALSE, 0);
533
534         entry = gtk_combo_box_entry_new_text();
535         srch.tran = transition;
536         srch.combo = entry;
537         srch.dialog = dialog;
538         g_signal_connect(G_OBJECT(entry) , "changed",
539                         G_CALLBACK(cb_combo_changed), NULL);
540         g_signal_connect(G_OBJECT(GTK_BIN(entry)->child) , "activate" ,
541                         G_CALLBACK(cb_search_entry_activate), &srch);
542         gtk_box_pack_start(GTK_BOX(vbox_l), entry, FALSE, FALSE, 0);
543
544         for (list = combolist; list; list = g_list_next(list)) {
545                 gtk_combo_box_append_text(
546                         GTK_COMBO_BOX(entry), (gchar *)list->data);
547         }
548         gtk_combo_box_set_active(GTK_COMBO_BOX(entry), 0);
549
550         get_conf_search(&conf);
551         create_check_box(vbox_l, &conf);
552
553         vbox_r = gtk_vbox_new(FALSE, 5);
554         gtk_box_pack_start(GTK_BOX(hbox), vbox_r, FALSE, FALSE, 0);
555
556         btn_prev = gtk_button_new_from_stock(GTK_STOCK_GO_BACK);
557         gtk_box_pack_start(GTK_BOX(vbox_r), btn_prev, TRUE, TRUE, 0);
558         g_signal_connect(G_OBJECT(btn_prev) , "clicked" ,
559                         G_CALLBACK (cb_btn_prev_clicked) , &srch);
560
561         btn_next = gtk_button_new_from_stock(GTK_STOCK_GO_FORWARD);
562         gtk_box_pack_start(GTK_BOX(vbox_r), btn_next, TRUE, TRUE, 0);
563         g_signal_connect(G_OBJECT(btn_next) , "clicked" ,
564                         G_CALLBACK (cb_btn_next_clicked) , &srch);
565
566         gtk_widget_set_size_request(dialog, 520, -1);
567         put_locate_index(transition, get_current_index(transition));
568         gtk_widget_show_all(dialog);
569
570         response = gtk_dialog_run(GTK_DIALOG(dialog));
571         gtk_widget_destroy(dialog);
572 }
573
574 void search_back(GtkAction *action, transition_t *transition)
575 {
576         search(transition, FALSE);
577 }
578
579 void search_forward(GtkAction *action, transition_t *transition)
580 {
581         search(transition, TRUE);
582 }
583 /*-------+---------+---------+---------+---------+---------+---------+--------*/