gentoo-0.20.7/0000775000175000017500000000000012730221005010066 500000000000000gentoo-0.20.7/gentoo.spec0000664000175000017500000000260612727751645012211 00000000000000%define name gentoo %define version 0.20.7 %define release 1 %define serial 2 Summary: gentoo is a graphical file management program Name: %{name} Version: %{version} Release: %{release} Serial: %{serial} Copyright: GPL Group: Applications/File URL: http://www.obsession.se/gentoo Vendor: Emil Brink Source: ftp://ftp.obsession.se/gentoo/%{name}-%{version}.tar.gz Requires: gtk+ >= 1.2.5 BuildRoot: %{_tmppath}/%{name}-%{version} %description gentoo is a modern, powerful, flexible, and utterly configurable file manager for UNIX systems, written using the GTK+ toolkit. It aims to be 100% graphically configurable; there's no need to edit config files by hand and then restart the application. gentoo is somewhat inspired in its look & feel by the classic Amiga program DirectoryOpus. %prep %setup -q %build %configure make %install [ "${RPM_BUILD_ROOT}" != "/" ] && [ -d ${RPM_BUILD_ROOT} ] && rm -rf ${RPM_BUILD_ROOT}; make DESTDIR=${RPM_BUILD_ROOT} install %clean [ "${RPM_BUILD_ROOT}" != "/" ] && [ -d ${RPM_BUILD_ROOT} ] && rm -rf ${RPM_BUILD_ROOT}; %files %defattr(-,root,root) %doc docs/* BUGS CONFIG-CHANGES CREDITS README* %config(noreplace) %{_sysconfdir}/gentoogtkrc %config(noreplace) %{_sysconfdir}/gentoorc %{_bindir}/gentoo %{_datadir}/gentoo %changelog * Tue Sep 11 2001 Ryan Weaver - Submitted patch to allow spec file generation in source. gentoo-0.20.7/src/0000775000175000017500000000000012730221005010655 500000000000000gentoo-0.20.7/src/cmd_configure.c0000644000175000017500000000276412310662641013565 00000000000000/* ** 1998-12-14 - A new module to pretty up the configuration-invocation, and also ** to implement a ConfigSave command. */ #include "gentoo.h" #include "cmdseq_config.h" #include "configure.h" #include "cmd_configure.h" /* ----------------------------------------------------------------------------------------- */ typedef struct { /* Options used by the "Configure" command. */ gboolean modified; gboolean auto_save; /* Automatic save, suppresses the dialog on quit. */ } OptConfigure; static OptConfigure configure_options; static CmdCfg *configure_cmc = NULL; /* 1998-12-14 - This is the classic "Configure" command, just given a standard prototype. */ gint cmd_configure(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca) { cfg_configure(min); return TRUE; } /* 1998-12-14 - This command causes the configuration to be saved. */ gint cmd_configuresave(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca) { cfg_save_all(min); return TRUE; } gboolean cmd_configure_autosave(void) { return configure_options.auto_save; } void cfg_configurecmd(MainInfo *min) { if(configure_cmc == NULL) { configure_options.auto_save = FALSE; configure_cmc = cmc_config_new("Configure", &configure_options); cmc_field_add_boolean(configure_cmc, "modified", NULL, offsetof(OptConfigure, modified)); cmc_field_add_boolean(configure_cmc, "auto_save", _("Automatically Save Changed Configuration on Exit?"), offsetof(OptConfigure, auto_save)); cmc_config_register(configure_cmc); } } gentoo-0.20.7/src/cmd_parent.h0000644000175000017500000000026112310662641013070 00000000000000/* ** 1998-05-25 - A very simple header file for the very simple PARENT command module. */ extern gint cmd_parent(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); gentoo-0.20.7/src/cmd_dpmisc.h0000644000175000017500000000122212310662641013054 00000000000000/* ** 1998-12-19 - Header for the DpHide command implementation. ** 1999-03-15 - Renamed when I added the recenter command. */ extern gint cmd_dphide(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); extern gint cmd_dprecenter(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); extern gint cmd_dpreorient(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); extern gint cmd_dpmaximize(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); extern gint cmd_dpgotorow(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); extern gint cmd_dpfocuspath(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); gentoo-0.20.7/src/cfg_styles.h0000644000175000017500000000041412310662641013116 00000000000000/* ** 1998-08-14 - Another one of those never-ending one-liner header files. The price you get ** to pay for putting everything in a module of its own, I guess... */ extern const CfgModule * cst_describe(MainInfo *min); extern StyleInfo * cst_get_styleinfo(void); gentoo-0.20.7/src/overwrite.h0000644000175000017500000000112512310662641013002 00000000000000/* ** 1998-09-17 - Header for the overwrite protection system. Sounds cool, eh? */ enum { OVWF_NO_RECURSE_TEST = 1 << 0 }; typedef enum { OVW_SKIP, OVW_PROCEED, OVW_PROCEED_FILE, OVW_PROCEED_DIR, OVW_CANCEL } OvwRes; extern void ovw_overwrite_begin(MainInfo *min, const gchar *desc, guint32 flags); extern OvwRes ovw_overwrite_file(MainInfo *min, const gchar *old_file, const gchar *new_file); extern OvwRes ovw_overwrite_unary_name(DirPane *dst, const gchar *dst_name); extern OvwRes ovw_overwrite_unary_file(DirPane *dst, const GFile *dst_file); extern void ovw_overwrite_end(MainInfo *min); gentoo-0.20.7/src/cmd_menupopup.h0000644000175000017500000000025412310662641013631 00000000000000/* ** 1999-06-12 - A little header for the menu popup command. Very early code. */ extern gint cmd_menupopup(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); gentoo-0.20.7/src/cmdarg.h0000644000175000017500000000310212310662641012206 00000000000000/* ** 1999-05-06 - Header for the built-in command argument parsing/handling module. */ #if !defined CMDARG_H #define CMDARG_H /* An opaque type that acts as a "handle" on the arguments given to a command. */ typedef struct CmdArg CmdArg; /* These are never called by individual command implementations, only by the ** main cmdseq command execution core. Gee, that sounded cool. :) */ extern CmdArg * car_create(gchar **argv); extern void car_destroy(CmdArg *ca); /* These are called by command implementations, to find out about the command ** argument keywords provided by the user. They all react very sanely to being ** called with a NULL argument. */ extern const gchar * car_keyword_get_value(const CmdArg *ca, const gchar *keyword, const gchar *default_value); extern gint car_keyword_get_integer(const CmdArg *ca, const gchar *keyword, gint default_value); extern gint car_keyword_get_enum(const CmdArg *ca, const gchar *keyword, gint default_value, ...); extern guint car_keyword_get_boolean(const CmdArg *ca, const gchar *keyword, guint default_value); /* These deal with the "bare" arguments, i.e. those that are NOT of the form ** keyword=value. Useful when a command needs a single "core" argument, that ** is not conceptually an option or modifier. */ extern guint car_bareword_get_amount(const CmdArg *ca); extern gboolean car_bareword_present(const CmdArg *ca, const gchar *word); extern const gchar * car_bareword_get(const CmdArg *ca, guint index); extern guint car_bareword_get_enum(const CmdArg *ca, guint index, guint default_value, ...); #endif /* CMDARG_H */ gentoo-0.20.7/src/cmd_run.h0000644000175000017500000000034512310662641012406 00000000000000/* ** 1998-09-12 - Header file for the run command module. */ extern gint cmd_run(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); extern gint cmd_rerun(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); gentoo-0.20.7/src/file.h0000644000175000017500000000020312310662641011667 00000000000000/* ** 1998-09-18 - Header file for the 'file' utility module. */ extern const gchar * fle_file(MainInfo *min, const gchar *name); gentoo-0.20.7/src/cmd_menupopup.c0000644000175000017500000000401712310662641013625 00000000000000/* ** 1999-06-12 - A simple command to show popup menu close the mouse pointer. Must be invoked ** by a command bound to a mouse button, since we need the triggering GdkEventButton ** handy. */ #include "gentoo.h" #include "cmdarg.h" #include "events.h" #include "menus.h" #include "cmd_menupopup.h" /* ----------------------------------------------------------------------------------------- */ #define CELL_SPACING 1 /* This is a private internal GtkCList constant. Oops. */ /* 2002-08-01 - This gets called if a "atfocus" bareword was present in the MenuPopup command. ** So, figure out where the focused row is, and fill in and suitably. This ** is kind of a hack, since it involves font computations that feel as if they ** should be inside GTK+, but... It might work. :) */ static void func_position(GtkMenu *menu, gint *x, gint *y, gboolean *push, gpointer data) { #if 0 MainInfo *min = data; GtkCList *cp = min->gui->cur_pane->view; gint wx, wy, px, py, pw, ph, fr; gdk_window_get_position(min->gui->window->window, &wx, &wy); gdk_window_get_position(GTK_WIDGET(cp)->window, &px, &py); gdk_window_get_size(GTK_WIDGET(cp)->window, &pw, &ph); *x = (wx + px) + pw / 2; *y = (wy + py) + ph / 2; #endif g_warning("Menu popup pane positioning not implemented"); } /* 2000-04-09 - Pop up the dirpane menu for the current pane. Now also works if bound to a ** (keyboard) key, as opposed to only working for mouse buttons as before. ** 2000-12-03 - Generality-boosted, through the new menu module. */ gint cmd_menupopup(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca) { GdkEventButton *evt; const gchar *name; guint button = 0; guint32 ac_time = 0U; GtkMenuPositionFunc pos = NULL; if((evt = (GdkEventButton *) evt_event_get(GDK_BUTTON_PRESS)) != NULL) { button = evt->button; ac_time = evt->time; } name = car_keyword_get_value(ca, "menu", "DirPaneMenu"); if(car_bareword_present(ca, "atfocus")) pos = func_position; return mnu_menu_popup(min->cfg.menus, name, pos, min, button, ac_time); } gentoo-0.20.7/src/cmd_dpfocusisrch.c0000644000175000017500000001312512310662641014271 00000000000000/* ** 2003-11-04 - Incremental search. Better late than never, right? */ #include #include #include #include "gentoo.h" #include "cmdseq.h" #include "dialog.h" #include "dirpane.h" #include "cmd_dpfocusisrch.h" /* ----------------------------------------------------------------------------------------- */ typedef struct { GtkWidget *hbox; /* Really should start with hbox. */ GtkWidget *label, *entry; } ISearchWidgetry; /* Various state, kept as a static global. Ugly, but simplifies things. */ static struct { DirPane *pane; /* Non-NULL during ISearch, NULL when not in use. */ guint page; MainInfo *min; char * (*search)(const char *haystack, const char *needle); gboolean offset_use; guint offset; gboolean select; ISearchWidgetry *wid; gulong sig_activate, sig_focus_out, sig_key_press; } the_isearch_info = { NULL }; /* ----------------------------------------------------------------------------------------- */ /* 2003-11-08 - Close down incremental search. Hides widgetry. */ static void isearch_close(void) { MainInfo *min = the_isearch_info.min; GtkWidget *entry = the_isearch_info.wid->entry; DirPane *pane = the_isearch_info.pane; /* Don't run if state seems invalid, close might already be in progress. */ if(pane != NULL) { g_signal_handler_disconnect(G_OBJECT(entry), the_isearch_info.sig_activate); g_signal_handler_disconnect(G_OBJECT(entry), the_isearch_info.sig_key_press); g_signal_handler_disconnect(G_OBJECT(entry), the_isearch_info.sig_focus_out); the_isearch_info.pane = NULL; /* Protect againsts against nesting. */ dp_pathwidgetry_show(pane, 0U); kbd_context_attach(min->gui->kbd_ctx, GTK_WINDOW(min->gui->window)); } } /* 2003-11-04 - Handle keypresses. Traps special keys for handy functionality. */ static gint evt_isearch_keypress(GtkWidget *wid, GdkEventKey *evt, gpointer user) { if(evt->keyval == GDK_KEY_Escape || (evt->keyval == GDK_KEY_g && (evt->state & GDK_CONTROL_MASK) != 0)) { isearch_close(); return TRUE; } return FALSE; } static gint evt_isearch_activate(GtkWidget *wid, gpointer user) { isearch_close(); return TRUE; } static gint evt_isearch_focus_out(GtkWidget *wid, GdkEventFocus *evt, gpointer user) { isearch_close(); return FALSE; } /* 2010-03-19 - Callback for the TreeView's search. Gets a column number passed in, but ignores that and always uses name. ** The return logic here is wack, which is why we're seemingly returning the inverse of what makes sense. ** We're hardcoded to always check for the display name, regardless of the 'column' GTK+ hands us. */ static gboolean cb_search_compare(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer user) { const gchar *dname = dp_row_get_name_display(model, (DirRow2*) iter); if(dname != NULL) { if(the_isearch_info.offset_use) { const gsize len = g_utf8_strlen(dname, -1); if(the_isearch_info.offset < len) dname = g_utf8_offset_to_pointer(dname, the_isearch_info.offset); else return TRUE; return !(strstr(dname, key) == dname); } return !(strstr(dname, key) != NULL); } return TRUE; } /* 2003-11-04 - Incremental search. Initial implementation, with a rather non-satisfying UI. */ gint cmd_dpfocusisrch(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca) { GtkWidget *entry; const gchar *text, *start; if(the_isearch_info.pane != NULL) return FALSE; kbd_context_detach(min->gui->kbd_ctx, GTK_WINDOW(min->gui->window)); the_isearch_info.pane = src; the_isearch_info.min = min; the_isearch_info.wid = (ISearchWidgetry *) dp_pathwidgetry_show(src, the_isearch_info.page); entry = the_isearch_info.wid->entry; gtk_widget_grab_focus(entry); gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(src->view), cb_search_compare, src, NULL); gtk_tree_view_set_search_column(GTK_TREE_VIEW(src->view), 0); gtk_tree_view_set_search_entry(GTK_TREE_VIEW(src->view), GTK_ENTRY(entry)); the_isearch_info.sig_activate = g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(evt_isearch_activate), NULL); the_isearch_info.sig_key_press = g_signal_connect(G_OBJECT(entry), "key_press_event", G_CALLBACK(evt_isearch_keypress), NULL); the_isearch_info.sig_focus_out = g_signal_connect(G_OBJECT(entry), "focus_out_event", G_CALLBACK(evt_isearch_focus_out), NULL); the_isearch_info.offset_use = FALSE; the_isearch_info.offset = 0; if((start = car_keyword_get_value(ca, "start", "0")) != NULL) { gchar *eptr; guint o; o = strtoul(start, &eptr, 0); if(eptr > start) { the_isearch_info.offset_use = TRUE; the_isearch_info.offset = (guint) o; } } the_isearch_info.select = car_keyword_get_boolean(ca, "select", FALSE); if((text = car_keyword_get_value(ca, "text", NULL)) != NULL) gtk_entry_set_text(GTK_ENTRY(entry), text); return TRUE; } /* ----------------------------------------------------------------------------------------- */ /* 2003-11-08 - Build dirpane path widgetry for incremental search. */ static GtkWidget ** widgetry_builder(MainInfo *min) { ISearchWidgetry *wid; wid = g_malloc(sizeof *wid); wid->hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); wid->label = gtk_label_new(_("ISearch")); gtk_box_pack_start(GTK_BOX(wid->hbox), wid->label, FALSE, FALSE, 5); wid->entry = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(wid->hbox), wid->entry, TRUE, TRUE, 0); return (GtkWidget **) wid; } /* 2003-11-08 - Configure DpFocusISrch. Does not add user-settable options, just registers ** a new pathwidgetry builder with the dirpane subsystem. Italian food. */ void cfg_dpfocusisrch(MainInfo *min) { the_isearch_info.page = dp_pathwidgetry_add(widgetry_builder); } gentoo-0.20.7/src/cmd_quit.c0000644000175000017500000000340712310662641012561 00000000000000/* ** 1998-10-21 - A little module to hold the quit commands. Purged them from the main ** gentoo.c module, in an effort to shrink it a little. ** 1999-05-07 - Slightly rewritten using the new command argument support. Removed ** the QuitNow command, use "Quit dialog=false" for the same effect. ** 1999-06-19 - Adapted for the new dialog module. ** 2000-03-04 - Modified for the new window handling. */ #include "gentoo.h" #include "dialog.h" #include "cmdarg.h" #include "cmdseq.h" #include "cmd_configure.h" #include "configure.h" #include "cmd_quit.h" /* ----------------------------------------------------------------------------------------- */ /* 1998-09-15 - Quit the program, but first check if there have been changes to the config. */ gint cmd_quit(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca) { guint dd, dialog = FALSE; if(win_window_update(min->gui->window)) cfg_modified_set(min); dd = (min->cfg.flags & CFLG_CHANGED) ? 2 : 0; dialog = car_keyword_get_boolean(ca, "dialog", dd); if(dialog == 2) { gint res; if(cmd_configure_autosave()) res = 1; else { res = dlg_dialog_sync_new_simple_wait(_("You may have some unsaved configuration changes.\n" "Quitting without saving will lose them. Really quit?"), _("Confirm Quitting"), _("_Quit|_Save, then Quit|_Cancel")); } if(res == -1) return TRUE; if(res == 1) csq_execute(min, "ConfigureSave"); else if(res == 2) return FALSE; } else if(dialog == 1) { if(dlg_dialog_sync_new_simple_wait(_("Are you sure you want to quit?"), _("Confirm Quitting"), NULL) != DLG_POSITIVE) return FALSE; } if(min->cfg.dp_history.save) dph_history_save(min, min->gui->pane, sizeof min->gui->pane / sizeof min->gui->pane[0]); gtk_main_quit(); return TRUE; } gentoo-0.20.7/src/cmd_moveas.h0000644000175000017500000000024612310662641013074 00000000000000/* ** 1998-09-12 - Header file for the native MOVEAS command implementation. */ extern gint cmd_moveas(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); gentoo-0.20.7/src/cfg_windows.c0000664000175000017500000001454512450070332013267 00000000000000/* ** 1998-10-15 - Config page for main window position and size. Neat. ** 2000-02-26 - This file has been pretty much entierly rewritten, and renamed. It now ** supports configuring position and size of not only the main window, but ** also the config and textview windows. Pretty neat. */ #include "gentoo.h" #include "dialog.h" #include "guiutil.h" #include "strutil.h" #include "cfg_module.h" #include "cfg_windows.h" #define NODE "Windows" /* ----------------------------------------------------------------------------------------- */ typedef struct { GtkWidget *vbox; /* Config page structures always begin like this. */ GtkWidget *content; /* Content built for us by the window module. */ GtkWidget *border[2]; /* Window border spin buttons. */ GtkWidget *dpos[3]; /* Dialog position mode radio buttons. */ MainInfo *min; gboolean modified; WinInfo *edit; /* Window info being edited. */ GtkWindowPosition dialog_pos; } P_Windows; static P_Windows the_page; /* ----------------------------------------------------------------------------------------- */ static void populate_page(P_Windows *page) { gint border[2], i; if(page->content) gtk_widget_destroy(page->content); page->content = win_wininfo_build(page->edit, &page->modified); gtk_box_pack_start(GTK_BOX(page->vbox), page->content, FALSE, FALSE, 0); gtk_widget_show_all(page->content); win_borders_get(page->edit, &border[0], &border[1]); for(i = 0; i < sizeof border / sizeof *border; i++) gtk_spin_button_set_value(GTK_SPIN_BUTTON(page->border[i]), border[i]); } /* ----------------------------------------------------------------------------------------- */ static void evt_border_changed(GtkWidget *wid, gpointer user) { P_Windows *page = user; gint w, h; w = gtk_spin_button_get_value(GTK_SPIN_BUTTON(page->border[0])); h = gtk_spin_button_get_value(GTK_SPIN_BUTTON(page->border[1])); win_borders_set(page->edit, w, h); page->modified = TRUE; } static void evt_dialog_position_toggled(GtkWidget *wid, gpointer user) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid))) { P_Windows *page = user; gint pos; pos = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(wid), "pos")); if(pos != page->dialog_pos) { page->dialog_pos = pos; page->modified = TRUE; } } } static GtkWidget * cwn_init(MainInfo *min, gchar **name) { P_Windows *page = &the_page; GtkWidget *hbox, *frame, *grid, *vbox; const gchar *blab[] = { N_("Horizontal"), N_("Vertical") }; const gchar *dlab[] = { N_("Dialog Windows Positioned by Window Manager"), N_("Dialog Windows Follow Mouse"), N_("Dialog Windows Center On Screen") }; GtkWindowPosition dpos[] = { GTK_WIN_POS_NONE, GTK_WIN_POS_MOUSE, GTK_WIN_POS_CENTER }; guint i; GSList *group = NULL; if(name == NULL) return NULL; *name = _("Windows"); page->edit = NULL; page->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); page->content = NULL; hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); frame = gtk_frame_new(_("Window Borders")); grid = gtk_grid_new(); for(i= 0; i < sizeof blab / sizeof *blab; i++) { GtkWidget *label; label = gtk_label_new(_(blab[i])); gtk_grid_attach(GTK_GRID(grid), label, 0, i, 1, 1); page->border[i] = gtk_spin_button_new_with_range(-32768, 32768, 1); gtk_widget_set_hexpand(page->border[i], TRUE); gtk_widget_set_halign(page->border[i], GTK_ALIGN_FILL); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(page->border[i]), 0); g_signal_connect(G_OBJECT(page->border[i]), "value_changed", G_CALLBACK(evt_border_changed), page); gtk_grid_attach(GTK_GRID(grid), page->border[i], 1, i, 1, 1); } gtk_container_add(GTK_CONTAINER(frame), grid); gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); frame = gtk_frame_new(_("Dialog Positioning")); vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); for(i = 0; i < sizeof dlab / sizeof *dlab; i++) { page->dpos[i] = gtk_radio_button_new_with_label(group, _(dlab[i])); g_object_set_data(G_OBJECT(page->dpos[i]), "pos", GINT_TO_POINTER(dpos[i])); g_signal_connect(G_OBJECT(page->dpos[i]), "toggled", G_CALLBACK(evt_dialog_position_toggled), page); if(dpos[i] == min->cfg.dialogs.pos) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->dpos[i]), TRUE); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(page->dpos[i])); gtk_box_pack_start(GTK_BOX(vbox), page->dpos[i], FALSE, FALSE, 0); } gtk_container_add(GTK_CONTAINER(frame), vbox); gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); gtk_box_pack_end(GTK_BOX(page->vbox), hbox, TRUE, FALSE, 5); gtk_widget_show_all(page->vbox); return page->vbox; } /* ----------------------------------------------------------------------------------------- */ /* 2000-01-30 - Update possize display. */ static void cwn_update(MainInfo *min) { P_Windows *page = &the_page; page->min = min; page->modified = FALSE; if(page->edit != NULL) win_wininfo_destroy(page->edit); page->edit = win_wininfo_copy(min->cfg.wininfo); page->dialog_pos = min->cfg.dialogs.pos; populate_page(page); } /* ----------------------------------------------------------------------------------------- */ static void cwn_accept(MainInfo *min) { P_Windows *page = &the_page; if(page->modified) { win_wininfo_destroy(min->cfg.wininfo); min->cfg.wininfo = page->edit; min->cfg.dialogs.pos = page->dialog_pos; dlg_position_set(min->cfg.dialogs.pos); page->edit = NULL; page->modified = FALSE; } } /* ----------------------------------------------------------------------------------------- */ static gboolean cwn_save(MainInfo *min, FILE *out) { win_wininfo_save(min->cfg.wininfo, out); return TRUE; } /* ----------------------------------------------------------------------------------------- */ static void cwn_load(MainInfo *min, const XmlNode *node) { win_wininfo_load(min->cfg.wininfo, node); } /* ----------------------------------------------------------------------------------------- */ /* 2000-02-26 - When the config window hides, we can free our editing copy if we (still) have one. */ static void cwn_hide(MainInfo *min) { P_Windows *page = &the_page; if(page->edit != NULL) { win_wininfo_destroy(page->edit); page->edit = NULL; } } /* ----------------------------------------------------------------------------------------- */ const CfgModule * cwn_describe(MainInfo *min) { static const CfgModule desc = { NODE, cwn_init, cwn_update, cwn_accept, cwn_save, cwn_load, cwn_hide }; return &desc; } gentoo-0.20.7/src/icon_dialog.c0000644000175000017500000001031012710361265013214 00000000000000/* ** 1999-05-24 - Broke this functionality out from the style configuration module since, er, ** I felt like it. Rewrote it in the process, too. :) Uses the sligtly more ** modern dialog module interface, thus returns directly the name of the icon ** that was selected (or NULL if user cancels). ** 1999-06-19 - Changes for the new dialog module. */ #include "gentoo.h" #include "iconutil.h" #include "guiutil.h" #include "strutil.h" #include "dialog.h" #include "icon_dialog.h" /* ----------------------------------------------------------------------------------------- */ /* Column indices in our list model. */ enum { COLUMN_ICON = 0, COLUMN_NAME }; /* 2008-07-29 - User double-clicked a row in the tree. Close the dialog. */ static void evt_row_activated(GtkWidget *wid, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user) { Dialog *dlg = user; dlg_dialog_sync_close(dlg, 0); } const gchar * idl_dialog_sync_new_wait(MainInfo *min, const gchar *path, const gchar *title, const gchar *current, gboolean show_progress) { static gchar retsel[1024]; GList *icons, *here; gboolean terminate = FALSE; gpointer progress = NULL; guint position, length; GtkWidget *scwin; GtkListStore *store; GtkWidget *view; GdkPixbuf *pixbuf; GtkTreeIter iter, *sel = NULL; gchar *selected = NULL; if(min == NULL) return NULL; if(title == NULL) title = _("Pick Icon"); if((icons = ico_get_all(min, path)) == NULL) return NULL; if(show_progress) { progress = gui_progress_begin(_("Loading Icon Graphics..."), _("Cancel")); length = g_list_length(icons); } /* Build a list model, to have somewhere to store the icons. */ store = gtk_list_store_new(2, GDK_TYPE_PIXBUF, G_TYPE_STRING); /* Load all icons. */ for(here = icons, position = 0U; here != NULL; here = g_list_next(here), position++) { if(progress != NULL) { if((terminate = gui_progress_update(progress, (gfloat) position / length, (gchar *) here->data))) break; } if(ico_no_icon(here->data)) continue; pixbuf = ico_icon_get_pixbuf(min, here->data); /* FIXME: Because of the way the icon-loader does caching, and how non-pixbuf loading * of an icon might already have been done, thus populating the cache with a non-pixbuf * entry, this doesn't filter for a NULL pixbuf. It's better to include all icons in * the list, for now. This will hopefully solve itself once panes go GtkTreeView. */ gtk_list_store_insert_with_values(store, &iter, -1, 0, pixbuf, 1, here->data, -1); if((current != NULL) && (strcmp(current, here->data) == 0) && sel == NULL) sel = gtk_tree_iter_copy(&iter); } if(progress != NULL) gui_progress_end(progress); if(!terminate) { GtkCellRenderer *cr; GtkTreeViewColumn *vc; GtkTreeSelection *ts; GtkTreeIter seliter; Dialog *dlg; view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); cr = gtk_cell_renderer_pixbuf_new(); vc = gtk_tree_view_column_new_with_attributes("(title)", cr, "pixbuf", COLUMN_ICON, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view), vc); cr = gtk_cell_renderer_text_new(); vc = gtk_tree_view_column_new_with_attributes("(title)", cr, "text", COLUMN_NAME, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view), vc); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); ts = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(sel != NULL && ts != NULL) { gtk_tree_selection_select_iter(ts, sel); gtk_tree_iter_free(sel); sel = NULL; } scwin = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scwin), view); dlg = dlg_dialog_sync_new(scwin, title, NULL); gtk_window_set_default_size(GTK_WINDOW(dlg_dialog_get_dialog(dlg)), 320, 544); g_signal_connect(G_OBJECT(view), "row_activated", G_CALLBACK(evt_row_activated), dlg); if(dlg_dialog_sync_wait(dlg) != DLG_POSITIVE) terminate = TRUE; if(gtk_tree_selection_get_selected(ts, NULL, &seliter)) gtk_tree_model_get(GTK_TREE_MODEL(store), &seliter, COLUMN_NAME, &selected, -1); dlg_dialog_sync_destroy(dlg); g_snprintf(retsel, sizeof retsel, "%s", selected); g_free(selected); } ico_free_all(icons); return terminate ? NULL : retsel; } gentoo-0.20.7/src/color_dialog.h0000644000175000017500000000057312310662641013417 00000000000000/* ** 1999-05-02 - Header for the little color dialog module. */ #if !defined COLOR_DIALOG_H #define COLOR_DIALOG_H #include #include "dialog.h" typedef void (*ColChangedFunc)(const GdkRGBA *color, gpointer user); extern gint cdl_dialog_sync_new_wait(const gchar *label, ColChangedFunc func, const GdkRGBA *initial, gpointer user); #endif /* COLOR_DIALOG_H */ gentoo-0.20.7/src/cmd_getsize.c0000644000175000017500000000752212310662641013253 00000000000000/* ** 1998-09-12 - This is GETSIZE, a recursive size computation command. It will assign ** the size of all contained files to directories. ** 1998-12-19 - Rewritten to use the new fut_dir_size() function, rather than its own ** routine. Simpler. ** 1999-03-06 - Adjusted for the new selection handling. ** 1999-04-09 - Added the cmd_clearsize() function, implementing the ClearSize command. */ #include "gentoo.h" #include #include "fileutil.h" #include "dirpane.h" #include "errors.h" #include "progress.h" #include "cmdseq_config.h" #include "cmd_getsize.h" #define CMD_ID "getsize" #define CMD_ID2 "clearsize" /* ----------------------------------------------------------------------------------------- */ typedef struct { gboolean modified; gboolean unselect; /* Unselect rows when done computing size? */ } OptGetSize; static OptGetSize getsize_options; static CmdCfg *getsize_cmc = NULL; /* ----------------------------------------------------------------------------------------- */ /* 1998-09-12 - Recursive directory sizer. ** 1999-04-09 - Now also updates the blocks field of the directory's stat buffer. */ gint cmd_getsize(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca) { GtkTreeModel *m = dp_get_tree_model(src); GSList *slist, *iter; guint num = 0; FUCount fuc; gboolean ok = TRUE; GError *err = NULL; if((slist = dp_get_selection(src)) == NULL) return 1; pgs_progress_begin(min, _("Getting sizes..."), PFLG_BUSY_MODE); for(iter = slist; ok && (iter != NULL); iter = g_slist_next(iter)) { if(dp_row_get_file_type(m, iter->data, TRUE) == G_FILE_TYPE_DIRECTORY) { GFile *here = dp_get_file_from_row(src, iter->data); if((ok = fut_size_gfile(min, here, NULL, &fuc, &err))) { dp_row_set_size(m, iter->data, fuc.num_bytes); dp_row_set_flag(m, iter->data, DPRF_HAS_SIZE); num++; if(getsize_options.unselect) dp_unselect(src, iter->data); } else err_set_gerror(min, &err, CMD_ID, here); } } pgs_progress_end(min); dp_free_selection(slist); if(num) { dp_update_stats(src); dp_show_stats(src); } return ok; } /* ----------------------------------------------------------------------------------------- */ /* 1999-04-09 - Clear the recursive sizes from all selected directories. Ignores files, but ** unselects them. */ gint cmd_clearsize(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca) { GtkTreeModel *m = dp_get_tree_model(src); GSList *slist, *iter; guint num = 0; GError *err = NULL; gboolean ok = TRUE; if((slist = dp_get_selection(src)) == NULL) return 1; for(iter = slist; ok && (iter != NULL); iter = g_slist_next(iter)) { if(dp_row_get_file_type(m, iter->data, TRUE) == G_FILE_TYPE_DIRECTORY && dp_row_get_flags(m, iter->data, DPRF_HAS_SIZE)) { /* Now, we need to re-scan the file's info, and replace it in the model. Interesting, but ** clearly a nitty job that needs to be done inside the dirpane module, not inline here. */ ok = dp_rescan_row(src, iter->data, &err); if(!ok) err_set_gerror(min, &err, CMD_ID2, dp_get_file_from_row(src, iter->data)); num++; } if(getsize_options.unselect) dp_unselect(src, iter->data); } dp_free_selection(slist); if(num) { dp_update_stats(src); dp_show_stats(src); } return ok; } /* ----------------------------------------------------------------------------------------- */ /* 1999-04-25 - Configure the GetSize command's (few) options. */ void cfg_getsize(MainInfo *min) { if(getsize_cmc == NULL) { getsize_options.modified = FALSE; getsize_options.unselect = TRUE; getsize_cmc = cmc_config_new("GetSize", &getsize_options); cmc_field_add_boolean(getsize_cmc, "modified", NULL, offsetof(OptGetSize, modified)); cmc_field_add_boolean(getsize_cmc, "unselect", _("Unselect Rows When Done?"), offsetof(OptGetSize, unselect)); cmc_config_register(getsize_cmc); } } gentoo-0.20.7/src/menus.c0000644000175000017500000004250712310662641012107 00000000000000/* ** General menu handling routines. This is the stuff made editable through ** the cfg_menus module. */ #include "gentoo.h" #include "cmdseq.h" #include "dialog.h" #include "dirpane.h" #include "fileutil.h" #include "guiutil.h" #include "strutil.h" #include "menus.h" /* ----------------------------------------------------------------------------------------- */ #define MENU_NONE _("(None)") #define MENU_ITEM_LABEL_SIZE 32 #define MENU_ITEM_ICON_SIZE 64 typedef enum { ITEM_SIMPLE, ITEM_SUBMENU, ITEM_SEPARATOR } MIType; typedef struct { gchar label[MENU_ITEM_LABEL_SIZE]; gchar icon[MENU_ITEM_ICON_SIZE]; } MILabel; struct item_simple { MILabel label; GString *cmdseq; }; struct item_submenu { MILabel label; gchar menu[MNU_MENU_NAME_SIZE]; }; struct MenuItem { MIType type; union { struct item_simple simple; struct item_submenu submenu; } data; }; typedef enum { MENU_NORMAL = 0, MENU_BUILTIN } MType; struct Menu { MType type; gchar name[MNU_MENU_NAME_SIZE]; GArray *item; gboolean used; /* Prevents re-use. Simplifies life. */ }; typedef struct { gchar name[MNU_MENU_NAME_SIZE]; void (*build)(MainInfo *min, GtkWidget *menu); } DynMenu; struct MenuInfo { MainInfo *min; GHashTable *menus; }; /* ----------------------------------------------------------------------------------------- */ static void menu_build_action(MainInfo *min, GtkWidget *wid); static void menu_build_time(MainInfo *min, GtkWidget *wid); static void menu_build_parents(MainInfo *min, GtkWidget *wid); static GHashTable *dynamic_hash = NULL; /* ----------------------------------------------------------------------------------------- */ void mnu_initialize(void) { static const DynMenu dyn_menu[] = { { "", menu_build_action }, { "", menu_build_time }, { "", menu_build_parents } }; guint i; dynamic_hash = g_hash_table_new(g_str_hash, g_str_equal); for(i = 0; i < sizeof dyn_menu / sizeof dyn_menu[0]; i++) g_hash_table_insert(dynamic_hash, (gpointer) dyn_menu[i].name, (gpointer) &dyn_menu[i]); } /* ----------------------------------------------------------------------------------------- */ Menu * mnu_menu_new(MenuInfo *mi, const gchar *name) { Menu *m; /* Discourage non-unique names. Firmly. */ if(g_hash_table_lookup(mi->menus, name) != NULL) return NULL; m = g_malloc(sizeof *m); g_strlcpy(m->name, name, sizeof m->name); m->item = g_array_new(FALSE, FALSE, sizeof (MenuItem)); m->used = FALSE; g_hash_table_insert(mi->menus, m->name, m); return m; } /* Destroy a menu. */ void mnu_menu_destroy(MenuInfo *mi, Menu *menu) { g_hash_table_remove(mi->menus, menu); g_array_free(menu->item, TRUE); g_free(menu); } static void menu_append(Menu *m, MenuItem *mi) { m->item = g_array_append_vals(m->item, mi, 1); } /* Create a new menu in , as an exact duplicate of (which ** _really_ should come from a different MenuInfo). */ static Menu * mnu_menu_new_copy(MenuInfo *mi, const Menu *old) { Menu *m; guint i; if((m = mnu_menu_new(mi, old->name)) == NULL) return m; for(i = 0; i < old->item->len; i++) menu_append(m, &g_array_index(old->item, MenuItem, i)); return m; } void mnu_menu_append_simple(Menu *m, const gchar *label, const gchar *cmdseq) { MenuItem mi; mi.type = ITEM_SIMPLE; g_strlcpy(mi.data.simple.label.label, label, sizeof mi.data.simple.label.label); mi.data.simple.label.icon[0] = '\0'; mi.data.simple.cmdseq = g_string_new(cmdseq); menu_append(m, &mi); } void mnu_menu_append_separator(Menu *m) { MenuItem mi; mi.type = ITEM_SEPARATOR; menu_append(m, &mi); } void mnu_menu_append_submenu(Menu *m, const gchar *label, const gchar *menu) { MenuItem mi; mi.type = ITEM_SUBMENU; g_strlcpy(mi.data.submenu.label.label, label, sizeof mi.data.submenu.label.label); mi.data.submenu.label.icon[0] = '\0'; g_strlcpy(mi.data.submenu.menu, menu, sizeof mi.data.submenu.menu); menu_append(m, &mi); } /* ----------------------------------------------------------------------------------------- */ /* 1999-08-26 - Just check if is on the list or not. We can't use g_slist_find(), ** since we need to do the comparison by textual content, not pointers. */ static gboolean action_on_list(GSList *actions, const gchar *action) { GSList *iter; for(iter = actions; iter != NULL; iter = g_slist_next(iter)) { if(strcmp(iter->data, action) == 0) return TRUE; } return FALSE; } /* 1999-08-26 - Check if is mentioned in each of the styles on (except ). ** Returns TRUE if so, FALSE if not. This routine really makes my performance-centered ** mind hurt. I guess I'll have to fix it someday. :) ** 2000-12-10 - Added quicker way to check if style has a named action property, so now it hurts less. */ static gboolean action_in_intersection(GSList *styles, GSList *current, const gchar *action) { const GSList *siter; for(siter = styles; siter != NULL; siter = g_slist_next(siter)) { if(siter == current) continue; if(!stl_style_property_has_action(siter->data, action)) return FALSE; } return TRUE; } /* 2000-12-03 - Dedicated activate-handler for items. Call the FileAction built-in. */ static void evt_menu_action_activate(GtkWidget *wid, gpointer user) { MainInfo *min; min = g_object_get_data(G_OBJECT(wid), "user"); csq_execute_format(min, "FileAction action='%s'", user); } /* 2000-12-03 - Build the Action submenu. It contains names of the actions available in ** all currently selected files in the current pane. */ static void menu_build_action(MainInfo *min, GtkWidget *menu) { DirPane *dp = min->gui->cur_pane; GSList *slist; if((slist = dp_get_selection(dp)) != NULL) { GSList *iter, *styles = NULL, *actions = NULL; GList *palist, *piter; GtkTreeModel *tm = dp_get_tree_model(dp); Style *stl; /* Build list of all styles used by rows in selection. */ for(iter = slist; iter != NULL; iter = g_slist_next(iter)) { const FType *ftype = dp_row_get_ftype(tm, iter->data); if(ftype != NULL) { stl = ftype->style; if(g_slist_find(styles, stl) == NULL) styles = g_slist_prepend(styles, stl); } } /* Compute intersection of all styles' action properties. */ for(iter = styles; iter != NULL; iter = g_slist_next(iter)) { palist = stl_style_property_get_actions(iter->data); for(piter = palist; piter != NULL; piter = g_list_next(piter)) { if(action_on_list(actions, piter->data)) continue; if(action_in_intersection(styles, iter, piter->data)) actions = g_slist_insert_sorted(actions, piter->data, (GCompareFunc) strcmp); } g_list_free(palist); } g_slist_free(styles); if(actions != NULL) { GtkWidget *item; for(iter = actions; iter != NULL; iter = g_slist_next(iter)) { item = gtk_menu_item_new_with_label(iter->data); g_object_set_data(G_OBJECT(item), "user", min); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(evt_menu_action_activate), iter->data); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); gtk_widget_show(item); } g_slist_free(actions); } dp_free_selection(slist); } else { GtkWidget *item; item = gtk_menu_item_new_with_label(_("(No Selection)")); gtk_widget_set_sensitive(item, FALSE); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); gtk_widget_show(item); } } /* 2000-12-03 - Create a menu with a single item, whose label shows the current ** local time, in 24-hour HH:MM.SS format. Initially created just to ** test the dynamic submenu handling, but I think I'll keep it. ;) ** Selecting the item does nothing. */ static void menu_build_time(MainInfo *min, GtkWidget *menu) { gchar buf[16]; time_t now; struct tm *nowf; GtkWidget *item; time(&now); nowf = localtime(&now); strftime(buf, sizeof buf, "%H:%M.%S", nowf); item = gtk_menu_item_new_with_label(buf); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); gtk_widget_show(item); } /* 2004-04-18 - User picked an item from the menu. Go there. */ static void evt_menu_parents_activate(GtkWidget *wid, gpointer user) { const gchar *text = NULL; if(!GTK_IS_MENU_ITEM(wid)) return; wid = gtk_bin_get_child(GTK_BIN(wid)); if(!GTK_IS_LABEL(wid)) return; text = gtk_label_get_text(GTK_LABEL(wid)); if(text != NULL) csq_execute_format(user, "DirEnter 'dir=%s'", stu_escape(text)); } /* 2004-04-18 - Build menu containing parent directories of current pane's dir. */ static void menu_build_parents(MainInfo *min, GtkWidget *menu) { const DirPane *dp = min->gui->cur_pane; gchar canon[PATH_MAX], *sep; GtkWidget *item; if(dp == NULL) return; fut_path_canonicalize(dp->dir.path, canon, sizeof canon); while((sep = strrchr(canon, G_DIR_SEPARATOR)) != NULL) { *sep = '\0'; if(canon[0] == '\0') break; item = gtk_menu_item_new_with_label(canon); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(evt_menu_parents_activate), min); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); } /* Always append a root ("/") item, since the root has itself as its parent. Avoids empty menu, as bonus. */ item = gtk_menu_item_new_with_label("/"); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(evt_menu_parents_activate), min); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); gtk_widget_show_all(menu); } /* ----------------------------------------------------------------------------------------- */ /* The standard callback for a menu item; just run the attached command. */ static void evt_menu_activate(GtkWidget *wid, gpointer user) { MainInfo *min; min = g_object_get_data(G_OBJECT(wid), "user"); csq_execute(min, user); } static void evt_menu_show(GtkWidget *wid, gpointer user) { DynMenu *dm = user; dm->build(g_object_get_data(G_OBJECT(wid), "user"), wid); } static void evt_menu_hide(GtkWidget *wid, gpointer user) { GList *list, *iter; for(iter = list = gtk_container_get_children(GTK_CONTAINER(wid)); iter != NULL; iter = g_list_next(iter)) gtk_container_remove(GTK_CONTAINER(wid), iter->data); g_list_free(list); } static GtkWidget * do_menu_widget_build(const MenuInfo *mi, const gchar *name, Menu *parent) { DynMenu *d; Menu *m; GtkWidget *menu, *menuitem, *smenu; guint i; MenuItem *mit; if(!name) return NULL; /* Dynamic menus are empty, and filled-in on demand in the "show" signal handler. ** This isn't the most pleasing solution performance-wise, but it's still rather ** elegant, IMO. The "hide" handler empties the menu again. */ if((d = g_hash_table_lookup(dynamic_hash, name)) != NULL) { menu = gtk_menu_new(); g_object_set_data(G_OBJECT(menu), "user", mi->min); g_signal_connect(G_OBJECT(menu), "show", G_CALLBACK(evt_menu_show), d); g_signal_connect(G_OBJECT(menu), "hide", G_CALLBACK(evt_menu_hide), d); return menu; } if((m = g_hash_table_lookup(mi->menus, name)) == NULL) return NULL; menu = gtk_menu_new(); for(i = 0; i < m->item->len; i++) { mit = &g_array_index(m->item, MenuItem, i); switch(mit->type) { case ITEM_SIMPLE: menuitem = gtk_menu_item_new_with_label(mit->data.simple.label.label); g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(evt_menu_activate), mit->data.simple.cmdseq->str); g_object_set_data(G_OBJECT(menuitem), "user", mi->min); break; case ITEM_SEPARATOR: menuitem = gtk_menu_item_new(); break; case ITEM_SUBMENU: if((smenu = do_menu_widget_build(mi, mit->data.submenu.menu, m)) != NULL) { menuitem = gtk_menu_item_new_with_label(mit->data.submenu.label.label); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), smenu); } else menuitem = NULL; break; default: menuitem = NULL; } if(menuitem) { gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); gtk_widget_show(menuitem); } } return menu; } /* Get a GTK+ menu representing the named menu. Dynamic content is not generated ** at this point; it is set up (using the "show" and "hide" signals) to be generated ** when (if) needed. */ GtkWidget * mnu_menu_widget_get(const MenuInfo *mi, const gchar *name) { return do_menu_widget_build(mi, name, NULL); } GtkWidget * mnu_menu_use(const MenuInfo *mi, const gchar *name) { return do_menu_widget_build(mi, name, NULL); } void mnu_menu_disuse(const MenuInfo *mi, const gchar *name) { Menu *m; if((m = g_hash_table_lookup(mi->menus, name)) == NULL) return; m->used = FALSE; } /* ----------------------------------------------------------------------------------------- */ static gboolean evt_popup_destroy(GtkWidget *wid, GdkEvent *evt, gpointer user) { gui_events_flush(); return FALSE; } static void evt_popup_hide(GtkWidget *wid, gpointer user) { gboolean ret; gui_events_flush(); g_signal_emit_by_name(G_OBJECT(wid), "destroy_event", NULL, &ret); } gboolean mnu_menu_popup(const MenuInfo *mi, const gchar *name, GtkMenuPositionFunc pos, gpointer data, guint button, guint32 activate_time) { GtkWidget *menu; if((menu = mnu_menu_widget_get(mi, name)) != NULL) { g_signal_connect_after(G_OBJECT(menu), "hide", G_CALLBACK(evt_popup_hide), NULL); g_signal_connect(G_OBJECT(menu), "destroy_event", G_CALLBACK(evt_popup_destroy), NULL); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, pos, data, button, activate_time); /* fprintf(stderr, "Popping up menu at %p\n", menu);*/ } return menu != NULL; } /* ----------------------------------------------------------------------------------------- */ MenuInfo * mnu_menuinfo_new(MainInfo *min) { MenuInfo *mi; mi = g_malloc(sizeof *mi); mi->min = min; mi->menus = g_hash_table_new(g_str_hash, g_str_equal); return mi; } MenuInfo * mnu_menuinfo_new_default(MainInfo *min) { MenuInfo *mi; Menu *menu; mi = mnu_menuinfo_new(min); menu = mnu_menu_new(mi, "SelectMenu"); mnu_menu_append_simple(menu, _("All"), "SelectAll"); mnu_menu_append_simple(menu, _("None"), "SelectNone"); mnu_menu_append_simple(menu, _("Toggle"), "SelectToggle"); mnu_menu_append_simple(menu, _("RegExp..."), "SelectRE"); /* menu = mnu_menu_new(mi, "PointlessComplexityMenu"); mnu_menu_append_submenu(menu, "Action2", ""); mnu_menu_append_submenu(menu, "Action2", ""); mnu_menu_append_submenu(menu, "Action2", ""); mnu_menu_append_submenu(menu, "Action2", ""); mnu_menu_append_submenu(menu, "Action2", ""); mnu_menu_append_submenu(menu, "Action2", ""); */ menu = mnu_menu_new(mi, "DirPaneMenu"); mnu_menu_append_simple(menu, _("Parent"), "DirParent"); mnu_menu_append_simple(menu, _("Other"), "DirFromOther"); mnu_menu_append_simple(menu, _("Rescan"), "DirRescan"); mnu_menu_append_submenu(menu, _("Select"), "SelectMenu"); mnu_menu_append_separator(menu); mnu_menu_append_submenu(menu, _("Action"), ""); /* mnu_menu_append_submenu(menu, "Time", "");*/ mnu_menu_append_simple(menu, _("Run..."), "Run"); mnu_menu_append_separator(menu); mnu_menu_append_simple(menu, _("Configure..."), "Configure"); /* mnu_menu_append_submenu(menu, "Pointless", "PointlessComplexityMenu");*/ /* menu = mnu_menu_new(mi, "ShortcutMenu"); mnu_menu_append_simple(menu, "Home", "DirEnter ~"); mnu_menu_append_simple(menu, "Local", "DirEnter /usr/local"); mnu_menu_append_simple(menu, "/", "DirEnter /"); */ return mi; } static void copy_menu(gpointer key, gpointer value, gpointer user) { mnu_menu_new_copy(user, value); } MenuInfo * mnu_menuinfo_copy(const MenuInfo *mi) { MenuInfo *nmi; nmi = mnu_menuinfo_new(mi->min); g_hash_table_foreach(mi->menus, copy_menu, nmi); return nmi; } #if 0 static void append_menu(gpointer key, gpointer value, gpointer user) { GList **list = user; Menu *m = value; if(m->used) return; *list = g_list_insert_sorted(*list, m->name, (GCompareFunc) strcmp); } static void evt_select_select_row(GtkWidget *wid, gint row, gint col, GdkEventButton *evt, gpointer user) { gchar **selected = user; *selected = gtk_clist_get_row_data(GTK_CLIST(wid), row); } static void evt_select_unselect_row(GtkWidget *wid, gint row, gint col, GdkEventButton *evt, gpointer user) { gchar **selected = user; *selected = NULL; } /* 2001-01-01 - Pop up dialog, let user pick a non-used menu. */ const gchar * mnu_menuinfo_select(const MenuInfo *mi) { GList *list = NULL, *iter; GtkWidget *scwin, *clist; gchar *row[] = { NULL }, *selected = NULL; gint ri, choice; Dialog *dlg; list = g_list_append(list, MENU_NONE); g_hash_table_foreach(mi->menus, append_menu, &list); scwin = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); clist = gtk_clist_new(1); for(iter = list; iter != NULL; iter = g_list_next(iter)) { row[0] = iter->data; ri = gtk_clist_append(GTK_CLIST(clist), row); gtk_clist_set_row_data(GTK_CLIST(clist), ri, row[0]); } g_signal_connect(G_OBJECT(clist), "select_row", G_CALLBACK(evt_select_select_row), &selected); g_signal_connect(G_OBJECT(clist), "unselect_row", G_CALLBACK(evt_select_unselect_row), &selected); gtk_container_add(GTK_CONTAINER(scwin), clist); gtk_widget_set_size_request(scwin, 200, 384); dlg = dlg_dialog_sync_new(scwin, _("Select Menu"), NULL); choice = dlg_dialog_sync_wait(dlg); dlg_dialog_sync_destroy(dlg); g_list_free(list); return choice == 0 ? (selected ? selected : MENU_NONE) : NULL; } #endif static void destroy_menu(gpointer key, gpointer value, gpointer user) { /* printf("Destroying menu \"%s\"\n", ((Menu *) value)->name);*/ mnu_menu_destroy(user, value); } void mnu_menuinfo_destroy(MenuInfo *mi) { g_hash_table_foreach(mi->menus, destroy_menu, mi); g_free(mi); } gentoo-0.20.7/src/mntent_wrap.h0000644000175000017500000000406712310662641013322 00000000000000/* ** 1999-01-27 - Wrapper around the mntent API functions. These are used to parse system ** databases holding information about filesystems that can be mounted, and ** that are mounted. Needs to be wrapped since it seems to differ wildly ** between various OSs (e.g. between Linux and Solaris). */ #if !defined GENTOO_MNTENT_H #define GENTOO_MNTENT_H #include /* Contains (at least) one (device,mountpoint) pair. Opaque, use accessor functions ** declared below to manipulate. */ typedef struct MntEnt MntEnt; /* The following three calls need platform-specific implementations. ----------------------- */ /* Open database file. Some platforms might ignore the . If a FILE * is not ** the most handy datatype for your platform, feel free to return some other pointer. ** Hm, this should probably be rewritten to use a gpointer instead of a FILE pointer... */ FILE * mne_setmntent(const gchar *filename); /* Get next mount entry from file. Returns NULL if there are no more entries available. ** The entry returned is strictly read-only, and lives in static memory, so it will change ** with the next (successful) call. To keep it, use mne_copy() to create a copy of it. */ const MntEnt * mne_getmntent(FILE *filep); /* Call this when you're done scanning the database, to close it down properly. */ gint mne_endmntent(FILE *filep); /* The rest of the calls are platform-neutral. --------------------------------------------- */ /* Create a copy of , in dynamically allocated memory. Returns a pointer to ** the copy, or NULL on failure. The copy shares no memory with the original. */ MntEnt * mne_copy(const MntEnt *src); /* Destroy a MntEnt, freeing all memory used by it. Only valid on entries created ** by mne_copy(). */ void mne_destroy(MntEnt *me); /* Return a pointer to a string containing the mountpoint path for the given entry (e.g. "/cdrom"). */ const gchar * mne_get_mountpoint(const MntEnt *me); /* Return pointer to a string with device name for given mount entry (e.g. "/dev/hdc"). */ const gchar * mne_get_device(const MntEnt *me); #endif gentoo-0.20.7/src/cmdgrab.h0000644000175000017500000000025412310662641012355 00000000000000/* ** 1998-09-26 - Header file for the output-grabbing module. */ extern gboolean cgr_grab_output(MainInfo *min, const gchar *prog, GPid child, gint fd_out, gint fd_err); gentoo-0.20.7/src/icon_dialog.h0000644000175000017500000000033212310662641013222 00000000000000/* ** 1999-05-24 - Another highly specialized dialog module. */ extern const gchar * idl_dialog_sync_new_wait(MainInfo *min, const gchar *path, const gchar *title, const gchar *current, gboolean show_progress); gentoo-0.20.7/src/cmd_direnter.h0000644000175000017500000000023512310662641013414 00000000000000/* ** 1998-09-02 - Header for the (pretty cool) command DirEnter. */ extern gint cmd_direnter(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); gentoo-0.20.7/src/gentoo.h0000664000175000017500000004375512705403464012274 00000000000000/* ** This is the main header file for gentoo. Most source files will include this header, ** since it declares many of the data types that are used. When including this header, ** it should always be the first included file. The preferred order of inclusion is: ** #include "gentoo.h" ** #include (e.g. , , ...) ** #include "more gentoo stuff" (e.g. "fileutil.h", "xmlutil.h", ...) ** #include "me.h" (for a module named "me.c", that is). ** ** The reason why this file should be the first included one is that it fixes some ** system-dependent things which need to go before any system headers are included. */ #include "config.h" #if !(defined __osf__ && defined __alpha__) && !defined __NetBSD__ && !defined __FreeBSD__ && !defined __sgi #if !defined __EXTENSIONS__ #define __EXTENSIONS__ #endif #if !defined _POSIX_C_SOURCE #define _POSIX_C_SOURCE 3 /* This is for Solaris. */ #endif #define POSIX_C_SOURCE 3 #endif /* !__osf__ && !__alpha */ #if defined __osf__ && defined __alpha__ /* On Tru64, this should bring in mknod(). */ #define _XOPEN_SOURCE_EXTENDED #define _OSF_SOURCE /* For MAXNAMLEN on Tru64. */ #endif #if !defined _BSD_SOURCE #define _BSD_SOURCE /* For MAXNAMLEN on Linux. */ #endif #include #include #include #include #include #include #include #include #include #include #include #include #include /* The various BSDs seem to have a lot in common. Let's try and use that, ** and save some typing in various tests below. This should probably all ** be replaced by proper Autoconfed stuff at some point. */ #if defined __OpenBSD__ || defined __FreeBSD__ || defined __NetBSD__ #define GENTOO_ON_BSD #endif /* BSD-specific mounting stuff. */ #if defined GENTOO_ON_BSD #include #include #endif #undef GTK_ENABLE_BROKEN /* We can't use autoconf to undefine symbols. */ #include #include #include /* Fix for < Glib 2.20. */ #ifndef G_GOFFSET_FORMAT #define G_GOFFSET_FORMAT G_GINT64_FORMAT #endif /* Not all systems' seem to define this. */ #if !defined MAP_FAILED #define MAP_FAILED ((void *) -1) #endif #if !defined MAXNAMLEN /* Still no MAXNAMLEN? Then make one up. */ #define MAXNAMLEN 255 #endif /* ----------------------------------------------------------------------------------------- */ #define RCNAME "gentoorc" /* ----------------------------------------------------------------------------------------- */ /* Sometimes, this does good stuff. I hope. That's about all you can do with GNU tools, ** since actually understanding them requires way more time than I'm willing to spend. */ #include "gnu-gettext.h" #if defined ENABLE_NLS /* This provides the _() and N_() macros used to mark strings for translation. */ #include #else /* Provide transparent definitions if NLS is disabled. */ #define _(str) str #define N_(str) str #endif /* ENABLE_NLS */ /* ----------------------------------------------------------------------------------------- */ typedef struct MainInfo MainInfo; typedef struct DirPane DirPane; typedef struct CmdSeq CmdSeq; /* These are various subsystems whose includes we need here, since they define datatypes ** that are needed below. This is a good point to include them, since MainInfo has been ** introduced (above). */ #include "buttonlayout.h" #include "keyboard.h" #include "controls.h" #include "iconutil.h" #include "queue.h" #include "cmdarg.h" #include "styles.h" #include "dirhistory.h" #include "window.h" #include "menus.h" #include "sizeutil.h" #define KEY_NAME_SIZE (32) #define CSQ_NAME_SIZE (32) /* FileType-related constants. */ enum { FT_NAME_SIZE = (32), FT_SUFFIX_SIZE = (32), FT_NAMERE_SIZE = (64), FT_FILERE_SIZE = (64), FTFL_REQPERM = (1<<0), FTFL_REQSUFFIX = (1<<1), FTFL_NAMEMATCH = (1<<2), FTFL_NAMEGLOB = (1<<3), FTFL_FILEMATCH = (1<<4), FTFL_FILEGLOB = (1<<5), FTFL_NAMENOCASE = (1<<6), FTFL_FILENOCASE = (1<<7), FTPM_SETUID = (1<<0), FTPM_SETGID = (1<<1), FTPM_STICKY = (1<<2), FTPM_READ = (1<<3), FTPM_WRITE = (1<<4), FTPM_EXECUTE = (1<<5), }; typedef struct { /* Used to map stat() info onto names. */ gchar name[FT_NAME_SIZE]; /* Human-readable name of filetype (e.g. "GIF image", "MP3 song"). */ mode_t mode; /* Type flags, matched against stat()'s mode info. */ guint32 flags; /* Various flags. */ guint32 perm; /* Permissions to require. Not orthogonal with mode. */ gchar suffix[FT_SUFFIX_SIZE]; /* Suffix to require (if FTFL_REQSUFFIX is set). */ gchar name_re_src[FT_NAMERE_SIZE]; /* Regular expression to match against the name (if FTFL_MATCHNAME). */ regex_t *name_re; /* Compiled version of the regular expression. */ gchar file_re_src[FT_FILERE_SIZE]; /* RE to match against output of 'file' command (if FTFL_MATCHFILE). */ regex_t *file_re; /* Again, a compiled version of the regular expression. */ Style *style; /* Style to use for items matching this type. */ } FType; #define DP_TITLE_SIZE (32) #define DP_FORMAT_SIZE (16) #define DP_DATEFMT_SIZE (32) #define DP_MAX_COLUMNS (32) typedef enum { DPC_NAME, DPC_SIZE, DPC_BLOCKS, DPC_BLOCKSIZE, DPC_MODENUM, DPC_MODESTR, DPC_NLINK, DPC_UIDNUM, DPC_UIDSTR, DPC_GIDNUM, DPC_GIDSTR, DPC_DEVICE, DPC_DEVMAJ, DPC_DEVMIN, DPC_ATIME, DPC_MTIME, DPC_CRTIME, DPC_CHTIME, DPC_TYPE, DPC_ICON, DPC_URI_NOFILE, DPC_NUM_TYPES } DPContent; typedef struct { guint show_type : 1; /* Append type-character (from "@ / * | =") to names? */ guint show_linkname : 1; /* Append " -> destination" on symbolic links? */ } DC_Name; typedef struct { SzUnit unit; guint ticks : 1; gchar tick; gint digits; gchar dformat[DP_FORMAT_SIZE]; /* Hidden from user, not saved, built by config code. */ guint dir_show_fs_size : 1; /* Show filesystem size for directories? */ } DC_Size; typedef struct { gchar format[DP_FORMAT_SIZE]; /* General numerical formatter (for size, mode, uid, etc). */ } DC_Fmt; typedef struct { gchar format[DP_DATEFMT_SIZE]; /* A strftime() format specifier. */ } DC_Time; typedef union { DC_Name name; DC_Size size; DC_Fmt blocks, blocksize; DC_Fmt mode, nlink, uidnum, gidnum, device, devmaj, devmin; DC_Time a_time, m_time, cr_time, ch_time; } DpCExtra; typedef struct { gchar title[DP_TITLE_SIZE]; DPContent content; DpCExtra extra; /* Content-specific flags. */ GtkJustification just; gint width; } DpCFmt; typedef enum { DPS_DIRS_FIRST = 0, DPS_DIRS_LAST, DPS_DIRS_MIXED } SortMode; typedef struct { DPContent content; /* The content type we wish to sort on. */ SortMode mode; /* Controls placement of directories. */ gboolean invert; /* If set, we sort backwards (Z-A). */ gboolean nocase; /* Set for case-insensitive string comparisons. Lame! */ } DPSort; typedef enum { SBP_IGNORE = 0, SBP_LEFT, SBP_RIGHT } SBarPos; #define FONT_MAX 128 typedef struct { guint num_columns; DpCFmt format[DP_MAX_COLUMNS]; DPSort sort; gchar def_path[PATH_MAX]; gboolean path_above; /* Set to get the path entry above the actual pane. */ gboolean hide_allowed; /* Set to enable hiding (default). */ gboolean scrollbar_always; /* Set to always show scrollbar, regardless of # of entries. */ gboolean huge_parent; /* Set to enable huge, tall, Opus-like parent button. */ SBarPos sbar_pos; /* Position of scrollbar. */ gboolean set_font; /* Set to override GTK+'s default font. */ gchar font_name[FONT_MAX]; /* Last-set font name, remains valid even when set_font == FALSE. */ gboolean rubber_banding; /* Set to enable GTK+'s "rubberbanding" selection. */ } DPFormat; typedef enum { DPORIENT_HORIZ = 0, DPORIENT_VERT } DpOrient; typedef enum { DPSPLIT_FREE = 0, DPSPLIT_RATIO, DPSPLIT_ABS_LEFT, DPSPLIT_ABS_RIGHT } DpSplit; /* Allow user to control how gentoo should allocate window space between the panes. */ typedef struct { DpOrient orientation; DpSplit mode; gdouble value; /* Parameter interpreted depending on mode. */ } DPPaning; typedef struct { gboolean select; /* Remember selections? */ gboolean save; /* Save history lists on exit? */ } DPHistory; /* ----------------------------------------------------------------------------------------- */ /* General command row flags. */ enum { CGF_RUNINBG = (1<<0), /* Run in command in background? */ CGF_KILLPREV = (1<<1), /* Kill previous instance of program (only background)? */ CGF_GRABOUTPUT = (1<<2), /* Capture the output into a special window? */ CGF_SURVIVE = (1<<3) /* Survive when gentoo quits (only background)? */ }; /* These flags are for the before- and after-flag fields. */ enum { CBAF_RESCAN_SOURCE = (1<<0), /* Rescan the source dir pane? */ CBAF_RESCAN_DEST = (1<<1), CBAF_CD_SOURCE = (1<<2), /* These save some config work. */ CBAF_CD_DEST = (1<<3), CBAF_REQSEL_SOURCE = (1<<4), /* Command won't run if there's no source selection when invoked. */ CBAF_REQSEL_DEST = (1<<5) /* Command won't run if there's no destination selection when invoked. */ }; typedef struct { /* Extra info for external commands. */ guint32 gflags; /* General flags. */ guint32 baflags[2]; /* Before and after flags. */ } CX_Ext; typedef enum { CRTP_BUILTIN, CRTP_EXTERNAL, CRTP_NUM_TYPES } CRType; typedef struct { /* A command "row". */ CRType type; /* The type of the row. */ GString *def; /* The row definition string. */ guint32 flags; /* Flags common to all types. */ union { /* Type-specific row info. */ CX_Ext external; /* Extra info for external commands. */ } extra; } CmdRow; #define CSFLG_REPEAT (1<<0) /* Repeat sequence until no selection? */ struct CmdSeq { gchar name[CSQ_NAME_SIZE]; /* Name of this command sequence, really. */ guint32 flags; /* Flags for this sequence. */ GList *rows; /* List of CmdRow definition rows. */ }; typedef struct { /* Information about commands lives here. */ GHashTable *builtin; /* Built-in commands (actually CmdDesc structs -- see cmdseq.c). */ GHashTable *cmdseq; /* Command sequences. */ } CmdInfo; /* ----------------------------------------------------------------------------------------- */ #define BTN_LABEL_SIZE (32) #define BTN_TOOLTIP_SIZE (64) /* Arbitrary, as always. */ typedef struct { GList *sheets; /* List of button sheets. */ } ButtonInfo; typedef struct { /* Options for overwrite-confirmation dialog module. */ guint show_info : 1; /* Show info (sizes & dates) for conflicting files? */ gchar datefmt[DP_DATEFMT_SIZE]; /* How to format dates? */ } OptOverwrite; typedef enum { HIDE_NONE, HIDE_DOT, HIDE_REGEXP } HMode; typedef struct { /* Info about files hidden from user. Not ignored, just hidden. */ HMode mode; gchar hide_re_src[MAXNAMLEN]; /* Regular expression; matches are hidden if mode == HIDE_REGEXP. */ regex_t *hide_re; /* Compiled version of the RE. */ guint no_case : 1; /* Ignore case in the RE? */ } HideInfo; typedef enum { PTID_ICON = 0, PTID_GTKRC, PTID_FSTAB, PTID_MTAB, PTID_NUM_PATHS } PathID; typedef struct { /* Miscellanous paths. */ GString *path[PTID_NUM_PATHS]; /* Just one GString per path, that's all. */ HideInfo hideinfo; /* Info about which files should be hidden. */ } PathInfo; typedef struct { /* Configuration information for dialogs. */ GtkWindowPosition pos; /* How should dialogs be positioned? */ } DialogInfo; typedef enum { ERR_DISPLAY_STATUSBAR, ERR_DISPLAY_TITLEBAR, ERR_DISPLAY_DIALOG } ErrDisplay; typedef struct { ErrDisplay display; /* How should error (and status messages) be shown? */ gboolean beep; /* Do a gdk_beep() on error? */ } ErrInfo; typedef struct { GHashTable *ignored; /* Keyed on 'tag', if present ignore the dialog. */ } NagInfo; #define CFLG_CHANGED (1<<0) /* Config has changed. Set on "OK", cleared by cfg_save_all(). */ typedef struct { /* Holds all configuration info. */ guint32 flags; GList *type; /* List of types (FType structures). */ StyleInfo *style; /* Opaque style container. */ DPFormat dp_format[2]; DPPaning dp_paning; /* Controls how the paned view acts. */ DPHistory dp_history; /* History list option. */ OptOverwrite opt_overwrite; MenuInfo *menus; ButtonInfo buttons; ButtonLayout *buttonlayout; CmdInfo commands; PathInfo path; WinInfo *wininfo; DialogInfo dialogs; CtrlInfo *ctrlinfo; ErrInfo errors; gboolean (*dir_filter)(const gchar *name); NagInfo nag; } CfgInfo; typedef struct GuiInfo GuiInfo; typedef struct { GVfs *vfs; } VfsInfo; struct MainInfo { /* gentoo's single most central data structure. */ gchar **run_commands; /* From the command line --run option, kept first for initializer in main(). */ VfsInfo vfs; CfgInfo cfg; GuiInfo *gui; IconInfo *ico; QueueInfo *que; }; /* -- Directory content data structures -- */ /* This is used for complete-as-you-type of paths. */ typedef struct { gchar prefix[PATH_MAX]; /* The path prefix that the GtkCompletion holds strings for. */ guint change_sig; /* Signal for change handler on path entry widget. */ GtkEntryCompletion *compl; /* A GTK+ 2.0 completion object, attached to the pane's path entry. */ } PathComplete; enum { DPRF_HAS_SIZE = 1 << 0, /* Set when a row has a "real" size (not set for directories unless GetSize:d). */ DPRF_LINK_EXISTS = 1 << 1, /* Set when a symlink's target exists. */ DPRF_LINK_TO_DIR = 1 << 2 /* Set when symlink points at (valid) directory. Implies DPRF_LINK_EXISTS. */ }; typedef struct { /* A filename, in both on-disk and display formats. */ const gchar *disk; /* On-disk name, as read during directory scanning. */ const gchar *display; /* Display, as returned by glib (generally, this will be UTF-8). */ } DRName; typedef struct { /* Representation of a single line in a directory (a file, typically). */ DRName dr_names; /* Actual filename, in two representations. */ DRName dr_linknames; /* Link name, again in two representations. */ struct stat dr_lstat; /* From a call to lstat(). */ struct stat *dr_stat; /* If link, this holds link target stats. Else, it points at dr_lstat. */ guint32 dr_flags; /* Misc. flags. */ const FType *dr_type; /* Type information. */ } DirRow; typedef GtkTreeIter DirRow2; typedef struct { guint num_dirs, num_files; guint64 num_bytes; } SelInfo; typedef struct { /* Some trivial file system information. Updated on rescan. */ gboolean valid; /* Set if the structure's contents are valid. */ guint64 fs_size; /* Size of filesystem, in bytes. */ guint64 fs_free; /* Free bytes in this filesystem. */ } FsInfo; #define URI_MAX (2000) /* This should only rarely be used, and hopefully ease out once GIO gets more mature. */ typedef struct { gchar path[URI_MAX]; /* Contents apply to this path. */ gchar *pathd; /* Dynamically allocated display version of the path. Beware! */ GtkListStore *store; /* Actual ListStore holding the pane's contents. Insert and clear here. */ GFile *root; /* A GFile representing the current location shown. */ gboolean is_local; /* Is the root considered local? Used to control 'file' etc. */ guint num_rows; /* Number of valid rows. */ guint tot_dirs, tot_files; /* Total number of entries in directory. */ guint64 tot_bytes; /* Sum of all sizes, in bytes. */ struct stat *stat; /* Info about link targets. */ gsize stat_alloc, stat_use; /* Allocated and used link stat structs. */ SelInfo sel; FsInfo fs; } DirContents; /* -- Main DirPane structure --------------------------------------------------------------- */ struct DirPane { MainInfo *main; /* Handy to have around. */ guint index; /* Index of *this* pane, in the grand scheme of things. */ GtkWidget *vbox; GtkWidget *notebook; /* Notebook holding (normally) path widgetry. */ GtkWidget *parent; /* The common parent button. */ GtkWidget *hparent; /* The "huge" parent button, if enabled in config. */ GtkWidget *path; /* GTK+ 2.0 GtkComboBox showing path and path history. */ PathComplete complete; /* Information for completing the path. */ GtkWidget *hide; /* A toggle button showing (and controlling) hide status. Focus target! */ GtkWidget *scwin; /* Scrolling window for clist to live in. */ GtkWidget *view; /* GtkTreeView for viewing the pane. */ GtkWidget *menu_top; /* The top-level menu, typically shown by right-clicking. */ GtkWidget *mitem_action; /* The item in the top-level menu that contains the actions submenu. */ GtkWidget *menu_action; /* The menu containing the intersection of all available actions on the selection. */ DirContents dir; /* Contents of directory (list of names etc). */ DirHistory *hist; /* Historic data about previously visited directories. */ gint last_row; /* The last clicked row. */ gint last_row2; /* The second last clicked row. */ gint dbclk_row; /* The row that was double clicked, or -1. */ guint sig_sel_changed; /* Signal for the "changed" event on the view's GtkTreeSelection. */ guint sig_path_activate; /* Signal for the "activate" event on path entry combo box. */ guint sig_path_changed; /* Signal for the "changed" event on the path entry combo box. */ }; /* -- Graphic user interface stuff --------------------------------------------------------- */ struct GuiInfo { GtkWidget *window; guint sig_main_configure; guint sig_main_delete; KbdContext *kbd_ctx; /* Keyboard context, for shortcuts. */ GtkWidget *vbox; /* Vbox that contains entire GUI. */ GtkWidget *top; /* A label showing status (selections, free space, etc). */ GtkWidget *panes; /* GtkPaned widget holding DirPanes. */ guint sig_pane_notify; /* Signal handler ID for notify::position. */ GtkWidget *middle; /* A box holding entire middle part. */ GtkWidget *bottom; /* Bottom part of GUI. */ DirPane pane[2]; DirPane *cur_pane; gboolean evt_button_valid; GdkEventButton evt_button; }; /* ----------------------------------------------------------------------------------------- */ /* These are defined in the main "gentoo.c" module, but really shouldn't be. Until they ** get a module of their own, they need to be prototyped like this. :( */ extern void rebuild_top(MainInfo *min); extern void rebuild_middle(MainInfo *min); extern void rebuild_bottom(MainInfo *min); gentoo-0.20.7/src/cmd_chmod.c0000644000175000017500000002267312310662641012677 00000000000000/* ** 1998-05-29 - A command to change the access flags of a file or directory. ** Made significantly simpler by the new cmd_generic module. ** 1999-03-06 - Adapted for new selection/generic handling. ** 2010-03-02 - GIO porting more or less complete. */ #include "gentoo.h" #include "errors.h" #include "dirpane.h" #include "strutil.h" #include "window.h" #include "cmd_generic.h" #include "cmd_chmod.h" #define CMD_ID "chmod" /* ----------------------------------------------------------------------------------------- */ typedef struct { GtkWidget *frame; GtkWidget *vbox; GtkWidget *check[3]; gulong signal[3]; } PFrame; typedef struct { GtkWidget *vbox; GtkWidget *label; GtkWidget *fbox; PFrame frame[4]; GtkWidget *entry_text; GtkWidget *entry_octal; GtkWidget *bbox; GtkWidget *all, *none, *toggle, *revert; mode_t last_mode; GtkWidget *recurse; gboolean last_recurse; GtkWidget *nodirs; gboolean last_nodirs; } ChmInfo; static const mode_t mask[] = { S_ISUID, S_ISGID, S_ISVTX, S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH }; /* ----------------------------------------------------------------------------------------- */ static mode_t get_checks(const ChmInfo *chm) { mode_t mode = 0U; guint i, j, k; for(i = k = 0; i < sizeof chm->frame / sizeof *chm->frame; i++) { for(j = 0; j < sizeof chm->frame[i].check / sizeof *chm->frame[i].check; j++, k++) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chm->frame[i].check[j]))) mode |= mask[k]; } } return mode; } /* 2009-03-25 - Update the textual representations. These are currently read-only. */ static void set_texts(ChmInfo *chm, mode_t mode) { gchar buf[32]; stu_mode_to_text(buf, sizeof buf, mode); gtk_entry_set_text(GTK_ENTRY(chm->entry_text), buf + 1); /* Skip the directory indicator. */ g_snprintf(buf, sizeof buf, "%o", mode); gtk_entry_set_text(GTK_ENTRY(chm->entry_octal), buf); } static void set_checks(ChmInfo *chm, mode_t mode) { guint i, j, k; for(i = k = 0; i < sizeof chm->frame / sizeof *chm->frame; i++) { for(j = 0; j < sizeof chm->frame[i].check / sizeof *chm->frame[i].check; j++, k++) { g_signal_handler_block(G_OBJECT(chm->frame[i].check[j]), chm->frame[i].signal[j]); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chm->frame[i].check[j]), mode & mask[k]); g_signal_handler_unblock(G_OBJECT(chm->frame[i].check[j]), chm->frame[i].signal[j]); } } set_texts(chm, mode); } static void chm_body(MainInfo *min, DirPane *src, DirRow2 *row, gpointer gen, gpointer user) { ChmInfo *chm = user; gchar temp[2 * FILENAME_MAX + 128]; mode_t mode = dp_row_get_mode(dp_get_tree_model(src), row); g_snprintf(temp, sizeof temp, _("Set protection bits for \"%s\":"), dp_row_get_name_display(dp_get_tree_model(src), row)); gtk_label_set_text(GTK_LABEL(chm->label), temp); set_checks(chm, chm->last_mode = (mode & 07777)); } /* ----------------------------------------------------------------------------------------- */ static gboolean chmod_gfile(MainInfo *min, DirPane *src, const GFile *file, mode_t mode, gboolean recurse, gboolean nodirs, GError **err) { GFileInfo *fi; gboolean ok = FALSE; if((fi = g_file_query_info((GFile *) file, G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, err)) != NULL) { const gboolean isdir = (g_file_info_get_file_type(fi) == G_FILE_TYPE_DIRECTORY); /* Don't try to change the file's type. */ g_file_info_remove_attribute(fi, G_FILE_ATTRIBUTE_STANDARD_TYPE); /* If non-directory or we're attacking dirs, set the mode first. */ if(!isdir || !nodirs) { g_file_info_set_attribute_uint32(fi, G_FILE_ATTRIBUTE_UNIX_MODE, mode); ok = g_file_set_attributes_from_info((GFile *) file, fi, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, err); } else ok = TRUE; /* Drop the info, we're done. */ g_object_unref(fi); /* If successful so far, consider recursing. */ if(ok && isdir && recurse) { GFileEnumerator *fe; if((fe = g_file_enumerate_children((GFile *) file, "standard::name,unix::mode", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, err)) != NULL) { GFileInfo *cfi; GFile *child; while(ok && (cfi = g_file_enumerator_next_file(fe, NULL, err)) != NULL) { if((child = g_file_get_child((GFile *) file, g_file_info_get_name(cfi))) != NULL) { ok = chmod_gfile(min, src, child, mode, recurse, nodirs, err); g_object_unref(child); } else ok = FALSE; g_object_unref(cfi); } g_object_unref(fe); } else ok = FALSE; } } return ok; } static gint chm_action(MainInfo *min, DirPane *src, DirPane *dst, DirRow2 *row, GError **err, gpointer user) { ChmInfo *chm = user; const mode_t mode = get_checks(chm); GFile *dfile; gboolean ok; chm->last_recurse = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chm->recurse)); chm->last_nodirs = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chm->nodirs)); dfile = dp_get_file_from_row(src, row); ok = chmod_gfile(min, src, dfile, mode, chm->last_recurse, chm->last_nodirs, err); if(ok) dp_unselect(src, row); return ok; } /* ----------------------------------------------------------------------------------------- */ static void evt_clicked(GtkWidget *wid, gpointer user) { ChmInfo *chm = user; if(wid == chm->all) set_checks(chm, S_ISUID | S_ISGID | S_ISVTX | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH); else if(wid == chm->none) set_checks(chm, 0); else if(wid == chm->toggle) set_checks(chm, (~get_checks(chm)) & 07777); else if(wid == chm->revert) set_checks(chm, chm->last_mode); else set_texts(chm, get_checks(chm)); } /* 1998-05-29 - Build a protection frame, with three checkboxes. If type is 0, we build a ** special one (with setuid/setgid/sticky), otherwise a standard (read/write/exec). */ static void build_frame(ChmInfo *ci, gint pos, gint type) { gchar *label[] = { N_("Special"), N_("Owner"), N_("Group"), N_("Others") }; gchar *check[] = { N_("Set UID"), N_("Set GID"), N_("Sticky"), N_("Read"), N_("Write"), N_("Execute") }; PFrame *fr = &ci->frame[pos]; gint i; fr->frame = gtk_frame_new(_(label[pos])); fr->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); for(i = 0; i < 3; i++) { fr->check[i] = gtk_check_button_new_with_label(_(check[type * 3 + i])); fr->signal[i] = g_signal_connect(G_OBJECT(fr->check[i]), "toggled", G_CALLBACK(evt_clicked), ci); gtk_box_pack_start(GTK_BOX(fr->vbox), fr->check[i], TRUE, TRUE, 0); } gtk_container_add(GTK_CONTAINER(fr->frame), fr->vbox); } gint cmd_chmod(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca) { static ChmInfo ci; guint i; GtkWidget *hbox, *w; ci.vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); ci.label = gtk_label_new(_("Protection Bits")); ci.fbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); for(i = 0; i < sizeof ci.frame / sizeof ci.frame[0]; i++) { build_frame(&ci, i, (i == 0) ? 0 : 1); gtk_box_pack_start(GTK_BOX(ci.fbox), ci.frame[i].frame, TRUE, TRUE, 5); } gtk_box_pack_start(GTK_BOX(ci.vbox), ci.label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(ci.vbox), ci.fbox, TRUE, TRUE, 0); hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); w = gtk_label_new(_("Textual")); gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 0); ci.entry_text = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(ci.entry_text), 10); gtk_entry_set_width_chars(GTK_ENTRY(ci.entry_text), 10); gtk_editable_set_editable(GTK_EDITABLE(ci.entry_text), FALSE); gtk_box_pack_start(GTK_BOX(hbox), ci.entry_text, FALSE, FALSE, 0); ci.entry_octal = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(ci.entry_octal), 4); gtk_entry_set_width_chars(GTK_ENTRY(ci.entry_octal), 4); gtk_editable_set_editable(GTK_EDITABLE(ci.entry_octal), FALSE); gtk_box_pack_end(GTK_BOX(hbox), ci.entry_octal, FALSE, FALSE, 0); w = gtk_label_new(_("Octal")); gtk_box_pack_end(GTK_BOX(hbox), w, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(ci.vbox), hbox, FALSE, FALSE, 0); ci.bbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); ci.all = gtk_button_new_with_label(_("All")); ci.none = gtk_button_new_with_label(_("None")); ci.toggle = gtk_button_new_with_label(_("Toggle")); ci.revert = gtk_button_new_with_label(_("Revert")); g_signal_connect(G_OBJECT(ci.all), "clicked", G_CALLBACK(evt_clicked), &ci); g_signal_connect(G_OBJECT(ci.none), "clicked", G_CALLBACK(evt_clicked), &ci); g_signal_connect(G_OBJECT(ci.toggle), "clicked", G_CALLBACK(evt_clicked), &ci); g_signal_connect(G_OBJECT(ci.revert), "clicked", G_CALLBACK(evt_clicked), &ci); gtk_box_pack_start(GTK_BOX(ci.bbox), ci.all, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(ci.bbox), ci.none, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(ci.bbox), ci.toggle, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(ci.bbox), ci.revert, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(ci.vbox), ci.bbox, TRUE, TRUE, 0); hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); ci.recurse = gtk_check_button_new_with_label(_("Recurse Directories?")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ci.recurse), ci.last_recurse); gtk_box_pack_start(GTK_BOX(hbox), ci.recurse, TRUE, TRUE, 0); ci.nodirs = gtk_check_button_new_with_label(_("Don't Touch Directories?")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ci.nodirs), ci.last_nodirs); gtk_box_pack_start(GTK_BOX(hbox), ci.nodirs, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(ci.vbox), hbox, FALSE, FALSE, 0); return cmd_generic(min, _("Change Mode"), CGF_SRC, chm_body, chm_action, NULL, &ci); } gentoo-0.20.7/src/cmd_renameseq.h0000644000175000017500000000021612310662641013557 00000000000000/* ** 2001-09-30 - Sequential rename declaration. */ extern gint cmd_renameseq(MainInfo *min, DirPane *src, DirPane *dst, const CmdArg *ca); gentoo-0.20.7/src/gentoo.c0000664000175000017500000004764312655630042012265 00000000000000/* ** 1998-05-17 - I just have to build an Opus-look-alike GTK GUI! :) ** 1998-09-11 - Er, it like, grew, or something. */ #include "gentoo.h" #include #include #include #include #include #if defined ENABLE_NLS #include #endif #include "errors.h" #include "configure.h" #include "dirpane.h" #include "dialog.h" #include "userinfo.h" #include "file.h" #include "fileutil.h" #include "gfam.h" #include "guiutil.h" #include "xmlutil.h" #include "strutil.h" #include "types.h" #include "styles.h" #include "sizeutil.h" #include "buttons.h" #include "buttonlayout.h" #include "queue.h" #include "cmdseq.h" #include "children.h" #include "dpformat.h" #include "keyboard.h" #include "controls.h" #include "iconutil.h" #include "cmdseq_config.h" #include "menus.h" #include "nag_dialog.h" #include "cfg_module.h" #include "cfg_nag.h" #include "cfg_windows.h" /* ----------------------------------------------------------------------------------------- */ /* 1998-05-18 - Filter out files the user really doesn't want to see, and that recursive ** directory traversing code really, really, REALLY, doesn't. */ static gboolean dir_filter(const gchar *name) { if((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) return FALSE; return TRUE; } /* ----------------------------------------------------------------------------------------- */ /* 2000-03-18 - User clicked close button on window. Just react as if the Quit command was run. */ static gboolean evt_main_delete(GtkWidget *wid, GdkEventAny *evt, gpointer user) { csq_execute(user, "Quit"); return TRUE; } /* 1998-10-26 - Initialize some fields in the dp structure. */ static void init_pane(DirPane *dp, gint index) { dp->index = index; dp->complete.prefix[0] = '\0'; dp->dir.stat = NULL; dp->dir.stat_alloc = 0; dp->dir.stat_use = 0; dp->hist = dph_dirhistory_new(); dp->dir.path[0] = '\0'; } static void evt_paned_notify_position(GObject *obj, GParamSpec *spec, gpointer user) { MainInfo *min = user; GdkWindow *pwin; gint pos, np; if(!dp_realized(min)) return; pos = gtk_paned_get_position(GTK_PANED(obj)); pwin = gtk_widget_get_window(min->gui->panes); np = min->cfg.dp_paning.orientation == DPORIENT_HORIZ ? gdk_window_get_width(pwin) : gdk_window_get_height(pwin); switch(min->cfg.dp_paning.mode) { case DPSPLIT_FREE: break; case DPSPLIT_RATIO: min->cfg.dp_paning.value = (gdouble) pos / np; break; case DPSPLIT_ABS_LEFT: min->cfg.dp_paning.value = pos; break; case DPSPLIT_ABS_RIGHT: min->cfg.dp_paning.value = np - pos; break; } } /* 1998-05-17 - Build a couple of dir-panes. ** 1998-05-18 - Now also puts the panes in a horizontally paned window, for extra Opusity. ;^) ** 1998-08-02 - Fixed *huge* bug where pane 1 (the right) was built using pane 0's format!! */ static GtkWidget * build_dirpanes(MainInfo *min) { GtkWidget *pane; GuiInfo *gui; gui = min->gui; gui->panes = gtk_paned_new(min->cfg.dp_paning.orientation == DPORIENT_HORIZ ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL); init_pane(&gui->pane[0], 0); pane = dp_build(min, &min->cfg.dp_format[0], &gui->pane[0]); gtk_paned_add1(GTK_PANED(gui->panes), pane); init_pane(&gui->pane[1], 1); pane = dp_build(min, &min->cfg.dp_format[1], &gui->pane[1]); gtk_paned_add2(GTK_PANED(gui->panes), pane); gui->sig_pane_notify = g_signal_connect(G_OBJECT(gui->panes), "notify::position", G_CALLBACK(evt_paned_notify_position), min); gtk_widget_show(gui->panes); gtk_widget_grab_focus(min->gui->pane[0].view); return gui->panes; } static void evt_top_button_press_event(GtkWidget *top, GdkEventButton *evt, gpointer user) { if(evt->button == 1 && evt->type == GDK_2BUTTON_PRESS) csq_execute(user, "About"); } /* 1998-05-19 - Create the top widgetry, returning something the caller can just add to a box. Sets the **