Statistics
| Revision:

root / src / prefs_actions.c @ 1

History | View | Annotate | Download (17.8 KB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2003 Hiroyuki Yamamoto & The Sylpheed Claws Team
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 */
19

    
20
#ifdef HAVE_CONFIG_H
21
#  include "config.h"
22
#endif
23

    
24
#include "defs.h"
25

    
26
#include <glib.h>
27
#include <gtk/gtk.h>
28
#include <gdk/gdkkeysyms.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include <errno.h>
33

    
34
#include "intl.h"
35
#include "prefs.h"
36
#include "inc.h"
37
#include "utils.h"
38
#include "gtkutils.h"
39
#include "manage_window.h"
40
#include "mainwindow.h"
41
#include "prefs_common.h"
42
#include "alertpanel.h"
43
#include "prefs_actions.h"
44
#include "action.h"
45

    
46
static struct Actions
47
{
48
        GtkWidget *window;
49

    
50
        GtkWidget *ok_btn;
51

    
52
        GtkWidget *name_entry;
53
        GtkWidget *cmd_entry;
54

    
55
        GtkWidget *actions_clist;
56
} actions;
57

    
58
/* widget creating functions */
59
static void prefs_actions_create        (MainWindow *mainwin);
60
static void prefs_actions_set_dialog        (void);
61
static gint prefs_actions_clist_set_row        (gint row);
62

    
63
/* callback functions */
64
static void prefs_actions_help_cb        (GtkWidget        *w,
65
                                         gpointer         data);
66
static void prefs_actions_register_cb        (GtkWidget        *w,
67
                                         gpointer         data);
68
static void prefs_actions_substitute_cb        (GtkWidget        *w,
69
                                         gpointer         data);
70
static void prefs_actions_delete_cb        (GtkWidget        *w,
71
                                         gpointer         data);
72
static void prefs_actions_up                (GtkWidget        *w,
73
                                         gpointer         data);
74
static void prefs_actions_down                (GtkWidget        *w,
75
                                         gpointer         data);
76
static void prefs_actions_select        (GtkCList        *clist,
77
                                         gint                 row,
78
                                         gint                 column,
79
                                         GdkEvent        *event);
80
static void prefs_actions_row_move        (GtkCList        *clist,
81
                                         gint                 source_row,
82
                                         gint                 dest_row);
83
static gint prefs_actions_deleted        (GtkWidget        *widget,
84
                                         GdkEventAny        *event,
85
                                         gpointer        *data);
86
static gboolean prefs_actions_key_pressed        (GtkWidget        *widget,
87
                                                 GdkEventKey        *event,
88
                                                 gpointer         data);
89
static void prefs_actions_cancel        (GtkWidget        *w,
90
                                         gpointer         data);
91
static void prefs_actions_ok                (GtkWidget        *w,
92
                                         gpointer         data);
93

    
94

    
95
void prefs_actions_open(MainWindow *mainwin)
96
{
97
        inc_lock();
98

    
99
        if (!actions.window)
100
                prefs_actions_create(mainwin);
101

    
102
        manage_window_set_transient(GTK_WINDOW(actions.window));
103
        gtk_widget_grab_focus(actions.ok_btn);
104

    
105
        prefs_actions_set_dialog();
106

    
107
        gtk_widget_show(actions.window);
108
}
109

    
110
static void prefs_actions_create(MainWindow *mainwin)
111
{
112
        GtkWidget *window;
113
        GtkWidget *vbox;
114
        GtkWidget *ok_btn;
115
        GtkWidget *cancel_btn;
116
        GtkWidget *confirm_area;
117

    
118
        GtkWidget *vbox1;
119

    
120
        GtkWidget *entry_vbox;
121
        GtkWidget *hbox;
122
        GtkWidget *name_label;
123
        GtkWidget *name_entry;
124
        GtkWidget *cmd_label;
125
        GtkWidget *cmd_entry;
126

    
127
        GtkWidget *reg_hbox;
128
        GtkWidget *btn_hbox;
129
        GtkWidget *arrow;
130
        GtkWidget *reg_btn;
131
        GtkWidget *subst_btn;
132
        GtkWidget *del_btn;
133

    
134
        GtkWidget *cond_hbox;
135
        GtkWidget *cond_scrolledwin;
136
        GtkWidget *cond_clist;
137

    
138
        GtkWidget *help_vbox;
139
        GtkWidget *help_label;
140
        GtkWidget *help_toggle;
141

    
142
        GtkWidget *btn_vbox;
143
        GtkWidget *up_btn;
144
        GtkWidget *down_btn;
145

    
146
        gchar *title[1];
147

    
148
        debug_print("Creating actions configuration window...\n");
149

    
150
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
151

    
152
        gtk_container_set_border_width(GTK_CONTAINER (window), 8);
153
        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
154
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);
155
        gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, TRUE);
156
        gtk_window_set_default_size(GTK_WINDOW(window), 400, -1);
157

    
158
        vbox = gtk_vbox_new(FALSE, 6);
159
        gtk_widget_show(vbox);
160
        gtk_container_add(GTK_CONTAINER(window), vbox);
161

    
162
        gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
163
                                &cancel_btn, _("Cancel"), NULL, NULL);
164
        gtk_widget_show(confirm_area);
165
        gtk_box_pack_end(GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
166
        gtk_widget_grab_default(ok_btn);
167

    
168
        gtk_window_set_title(GTK_WINDOW(window), _("Actions configuration"));
169
        g_signal_connect(G_OBJECT(window), "delete_event",
170
                         G_CALLBACK(prefs_actions_deleted), NULL);
171
        g_signal_connect(G_OBJECT(window), "key_press_event",
172
                         G_CALLBACK(prefs_actions_key_pressed), NULL);
173
        MANAGE_WINDOW_SIGNALS_CONNECT(window);
174
        g_signal_connect(G_OBJECT(ok_btn), "clicked",
175
                         G_CALLBACK(prefs_actions_ok), mainwin);
176
        g_signal_connect(G_OBJECT(cancel_btn), "clicked",
177
                         G_CALLBACK(prefs_actions_cancel), NULL);
178

    
179
        vbox1 = gtk_vbox_new(FALSE, 8);
180
        gtk_widget_show(vbox1);
181
        gtk_box_pack_start(GTK_BOX(vbox), vbox1, TRUE, TRUE, 0);
182
        gtk_container_set_border_width(GTK_CONTAINER(vbox1), 2);
183

    
184
        entry_vbox = gtk_vbox_new(FALSE, 4);
185
        gtk_box_pack_start(GTK_BOX(vbox1), entry_vbox, FALSE, FALSE, 0);
186

    
187
        hbox = gtk_hbox_new(FALSE, 8);
188
        gtk_box_pack_start(GTK_BOX(entry_vbox), hbox, FALSE, FALSE, 0);
189

    
190
        name_label = gtk_label_new(_("Menu name:"));
191
        gtk_box_pack_start(GTK_BOX(hbox), name_label, FALSE, FALSE, 0);
192

    
193
        name_entry = gtk_entry_new();
194
        gtk_box_pack_start(GTK_BOX(hbox), name_entry, TRUE, TRUE, 0);
195

    
196
        hbox = gtk_hbox_new(FALSE, 8);
197
        gtk_box_pack_start(GTK_BOX(entry_vbox), hbox, TRUE, TRUE, 0);
198

    
199
        cmd_label = gtk_label_new(_("Command line:"));
200
        gtk_box_pack_start(GTK_BOX(hbox), cmd_label, FALSE, FALSE, 0);
201

    
202
        cmd_entry = gtk_entry_new();
203
        gtk_box_pack_start(GTK_BOX(hbox), cmd_entry, TRUE, TRUE, 0);
204

    
205
        gtk_widget_show_all(entry_vbox);
206

    
207
        help_vbox = gtk_vbox_new(FALSE, 8);
208
        gtk_box_pack_start(GTK_BOX(vbox1), help_vbox, FALSE, FALSE, 0);
209

    
210
        help_label = gtk_label_new
211
                (_("Menu name:\n"
212
                   " Use / in menu name to make submenus.\n"
213
                   "Command line:\n"
214
                   " Begin with:\n"
215
                   "   | to send message body or selection to command\n"
216
                   "   > to send user provided text to command\n"
217
                   "   * to send user provided hidden text to command\n"
218
                   " End with:\n"
219
                   "   | to replace message body or selection with command output\n"
220
                   "   > to insert command's output without replacing old text\n"
221
                   "   & to run command asynchronously\n"
222
                   " Use:\n"
223
                   "   %f for message file name\n"
224
                   "   %F for the list of the file names of selected messages\n"
225
                   "   %p for the selected message part\n"
226
                   "   %u for a user provided argument\n"
227
                   "   %h for a user provided hidden argument\n"
228
                   "   %s for the text selection"));
229
        gtk_misc_set_alignment(GTK_MISC(help_label), 0, 0.5);
230
        gtk_label_set_justify(GTK_LABEL(help_label), GTK_JUSTIFY_LEFT);
231
        gtk_widget_show(help_label);
232
        gtk_box_pack_start(GTK_BOX(help_vbox), help_label, FALSE, FALSE, 0);
233
        gtk_widget_hide(help_vbox);
234

    
235
        /* register / substitute / delete */
236

    
237
        reg_hbox = gtk_hbox_new(FALSE, 4);
238
        gtk_widget_show(reg_hbox);
239
        gtk_box_pack_start(GTK_BOX(vbox1), reg_hbox, FALSE, FALSE, 0);
240

    
241
        arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
242
        gtk_widget_show(arrow);
243
        gtk_box_pack_start(GTK_BOX(reg_hbox), arrow, FALSE, FALSE, 0);
244
        gtk_widget_set_size_request(arrow, -1, 16);
245

    
246
        btn_hbox = gtk_hbox_new(TRUE, 4);
247
        gtk_widget_show(btn_hbox);
248
        gtk_box_pack_start(GTK_BOX(reg_hbox), btn_hbox, FALSE, FALSE, 0);
249

    
250
        reg_btn = gtk_button_new_with_label(_("Add"));
251
        gtk_widget_show(reg_btn);
252
        gtk_box_pack_start(GTK_BOX(btn_hbox), reg_btn, FALSE, TRUE, 0);
253
        g_signal_connect(G_OBJECT(reg_btn), "clicked",
254
                         G_CALLBACK(prefs_actions_register_cb), NULL);
255

    
256
        subst_btn = gtk_button_new_with_label(_(" Replace "));
257
        gtk_widget_show(subst_btn);
258
        gtk_box_pack_start(GTK_BOX(btn_hbox), subst_btn, FALSE, TRUE, 0);
259
        g_signal_connect(G_OBJECT(subst_btn), "clicked",
260
                         G_CALLBACK(prefs_actions_substitute_cb), NULL);
261

    
262
        del_btn = gtk_button_new_with_label(_("Delete"));
263
        gtk_widget_show(del_btn);
264
        gtk_box_pack_start(GTK_BOX(btn_hbox), del_btn, FALSE, TRUE, 0);
265
        g_signal_connect(G_OBJECT(del_btn), "clicked",
266
                         G_CALLBACK(prefs_actions_delete_cb), NULL);
267

    
268
        help_toggle = gtk_toggle_button_new_with_label(_(" Syntax help "));
269
        gtk_widget_show(help_toggle);
270
        gtk_box_pack_end(GTK_BOX(reg_hbox), help_toggle, FALSE, FALSE, 0);
271
        g_signal_connect(G_OBJECT(help_toggle), "toggled",
272
                         G_CALLBACK(prefs_actions_help_cb), help_vbox);
273

    
274
        cond_hbox = gtk_hbox_new(FALSE, 8);
275
        gtk_widget_show(cond_hbox);
276
        gtk_box_pack_start(GTK_BOX(vbox1), cond_hbox, TRUE, TRUE, 0);
277

    
278
        cond_scrolledwin = gtk_scrolled_window_new(NULL, NULL);
279
        gtk_widget_show(cond_scrolledwin);
280
        gtk_widget_set_size_request(cond_scrolledwin, -1, 150);
281
        gtk_box_pack_start(GTK_BOX(cond_hbox), cond_scrolledwin,
282
                           TRUE, TRUE, 0);
283
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (cond_scrolledwin),
284
                                       GTK_POLICY_AUTOMATIC,
285
                                       GTK_POLICY_AUTOMATIC);
286

    
287
        title[0] = _("Registered actions");
288
        cond_clist = gtk_clist_new_with_titles(1, title);
289
        gtk_widget_show(cond_clist);
290
        gtk_container_add(GTK_CONTAINER (cond_scrolledwin), cond_clist);
291
        gtk_clist_set_column_width(GTK_CLIST (cond_clist), 0, 80);
292
        gtk_clist_set_selection_mode(GTK_CLIST (cond_clist),
293
                                     GTK_SELECTION_BROWSE);
294
        GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(cond_clist)->column[0].button,
295
                               GTK_CAN_FOCUS);
296
        g_signal_connect(G_OBJECT(cond_clist), "select_row",
297
                         G_CALLBACK(prefs_actions_select), NULL);
298
        g_signal_connect_after(G_OBJECT(cond_clist), "row_move",
299
                               G_CALLBACK(prefs_actions_row_move), NULL);
300

    
301
        btn_vbox = gtk_vbox_new(FALSE, 8);
302
        gtk_widget_show(btn_vbox);
303
        gtk_box_pack_start(GTK_BOX(cond_hbox), btn_vbox, FALSE, FALSE, 0);
304

    
305
        up_btn = gtk_button_new_with_label(_("Up"));
306
        gtk_widget_show(up_btn);
307
        gtk_box_pack_start(GTK_BOX(btn_vbox), up_btn, FALSE, FALSE, 0);
308
        g_signal_connect(G_OBJECT(up_btn), "clicked",
309
                         G_CALLBACK(prefs_actions_up), NULL);
310

    
311
        down_btn = gtk_button_new_with_label(_("Down"));
312
        gtk_widget_show(down_btn);
313
        gtk_box_pack_start(GTK_BOX(btn_vbox), down_btn, FALSE, FALSE, 0);
314
        g_signal_connect(G_OBJECT(down_btn), "clicked",
315
                         G_CALLBACK(prefs_actions_down), NULL);
316

    
317
        gtk_widget_show(window);
318

    
319
        actions.window = window;
320
        actions.ok_btn = ok_btn;
321

    
322
        actions.name_entry = name_entry;
323
        actions.cmd_entry  = cmd_entry;
324

    
325
        actions.actions_clist = cond_clist;
326
}
327

    
328
static void prefs_actions_help_cb(GtkWidget *w, gpointer data)
329
{
330
        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
331
                gtk_widget_show(GTK_WIDGET(data));
332
        else
333
                gtk_widget_hide(GTK_WIDGET(data));
334
}
335

    
336
void prefs_actions_read_config(void)
337
{
338
        gchar *rcpath;
339
        FILE *fp;
340
        gchar buf[PREFSBUFSIZE];
341
        gchar *act;
342

    
343
        debug_print("Reading actions configurations...\n");
344

    
345
        rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, ACTIONS_RC, NULL);
346
        if ((fp = fopen(rcpath, "rb")) == NULL) {
347
                if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
348
                g_free(rcpath);
349
                return;
350
        }
351
        g_free(rcpath);
352

    
353
        while (prefs_common.actions_list != NULL) {
354
                act = (gchar *)prefs_common.actions_list->data;
355
                prefs_common.actions_list =
356
                        g_slist_remove(prefs_common.actions_list, act);
357
                g_free(act);
358
        }
359

    
360
        while (fgets(buf, sizeof(buf), fp) != NULL) {
361
                g_strchomp(buf);
362
                act = strstr(buf, ": ");
363
                if (act && act[2] && 
364
                    action_get_type(&act[2]) != ACTION_ERROR)
365
                        prefs_common.actions_list =
366
                                g_slist_append(prefs_common.actions_list,
367
                                               g_strdup(buf));
368
        }
369
        fclose(fp);
370
}
371

    
372
void prefs_actions_write_config(void)
373
{
374
        gchar *rcpath;
375
        PrefFile *pfile;
376
        GSList *cur;
377

    
378
        debug_print("Writing actions configuration...\n");
379

    
380
        rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, ACTIONS_RC, NULL);
381
        if ((pfile= prefs_file_open(rcpath)) == NULL) {
382
                g_warning("failed to write configuration to file\n");
383
                g_free(rcpath);
384
                return;
385
        }
386

    
387
        for (cur = prefs_common.actions_list; cur != NULL; cur = cur->next) {
388
                gchar *act = (gchar *)cur->data;
389
                if (fputs(act, pfile->fp) == EOF ||
390
                    fputc('\n', pfile->fp) == EOF) {
391
                        FILE_OP_ERROR(rcpath, "fputs || fputc");
392
                        prefs_file_close_revert(pfile);
393
                        g_free(rcpath);
394
                        return;
395
                }
396
        }
397
        
398
        g_free(rcpath);
399

    
400
        if (prefs_file_close(pfile) < 0) {
401
                g_warning("failed to write configuration to file\n");
402
                return;
403
        }
404
}
405

    
406
static void prefs_actions_set_dialog(void)
407
{
408
        GtkCList *clist = GTK_CLIST(actions.actions_clist);
409
        GSList *cur;
410
        gchar *action_str[1];
411
        gint row;
412

    
413
        gtk_clist_freeze(clist);
414
        gtk_clist_clear(clist);
415

    
416
        action_str[0] = _("(New)");
417
        row = gtk_clist_append(clist, action_str);
418
        gtk_clist_set_row_data(clist, row, NULL);
419

    
420
        for (cur = prefs_common.actions_list; cur != NULL; cur = cur->next) {
421
                gchar *action[1];
422

    
423
                action[0] = (gchar *)cur->data;
424
                row = gtk_clist_append(clist, action);
425
                gtk_clist_set_row_data(clist, row, action[0]);
426
        }
427

    
428
        gtk_clist_thaw(clist);
429
}
430

    
431
static void prefs_actions_set_list(void)
432
{
433
        gint row = 1;
434
        gchar *action;
435

    
436
        g_slist_free(prefs_common.actions_list);
437
        prefs_common.actions_list = NULL;
438

    
439
        while ((action = (gchar *)gtk_clist_get_row_data
440
                (GTK_CLIST(actions.actions_clist), row)) != NULL) {
441
                prefs_common.actions_list =
442
                        g_slist_append(prefs_common.actions_list, action);
443
                row++;
444
        }
445
}
446

    
447
#define GET_ENTRY(entry) \
448
        entry_text = gtk_entry_get_text(GTK_ENTRY(entry))
449

    
450
static gint prefs_actions_clist_set_row(gint row)
451
{
452
        GtkCList *clist = GTK_CLIST(actions.actions_clist);
453
        const gchar *entry_text;
454
        gint len;
455
        gchar action[PREFSBUFSIZE];
456
        gchar *buf[1];
457

    
458
        g_return_val_if_fail(row != 0, -1);
459

    
460
        GET_ENTRY(actions.name_entry);
461
        if (entry_text[0] == '\0') {
462
                alertpanel_error(_("Menu name is not set."));
463
                return -1;
464
        }
465

    
466
        if (strchr(entry_text, ':')) {
467
                alertpanel_error(_("Colon ':' is not allowed in the menu name."));
468
                return -1;
469
        }
470

    
471
        strncpy(action, entry_text, PREFSBUFSIZE - 1);
472
        g_strstrip(action);
473

    
474
        /* Keep space for the ': ' delimiter */
475
        len = strlen(action) + 2;
476
        if (len >= PREFSBUFSIZE - 1) {
477
                alertpanel_error(_("Menu name is too long."));
478
                return -1;
479
        }
480

    
481
        strcat(action, ": ");
482

    
483
        GET_ENTRY(actions.cmd_entry);
484

    
485
        if (entry_text[0] == '\0') {
486
                alertpanel_error(_("Command line not set."));
487
                return -1;
488
        }
489

    
490
        if (len + strlen(entry_text) >= PREFSBUFSIZE - 1) {
491
                alertpanel_error(_("Menu name and command are too long."));
492
                return -1;
493
        }
494

    
495
        if (action_get_type(entry_text) == ACTION_ERROR) {
496
                alertpanel_error(_("The command\n%s\nhas a syntax error."), 
497
                                 entry_text);
498
                return -1;
499
        }
500

    
501
        strcat(action, entry_text);
502

    
503
        buf[0] = action;
504
        if (row < 0)
505
                row = gtk_clist_append(clist, buf);
506
        else {
507
                gchar *old_action;
508
                gtk_clist_set_text(clist, row, 0, action);
509
                old_action = (gchar *) gtk_clist_get_row_data(clist, row);
510
                if (old_action)
511
                        g_free(old_action);
512
        }
513

    
514
        buf[0] = g_strdup(action);
515

    
516
        gtk_clist_set_row_data(clist, row, buf[0]);
517

    
518
        prefs_actions_set_list();
519

    
520
        return 0;
521
}
522

    
523
/* callback functions */
524

    
525
static void prefs_actions_register_cb(GtkWidget *w, gpointer data)
526
{
527
        prefs_actions_clist_set_row(-1);
528
}
529

    
530
static void prefs_actions_substitute_cb(GtkWidget *w, gpointer data)
531
{
532
        GtkCList *clist = GTK_CLIST(actions.actions_clist);
533
        gchar *action;
534
        gint row;
535

    
536
        if (!clist->selection) return;
537

    
538
        row = GPOINTER_TO_INT(clist->selection->data);
539
        if (row == 0) return;
540

    
541
        action = gtk_clist_get_row_data(clist, row);
542
        if (!action) return;
543

    
544
        prefs_actions_clist_set_row(row);
545
}
546

    
547
static void prefs_actions_delete_cb(GtkWidget *w, gpointer data)
548
{
549
        GtkCList *clist = GTK_CLIST(actions.actions_clist);
550
        gchar *action;
551
        gint row;
552

    
553
        if (!clist->selection) return;
554
        row = GPOINTER_TO_INT(clist->selection->data);
555
        if (row == 0) return;
556

    
557
        if (alertpanel(_("Delete action"),
558
                       _("Do you really want to delete this action?"),
559
                       _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
560
                return;
561

    
562
        action = gtk_clist_get_row_data(clist, row);
563
        g_free(action);
564
        gtk_clist_remove(clist, row);
565
        prefs_common.actions_list = g_slist_remove(prefs_common.actions_list,
566
                                                   action);
567
}
568

    
569
static void prefs_actions_up(GtkWidget *w, gpointer data)
570
{
571
        GtkCList *clist = GTK_CLIST(actions.actions_clist);
572
        gint row;
573

    
574
        if (!clist->selection) return;
575

    
576
        row = GPOINTER_TO_INT(clist->selection->data);
577
        if (row > 1)
578
                gtk_clist_row_move(clist, row, row - 1);
579
}
580

    
581
static void prefs_actions_down(GtkWidget *w, gpointer data)
582
{
583
        GtkCList *clist = GTK_CLIST(actions.actions_clist);
584
        gint row;
585

    
586
        if (!clist->selection) return;
587

    
588
        row = GPOINTER_TO_INT(clist->selection->data);
589
        if (row > 0 && row < clist->rows - 1)
590
                gtk_clist_row_move(clist, row, row + 1);
591
}
592

    
593
#define ENTRY_SET_TEXT(entry, str) \
594
        gtk_entry_set_text(GTK_ENTRY(entry), str ? str : "")
595

    
596
static void prefs_actions_select(GtkCList *clist, gint row, gint column,
597
                                 GdkEvent *event)
598
{
599
        gchar *action;
600
        gchar *cmd;
601
        gchar buf[PREFSBUFSIZE];
602
        action = gtk_clist_get_row_data(clist, row);
603

    
604
        if (!action) {
605
                ENTRY_SET_TEXT(actions.name_entry, "");
606
                ENTRY_SET_TEXT(actions.cmd_entry, "");
607
                return;
608
        }
609

    
610
        strncpy(buf, action, PREFSBUFSIZE - 1);
611
        buf[PREFSBUFSIZE - 1] = 0x00;
612
        cmd = strstr(buf, ": ");
613

    
614
        if (cmd && cmd[2])
615
                ENTRY_SET_TEXT(actions.cmd_entry, &cmd[2]);
616
        else
617
                return;
618

    
619
        *cmd = 0x00;
620
        ENTRY_SET_TEXT(actions.name_entry, buf);
621
}
622

    
623
static void prefs_actions_row_move(GtkCList *clist,
624
                                   gint source_row, gint dest_row)
625
{
626
        prefs_actions_set_list();
627
        if (gtk_clist_row_is_visible(clist, dest_row) != GTK_VISIBILITY_FULL) {
628
                gtk_clist_moveto(clist, dest_row, -1,
629
                                 source_row < dest_row ? 1.0 : 0.0, 0.0);
630
        }
631
}
632

    
633
static gint prefs_actions_deleted(GtkWidget *widget, GdkEventAny *event,
634
                                  gpointer *data)
635
{
636
        prefs_actions_cancel(widget, data);
637
        return TRUE;
638
}
639

    
640
static gboolean prefs_actions_key_pressed(GtkWidget *widget, GdkEventKey *event,
641
                                          gpointer data)
642
{
643
        if (event && event->keyval == GDK_Escape)
644
                prefs_actions_cancel(widget, data);
645
        return FALSE;
646
}
647

    
648
static void prefs_actions_cancel(GtkWidget *w, gpointer data)
649
{
650
        prefs_actions_read_config();
651
        gtk_widget_hide(actions.window);
652
        inc_unlock();
653
}
654

    
655
static void prefs_actions_ok(GtkWidget *widget, gpointer data)
656
{
657
        GtkItemFactory *ifactory;
658
        MainWindow *mainwin = (MainWindow *)data;
659

    
660
        prefs_actions_write_config();
661
        ifactory = gtk_item_factory_from_widget(mainwin->menubar);
662
        action_update_mainwin_menu(ifactory, mainwin);
663
        gtk_widget_hide(actions.window);
664
        inc_unlock();
665
}
666