utilunix.c(mc_tmpdir): Check return value of getpwuid() for NULL.
[midnight-commander.git] / src / panelize.c
blob44d22e7cfd22c4938512cef98b4c2f67876e00b8
1 /* External panelize
2 Copyright (C) 1995 The Free Software Foundation
4 Written by: 1995 Janne Kukonlehto
5 1995 Jakub Jelinek
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include <config.h>
23 #ifdef HAVE_UNISTD_H
24 # include <unistd.h>
25 #endif
26 #include <string.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
32 #include "global.h"
33 #include "tty.h" /* attrset() */
34 #include "win.h"
35 #include "color.h"
36 #include "dialog.h"
37 #include "widget.h"
38 #include "wtools.h" /* For common_dialog_repaint() */
39 #include "setup.h" /* For profile_bname */
40 #include "profile.h" /* Load/save directories panelize */
41 #include "dir.h"
42 #include "panel.h" /* current_panel */
43 #include "main.h" /* repaint_screen */
44 #include "panelize.h"
46 #define UX 5
47 #define UY 2
49 #define BX 5
50 #define BY 18
52 #define BUTTONS 4
53 #define LABELS 3
54 #define B_ADD B_USER
55 #define B_REMOVE (B_USER + 1)
57 static WListbox *l_panelize;
58 static Dlg_head *panelize_dlg;
59 static int last_listitem;
60 static WInput *pname;
62 static struct {
63 int ret_cmd, flags, y, x;
64 char *text;
65 } panelize_but [BUTTONS] = {
66 { B_CANCEL, NORMAL_BUTTON, 0, 53, N_("&Cancel") },
67 { B_ADD, NORMAL_BUTTON, 0, 28, N_("&Add new") },
68 { B_REMOVE, NORMAL_BUTTON, 0, 16, N_("&Remove") },
69 { B_ENTER, DEFPUSH_BUTTON, 0, 0, N_("Pane&lize") },
72 static char *panelize_section = "Panelize";
73 static void do_external_panelize (char *command);
75 /* Directory panelize */
76 static struct panelize {
77 char *command;
78 char *label;
79 struct panelize *next;
80 } *panelize = NULL;
82 static void
83 update_command (void)
85 if (l_panelize->pos != last_listitem) {
86 last_listitem = l_panelize->pos;
87 assign_text (pname,
88 ((struct panelize *) l_panelize->current->data)->command);
89 pname->point = 0;
90 update_input (pname, 1);
94 static cb_ret_t
95 panelize_callback (Dlg_head *h, dlg_msg_t msg, int parm)
97 switch (msg) {
98 case DLG_DRAW:
99 common_dialog_repaint (h);
100 attrset (COLOR_NORMAL);
101 draw_box (h, UY, UX, h->lines - 10, h->cols - 10);
102 return MSG_HANDLED;
104 case DLG_POST_KEY:
105 /* fall */
106 case DLG_INIT:
107 attrset (MENU_ENTRY_COLOR);
108 update_command ();
109 return MSG_HANDLED;
111 default:
112 return default_dlg_callback (h, msg, parm);
116 static void
117 init_panelize (void)
119 int i, panelize_cols = COLS - 6;
120 struct panelize *current = panelize;
122 #ifdef ENABLE_NLS
123 static int i18n_flag = 0;
124 static int maxlen = 0;
126 if (!i18n_flag) {
127 i = sizeof (panelize_but) / sizeof (panelize_but[0]);
128 while (i--) {
129 panelize_but[i].text = _(panelize_but[i].text);
130 maxlen += strlen (panelize_but[i].text) + 5;
132 maxlen += 10;
134 i18n_flag = 1;
136 panelize_cols = max (panelize_cols, maxlen);
138 panelize_but[2].x =
139 panelize_but[3].x + strlen (panelize_but[3].text) + 7;
140 panelize_but[1].x =
141 panelize_but[2].x + strlen (panelize_but[2].text) + 5;
142 panelize_but[0].x =
143 panelize_cols - strlen (panelize_but[0].text) - 8 - BX;
145 #endif /* ENABLE_NLS */
147 last_listitem = 0;
149 do_refresh ();
151 panelize_dlg =
152 create_dlg (0, 0, 22, panelize_cols, dialog_colors,
153 panelize_callback, "[External panelize]",
154 _("External panelize"), DLG_CENTER | DLG_REVERSE);
156 for (i = 0; i < BUTTONS; i++)
157 add_widget (panelize_dlg,
158 button_new (BY + panelize_but[i].y,
159 BX + panelize_but[i].x,
160 panelize_but[i].ret_cmd,
161 panelize_but[i].flags,
162 panelize_but[i].text, 0));
164 pname =
165 input_new (UY + 14, UX, INPUT_COLOR, panelize_dlg->cols - 10, "",
166 "in");
167 add_widget (panelize_dlg, pname);
169 add_widget (panelize_dlg, label_new (UY + 13, UX, _("Command")));
171 /* get new listbox */
172 l_panelize =
173 listbox_new (UY + 1, UX + 1, panelize_dlg->cols - 12, 10, NULL);
175 while (current) {
176 listbox_add_item (l_panelize, 0, 0, current->label, current);
177 current = current->next;
180 /* add listbox to the dialogs */
181 add_widget (panelize_dlg, l_panelize);
183 listbox_select_entry (l_panelize,
184 listbox_search_text (l_panelize,
185 _("Other command")));
188 static void panelize_done (void)
190 destroy_dlg (panelize_dlg);
191 repaint_screen ();
194 static void add2panelize (char *label, char *command)
196 struct panelize *current, *old;
198 old = NULL;
199 current = panelize;
200 while (current && strcmp (current->label, label) <= 0){
201 old = current;
202 current = current->next;
205 if (old == NULL){
206 panelize = g_new (struct panelize, 1);
207 panelize->label = label;
208 panelize->command = command;
209 panelize->next = current;
210 } else {
211 struct panelize *new;
212 new = g_new (struct panelize, 1);
213 new->label = label;
214 new->command = command;
215 old->next = new;
216 new->next = current;
220 static void
221 add2panelize_cmd (void)
223 char *label;
225 if (pname->buffer && (*pname->buffer)) {
226 label = input_dialog (_(" Add to external panelize "),
227 _(" Enter command label: "),
228 "");
229 if (!label)
230 return;
231 if (!*label) {
232 g_free (label);
233 return;
236 add2panelize (label, g_strdup (pname->buffer));
240 static void remove_from_panelize (struct panelize *entry)
242 if (strcmp (entry->label, _("Other command")) != 0) {
243 if (entry == panelize) {
244 panelize = panelize->next;
245 } else {
246 struct panelize *current = panelize;
247 while (current && current->next != entry)
248 current = current->next;
249 if (current) {
250 current->next = entry->next;
254 g_free (entry->label);
255 g_free (entry->command);
256 g_free (entry);
260 void
261 external_panelize (void)
263 char *target = NULL;
265 if (!vfs_current_is_local ()){
266 message (1, MSG_ERROR,
267 _(" Cannot run external panelize in a non-local directory "));
268 return;
271 init_panelize ();
273 /* display file info */
274 attrset (SELECTED_COLOR);
276 run_dlg (panelize_dlg);
278 switch (panelize_dlg->ret_value) {
279 case B_CANCEL:
280 break;
282 case B_ADD:
283 add2panelize_cmd ();
284 break;
286 case B_REMOVE:
287 remove_from_panelize (l_panelize->current->data);
288 break;
290 case B_ENTER:
291 target = pname->buffer;
292 if (target != NULL && *target) {
293 char *cmd = g_strdup (target);
294 destroy_dlg (panelize_dlg);
295 do_external_panelize (cmd);
296 g_free (cmd);
297 repaint_screen ();
298 return;
300 break;
303 panelize_done ();
306 void load_panelize (void)
308 void *profile_keys;
309 char *key, *value;
311 profile_keys = profile_init_iterator (panelize_section, profile_name);
313 add2panelize (g_strdup (_("Other command")), g_strdup (""));
315 if (!profile_keys){
316 add2panelize (g_strdup (_("Find rejects after patching")), g_strdup ("find . -name \\*.rej -print"));
317 add2panelize (g_strdup (_("Find *.orig after patching")), g_strdup ("find . -name \\*.orig -print"));
318 add2panelize (g_strdup (_("Find SUID and SGID programs")), g_strdup ("find . \\( \\( -perm -04000 -a -perm +011 \\) -o \\( -perm -02000 -a -perm +01 \\) \\) -print"));
319 return;
322 while (profile_keys){
323 profile_keys = profile_iterator_next (profile_keys, &key, &value);
324 add2panelize (g_strdup (key), g_strdup (value));
328 void save_panelize (void)
330 struct panelize *current = panelize;
332 profile_clean_section (panelize_section, profile_name);
333 for (;current; current = current->next){
334 if (strcmp (current->label, _("Other command")))
335 WritePrivateProfileString (panelize_section,
336 current->label,
337 current->command,
338 profile_name);
340 sync_profiles ();
343 void done_panelize (void)
345 struct panelize *current = panelize;
346 struct panelize *next;
348 for (; current; current = next){
349 next = current->next;
350 g_free (current->label);
351 g_free (current->command);
352 g_free (current);
356 static void do_external_panelize (char *command)
358 int status, link_to_dir, stale_link;
359 int next_free = 0;
360 struct stat st;
361 dir_list *list = &current_panel->dir;
362 char line [MC_MAXPATHLEN];
363 char *name;
364 FILE *external;
366 open_error_pipe ();
367 external = popen (command, "r");
368 if (!external){
369 close_error_pipe (1, _("Cannot invoke command."));
370 return;
372 /* Clear the counters and the directory list */
373 panel_clean_dir (current_panel);
375 while (1) {
376 clearerr(external);
377 if (fgets (line, MC_MAXPATHLEN, external) == NULL) {
378 if (ferror(external) && errno == EINTR)
379 continue;
380 else
381 break;
383 if (line[strlen(line)-1] == '\n')
384 line[strlen(line)-1] = 0;
385 if (strlen(line) < 1)
386 continue;
387 if (line [0] == '.' && line[1] == PATH_SEP)
388 name = line + 2;
389 else
390 name = line;
391 status = handle_path (list, name, &st, next_free, &link_to_dir,
392 &stale_link);
393 if (status == 0)
394 continue;
395 if (status == -1)
396 break;
397 list->list [next_free].fnamelen = strlen (name);
398 list->list [next_free].fname = g_strdup (name);
399 file_mark (current_panel, next_free, 0);
400 list->list [next_free].f.link_to_dir = link_to_dir;
401 list->list [next_free].f.stale_link = stale_link;
402 list->list [next_free].f.dir_size_computed = 0;
403 list->list [next_free].st = st;
404 next_free++;
405 if (!(next_free & 32))
406 rotate_dash ();
409 current_panel->is_panelized = 1;
410 if (next_free){
411 current_panel->count = next_free;
412 if (list->list [0].fname [0] == PATH_SEP){
413 strcpy (current_panel->cwd, PATH_SEP_STR);
414 chdir (PATH_SEP_STR);
416 } else {
417 current_panel->count = set_zero_dir (list);
419 if (pclose (external) < 0)
420 message (0, _("External panelize"), _("Pipe close failed"));
421 close_error_pipe (0, 0);
422 try_to_select (current_panel, NULL);
423 panel_re_sort (current_panel);