More GTK dependencies

master
Chris Dorman 2020-12-01 17:36:52 -08:00
parent 5b5b425ba6
commit bf01888987
10 changed files with 157 additions and 954 deletions

View File

@ -44,6 +44,11 @@ lynxmirror="https://invisible-mirror.net/archives/lynx/tarballs"
expatmirror="https://github.com/libexpat/libexpat/releases/download/R_2_2_7"
utillinuxmirror="https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.33"
foxmirror="ftp://ftp.fox-toolkit.org/pub"
glib2mirror="https://download.gnome.org/sources/glib/2.56"
cairomirror="https://www.cairographics.org/releases"
gdkpixbufmirror="http://ftp.gnome.org/pub/gnome/sources/gdk-pixbuf/2.36"
atkmirror="http://ftp.gnome.org/pub/gnome/sources/atk/2.26"
gobjectintromirror="http://ftp.gnome.org/pub/gnome/sources/gobject-introspection/1.54"
# filenames
gcc="gcc-9.2.0.tar.xz"
@ -79,6 +84,12 @@ idn="libidn-1.36.tar.gz"
expat="expat-2.2.7.tar.xz"
utillinux="util-linux-2.33.2.tar.xz"
fox="fox-1.6.57.tar.gz"
glib2="glib-2.56.4.tar.xz"
gobjectintro="gobject-introspection-1.54.1.tar.xz"
gdkpixbuf="gdk-pixbuf-2.36.11.tar.xz"
cairo="cairo-1.14.12.tar.xz"
pixman="pixman-0.34.0.tar.gz"
atk="atk-2.26.1.tar.xz"
# work directories
tmpdir="`pwd`/pkgsrc"
@ -123,6 +134,13 @@ xcbprotosrcdir=${xcbproto//.tar.gz}
expatsrcdir=${expat//.tar.xz}
utillinuxsrcdir=${utillinux//.tar.xz}
foxsrcdir=${fox//.tar.gz}
glib2srcdir=${glib2srcdir//.tar.xz}
gdkpixbufsrcdir=${gdkpixbuf//.tar.xz}
cairosrcdir=${cairo//.tar.xz}
pixmansrcdir=${pixman//.tar.gz}
atksrcdir=${atk//.tar.xz}
gobjectintrosrcdir=${gobjectintro//.tar.xz}
if [ ! -d "$tmpdir" ]; then
echo "Warning: package source directory not found, creating."
@ -953,6 +971,145 @@ lynx()
cd $tmpdir
}
glib2()
{
cd $tmpdir
# Grab sources for libexpat
if [ ! -d $glib2srcdir ]; then
wget $glib2mirror/$glib2
tar -xf $glib2
fi
cd $glib2srcdir
if [ ! -d "make-glib" ]; then
mkdir make-glib
cd make-glib
elif
cd make-glib
fi
meson --prefix=$freondir -Dwith-pcre=no -Dwith-docs=no .. &&
ninja
ninja install
cd $tmpdir
}
atk()
{
cd $tmpdir
# Grab sources for libexpat
if [ ! -d $atksrcdir ]; then
wget $atkmirror/$atk
tar -xf $atk
fi
cd $atksrcdir
if [ ! -d "make-atk" ]; then
mkdir make-atk
cd make-atk
elif
cd make-atk
fi
meson --prefix=$freondir .. &&
ninja
ninja install
cd $tmpdir
}
cairo()
{
cd $tmpdir
# Grab sources for cairo
if [ ! -d $cairosrcdir ]; then
wget $cairomirror/$cairo
tar -xf $cairo
fi
cd $cairosrcdir
./configure --prefix=$freondir --disable-static
make -j$corecount
make install
cd $tmpdir
}
pixman()
{
cd $tmpdir
# Grab sources for pixman
if [ ! -d $pixmansrcdir ]; then
wget $cairomirror/$pixman
tar -xf $pixman
fi
cd $pixmansrcdir
./configure --prefix=$freondir --disable-static
make -j$corecount
make install
cd $tmpdir
}
gobject-intro()
{
cd $tmpdir
# Grab sources for gobject introspect
if [ ! -d $gobjectintrosrcdir ]; then
wget $gobjectintromirror/$gobjectintro
tar -xf $gobjectintro
fi
cd $gobjectintrosrcdir
./configure --prefix=$freondir --disable-static --without-python
make -j$corecount
make install
cd $tmpdir
}
gdk-pixbuf()
{
cd $tmpdir
# Grab sources for libexpat
if [ ! -d $gdkpixbufsrcdir ]; then
wget $gdkpixbufmirror/$gdkpixbuf
tar -xf $gdkpixbuf
fi
cd $gdkpixbufsrcdir
./configure --prefix=$freondir --with-x11
make -j$corecount
make install
cd $tmpdir
}
expat()
{
cd $tmpdir

View File

@ -1,45 +0,0 @@
CC = cc
CFLAGS = -std=c99 -D_GNU_SOURCE -g -O2 -pthread -Wall -pedantic `pkg-config --cflags --libs gtk+-2.0 gthread-2.0` -export-dynamic
PREFIX = /freon
SRC = dfm.c
OBJ = ${SRC:.c=.o}
all: clean dfm
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
$(OBJ): config.h version.h
dfm: ${OBJ}
$(CC) $(LDFLAGS) -o $@ $(OBJ) $(CFLAGS)
config:
@echo creating default config.h from config.ex.h
@cp config.ex.h config.h
clean:
@echo cleaning directory
@rm -f dfm ${OBJ} *.gch version.h
install: all
@echo installing dfm to ${PREFIX}/bin
@mkdir -p ${PREFIX}/bin
@cp -f dfm ${PREFIX}/bin
@chmod 755 ${PREFIX}/bin/dfm
uninstall:
@echo removing dfm from ${PREFIX}/bin
@rm -f ${PREFIX}/dfm
version.h:
@echo "#ifndef _VERSION_H_" > version.h
@echo "#define _VERSION_H_" >> version.h
@echo -n "#define VERSION \"" >> version.h
@git show -s --pretty=format:"dfm commit %h (%ai)\"%n" >> version.h
@echo "#endif" >> version.h
.PHONY: clean

View File

@ -1,17 +0,0 @@
dfm
===
simple gtk+ file manager
Configuration
-------------
Create configuration file with:
make config
And edit config.h
Installation
------------
Create a configuration file, and then run the following to build and install:
make clean install

View File

@ -1,65 +0,0 @@
#define MODKEY GDK_CONTROL_MASK
/* Terminal command */
#define TERMINAL (char *[]){ "rxvt", NULL }
/* Bookmarks */
static const char *bookmarks[] = {
"/",
"/root"
};
/* Time format */
static const char *timefmt = "%Y-%m-%d %H:%M:%S";
/* Poll time for directory updating (in seconds) */
static const int polltime = 1;
/* Command to be executed when activating a file */
static const char *filecmd[] = { "/bin/sh", "-c",
"executor \"$DFM_PATH\"", NULL };
/* Key bindings */
static Key keys[] = {
/* Movement */
{ MODKEY, GDK_j, move_cursor, { .i = DOWN } },
{ MODKEY, GDK_k, move_cursor, { .i = UP } },
{ MODKEY|GDK_SHIFT_MASK, GDK_j, move_cursor, { .i = PAGEDOWN } },
{ MODKEY|GDK_SHIFT_MASK, GDK_k, move_cursor, { .i = PAGEUP } },
{ MODKEY, GDK_g, move_cursor, { .i = HOME } },
{ MODKEY|GDK_SHIFT_MASK, GDK_g, move_cursor, { .i = END } },
/* Spawn new window */
{ MODKEY, GDK_w, newwin, { 0 } },
/* Go up one level */
{ MODKEY, GDK_h, set_path, { .v = ".." } },
{ 0, GDK_BackSpace, set_path, { .v = ".." } },
/* Terminal launch */
{ MODKEY, GDK_x, dir_exec, { .v = TERMINAL } },
/* Make directory */
{ MODKEY|GDK_SHIFT_MASK, GDK_m, make_dir, { .i = 0755 } },
{ MODKEY, GDK_m, mv, { 0 } },
/* Set path */
{ MODKEY, GDK_l, set_path, { 0 } },
/* Preferences */
{ MODKEY|GDK_SHIFT_MASK, GDK_h, toggle_pref, { .i = DOTFILES } },
/* Bookmarks */
{ MODKEY, GDK_1, bookmark, { .i = 0 } },
{ MODKEY, GDK_2, bookmark, { .i = 1 } },
{ MODKEY, GDK_3, bookmark, { .i = 2 } },
{ MODKEY, GDK_4, bookmark, { .i = 3 } },
{ MODKEY, GDK_5, bookmark, { .i = 4 } },
{ MODKEY, GDK_6, bookmark, { .i = 5 } },
{ MODKEY, GDK_7, bookmark, { .i = 6 } },
{ MODKEY, GDK_8, bookmark, { .i = 7 } },
{ MODKEY, GDK_9, bookmark, { .i = 8 } },
{ MODKEY, GDK_0, bookmark, { .i = 9 } }
};

View File

@ -1,65 +0,0 @@
#define MODKEY GDK_CONTROL_MASK
/* Terminal command */
#define TERMINAL (char *[]){ "rxvt", NULL }
/* Bookmarks */
static const char *bookmarks[] = {
"/",
"/root"
};
/* Time format */
static const char *timefmt = "%Y-%m-%d %H:%M:%S";
/* Poll time for directory updating (in seconds) */
static const int polltime = 1;
/* Command to be executed when activating a file */
static const char *filecmd[] = { "/bin/sh", "-c",
"executor \"$DFM_PATH\"", NULL };
/* Key bindings */
static Key keys[] = {
/* Movement */
{ MODKEY, GDK_j, move_cursor, { .i = DOWN } },
{ MODKEY, GDK_k, move_cursor, { .i = UP } },
{ MODKEY|GDK_SHIFT_MASK, GDK_j, move_cursor, { .i = PAGEDOWN } },
{ MODKEY|GDK_SHIFT_MASK, GDK_k, move_cursor, { .i = PAGEUP } },
{ MODKEY, GDK_g, move_cursor, { .i = HOME } },
{ MODKEY|GDK_SHIFT_MASK, GDK_g, move_cursor, { .i = END } },
/* Spawn new window */
{ MODKEY, GDK_w, newwin, { 0 } },
/* Go up one level */
{ MODKEY, GDK_h, set_path, { .v = ".." } },
{ 0, GDK_BackSpace, set_path, { .v = ".." } },
/* Terminal launch */
{ MODKEY, GDK_x, dir_exec, { .v = TERMINAL } },
/* Make directory */
{ MODKEY|GDK_SHIFT_MASK, GDK_m, make_dir, { .i = 0755 } },
{ MODKEY, GDK_m, mv, { 0 } },
/* Set path */
{ MODKEY, GDK_l, set_path, { 0 } },
/* Preferences */
{ MODKEY|GDK_SHIFT_MASK, GDK_h, toggle_pref, { .i = DOTFILES } },
/* Bookmarks */
{ MODKEY, GDK_1, bookmark, { .i = 0 } },
{ MODKEY, GDK_2, bookmark, { .i = 1 } },
{ MODKEY, GDK_3, bookmark, { .i = 2 } },
{ MODKEY, GDK_4, bookmark, { .i = 3 } },
{ MODKEY, GDK_5, bookmark, { .i = 4 } },
{ MODKEY, GDK_6, bookmark, { .i = 5 } },
{ MODKEY, GDK_7, bookmark, { .i = 6 } },
{ MODKEY, GDK_8, bookmark, { .i = 7 } },
{ MODKEY, GDK_9, bookmark, { .i = 8 } },
{ MODKEY, GDK_0, bookmark, { .i = 9 } }
};

Binary file not shown.

View File

@ -1,730 +0,0 @@
/* dfm - Simple GTK+ file manager
*
* Copyright (c) 2011 David Stenberg
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <pthread.h>
#include <sys/stat.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "version.h"
#define ARRSIZE(x) (sizeof(x) / sizeof(*x))
#define CLEANMASK(mask) (mask & ~(GDK_MOD2_MASK))
enum ListColumns {
NAME_STR,
PERMS_STR,
SIZE_STR,
MTIME_STR,
IS_DIR
};
enum Movement {
UP,
DOWN,
HOME,
END,
PAGEUP,
PAGEDOWN
};
enum Preferences {
DOTFILES
};
typedef struct {
GtkWidget *win;
GtkWidget *scroll;
GtkWidget *tree;
gchar *path;
gboolean show_dot;
time_t mtime;
} FmWindow;
typedef struct {
gboolean b;
gint i;
void *v;
} Arg;
typedef struct {
guint mod;
guint key;
void (*func)(FmWindow *fw, const Arg *arg);
const Arg arg;
} Key;
/* functions */
static void action(GtkWidget *w, GtkTreePath *p, GtkTreeViewColumn *c, FmWindow *fw);
static void bookmark(FmWindow *fw, const Arg *arg);
static gint compare(GtkTreeModel *m, GtkTreeIter *a, GtkTreeIter *b, gpointer p);
static gchar *create_perm_str(mode_t mode);
static gchar *create_size_str(size_t size);
static gchar *create_time_str(const char *fmt, const struct tm *time);
static FmWindow *createwin();
static void destroywin(GtkWidget *w, FmWindow *fw);
static void dir_exec(FmWindow *fw, const Arg *arg);
static gint get_mtime(const gchar *path, time_t *time);
static GList *get_selected(FmWindow *fw);
static gboolean keypress(GtkWidget *w, GdkEventKey *ev, FmWindow *fw);
static void make_dir(FmWindow *fw, const Arg *arg);
static void move_cursor(FmWindow *fw, const Arg *arg);
static void mv(FmWindow *fw, const Arg *arg);
static void newwin(FmWindow *fw, const Arg *arg);
static void open_directory(FmWindow *fw, const char *str);
static void set_path(FmWindow *fw, const Arg *arg);
static gchar *prev_dir(gchar *path);
static void read_files(FmWindow *fw, DIR *dir);
static void reload(FmWindow *fw);
static void spawn(const gchar * const *argv, const gchar *path);
static gchar *text_dialog(GtkWindow *p, const gchar *title, const gchar *text);
static void text_dialog_enter(GtkWidget *w, GtkDialog *dialog);
static void toggle_pref(FmWindow *fw, const Arg *arg);
static void update(FmWindow *fw);
static void *update_thread(void *v);
static int valid_filename(const char *s, int show_dot);
/* variables */
static gboolean show_dotfiles = FALSE;
static GList *windows = NULL;
#include "config.h"
/* enters the selected item if directory, otherwise
* executes program with the file as argument */
void
action(GtkWidget *w, GtkTreePath *p, GtkTreeViewColumn *c, FmWindow *fw)
{
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(fw->tree));
GtkTreeIter iter;
gchar *name;
gchar fpath[PATH_MAX];
gboolean is_dir;
gtk_tree_model_get_iter(model, &iter, p);
gtk_tree_model_get(model, &iter, NAME_STR, &name,
IS_DIR, &is_dir, -1);
chdir(fw->path);
realpath(name, fpath);
g_free(name);
if (is_dir) { /* open directory */
open_directory(fw, fpath);
} else { /* execute program */
spawn(filecmd, fpath);
}
}
/* open a bookmark */
void
bookmark(FmWindow *fw, const Arg *arg)
{
if (arg->i >= 0 && arg->i < ARRSIZE(bookmarks))
open_directory(fw, (char *)bookmarks[arg->i]);
}
/* compares two rows in the tree model */
gint
compare(GtkTreeModel *m, GtkTreeIter *a, GtkTreeIter *b, gpointer p)
{
gchar *name[2];
gint isdir[2];
gint ret;
gtk_tree_model_get(m, a, NAME_STR, &name[0], IS_DIR, &isdir[0], -1);
gtk_tree_model_get(m, b, NAME_STR, &name[1], IS_DIR, &isdir[1], -1);
if (isdir[0] == isdir[1])
ret = g_ascii_strcasecmp(name[0], name[1]);
else
ret = isdir[0] ? -1 : 1;
g_free(name[0]);
g_free(name[1]);
return ret;
}
/* creates a formatted permission string */
gchar*
create_perm_str(mode_t mode)
{
char *permstr[] = {
"---", "--x", "-w-", "-wx",
"r--", "r-x", "rw-", "rwx" };
return g_strdup_printf("%s%s%s", permstr[(mode >> 6) & 7],
permstr[(mode >> 3) & 7],
permstr[mode & 7]);
}
/* creates a formatted size string */
gchar*
create_size_str(size_t size)
{
if (size < 1024)
return g_strdup_printf("%i B", (int)size);
else if (size < 1024*1024)
return g_strdup_printf("%.1f KB", size/1024.0);
else if (size < 1024*1024*1024)
return g_strdup_printf("%.1f MB", size/(1024.0*1024));
else
return g_strdup_printf("%.1f GB", size/(1024.0*1024*1024));
}
/* creates a formatted time string */
gchar*
create_time_str(const char *fmt, const struct tm *time)
{
gchar buf[64];
strftime(buf, sizeof(buf), fmt, time);
return g_strdup(buf);
}
/* creates and initializes a FmWindow */
FmWindow*
createwin()
{
FmWindow *fw;
GtkCellRenderer *rend;
GtkListStore *store;
GtkTreeSortable *sortable;
fw = g_malloc(sizeof(FmWindow));
fw->path = NULL;
fw->show_dot = show_dotfiles;
fw->win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(fw->win), 640, 480);
gtk_window_set_icon_name(GTK_WINDOW(fw->win), "folder");
/* setup scrolled window */
fw->scroll = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(fw->scroll),
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
/* setup list store */
store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
sortable = GTK_TREE_SORTABLE(store);
/* setup tree view */
fw->tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(fw->tree), TRUE);
gtk_tree_view_set_rubber_banding(GTK_TREE_VIEW(fw->tree), TRUE);
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(fw->tree), TRUE);
gtk_tree_selection_set_mode(
gtk_tree_view_get_selection(GTK_TREE_VIEW(fw->tree)),
GTK_SELECTION_MULTIPLE);
rend = gtk_cell_renderer_text_new();
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(fw->tree),
-1, "Name", rend, "text", NAME_STR, NULL);
rend = gtk_cell_renderer_text_new();
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(fw->tree),
-1, "Permissions", rend, "text", PERMS_STR, NULL);
rend = gtk_cell_renderer_text_new();
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(fw->tree),
-1, "Size", rend, "text", SIZE_STR, NULL);
rend = gtk_cell_renderer_text_new();
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(fw->tree),
-1, "Modified", rend, "text", MTIME_STR, NULL);
/* expand first column */
gtk_tree_view_column_set_expand(
gtk_tree_view_get_column(GTK_TREE_VIEW(fw->tree), 0),
TRUE);
/* setup list sorting */
gtk_tree_sortable_set_sort_func(sortable, NAME_STR, compare, NULL, NULL);
gtk_tree_sortable_set_sort_column_id(sortable, NAME_STR, GTK_SORT_ASCENDING);
/* connect signals */
g_signal_connect(G_OBJECT(fw->win), "destroy",
G_CALLBACK(destroywin), fw);
g_signal_connect(G_OBJECT(fw->win), "key-press-event",
G_CALLBACK(keypress), fw);
g_signal_connect(G_OBJECT(fw->tree), "row-activated",
G_CALLBACK(action), fw);
/* add widgets */
gtk_container_add(GTK_CONTAINER(fw->scroll), fw->tree);
gtk_container_add(GTK_CONTAINER(fw->win), fw->scroll);
gtk_widget_show_all(fw->win);
return fw;
}
/* removes and deallocates a FmWindow */
void
destroywin(GtkWidget *w, FmWindow *fw)
{
if ((windows = g_list_remove(windows, fw)) == NULL)
gtk_main_quit();
gtk_widget_destroy(fw->tree);
gtk_widget_destroy(fw->scroll);
gtk_widget_destroy(fw->win);
if (fw->path)
g_free(fw->path);
g_free(fw);
}
/* change directory to current, and spawns program in background */
void
dir_exec(FmWindow *fw, const Arg *arg)
{
g_return_if_fail(fw->path && arg->v);
spawn(arg->v, fw->path);
}
/* get mtime for a file. returns 0 if ok */
gint
get_mtime(const gchar *path, time_t *time)
{
struct stat st;
gint err;
g_return_val_if_fail(time, 0);
if ((err = stat(path, &st)) == 0)
*time = st.st_mtime;
return err;
}
/* returns a list of name for selected files (relative file names, not absolute) */
GList *
get_selected(FmWindow *fw)
{
GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(fw->tree));
GtkTreeModel *model;
GtkTreeIter iter;
GList *lsel = gtk_tree_selection_get_selected_rows(sel, &model);
GList *node = lsel;
GList *files = NULL;
gchar *name;
while (node) {
gtk_tree_model_get_iter(model, &iter, node->data);
gtk_tree_model_get(model, &iter, NAME_STR, &name, -1);
files = g_list_append(files, name);
node = g_list_next(node);
}
g_list_foreach(lsel, (GFunc) gtk_tree_path_free, NULL);
g_list_free(lsel);
return files;
}
/* handles key events on the FmWindow */
gboolean
keypress(GtkWidget *w, GdkEventKey *ev, FmWindow *fw)
{
gint i;
for (i = 0; i < ARRSIZE(keys); i++) {
if (gdk_keyval_to_lower(ev->keyval) == keys[i].key &&
CLEANMASK(ev->state) == keys[i].mod &&
keys[i].func) {
keys[i].func(fw, &keys[i].arg);
}
}
return FALSE;
}
void
make_dir(FmWindow *fw, const Arg *arg)
{
gchar *path;
g_return_if_fail(fw->path);
if ((path = text_dialog(GTK_WINDOW(fw->win), "make directory", NULL))) {
if (mkdir(path, arg->i) == -1)
g_warning("mkdir: %s", strerror(errno));
g_free(path);
}
}
/* moves cursor in the tree view */
void
move_cursor(FmWindow *fw, const Arg *arg)
{
/* TODO: fix this */
GtkMovementStep m;
gint v;
gboolean ret;
switch (arg->i) {
case UP:
m = GTK_MOVEMENT_DISPLAY_LINES;
v = -1;
break;
case DOWN:
m = GTK_MOVEMENT_DISPLAY_LINES;
v = 1;
break;
case HOME:
m = GTK_MOVEMENT_BUFFER_ENDS;
v = -1;
break;
case END:
m = GTK_MOVEMENT_BUFFER_ENDS;
v = 1;
break;
case PAGEUP:
m = GTK_MOVEMENT_PAGES;
v = -1;
break;
case PAGEDOWN:
m = GTK_MOVEMENT_PAGES;
v = 1;
break;
default:
return;
}
g_signal_emit_by_name(G_OBJECT(fw->tree), "move-cursor", m, v, &ret);
}
void
mv(FmWindow *fw, const Arg *arg)
{
/* TODO: dummy atm */
GList *files = get_selected(fw);
GList *iter = files;
while (iter) {
printf("f: '%s'\n", (char *)iter->data);
iter = g_list_next(iter);
}
g_list_foreach(files, (GFunc) g_free, NULL);
g_list_free(files);
}
/* creates and inserts a new FmWindow to the window list */
void
newwin(FmWindow *fw, const Arg *arg)
{
FmWindow *new = createwin();
windows = g_list_append(windows, new);
open_directory(new, arg->v ? arg->v : (fw ? fw->path : NULL));
}
/* open and reads directory data to FmWindow */
void
open_directory(FmWindow *fw, const char *str)
{
DIR *dir;
char rpath[PATH_MAX];
g_return_if_fail(str);
/* change to current working directory to get relative paths right */
if (fw->path)
chdir(fw->path);
/* get clean absolute path string */
realpath(str, rpath);
if (!(dir = opendir(rpath))) {
g_warning("%s: %s\n", rpath, g_strerror(errno));
if (strcmp(rpath, "/") != 0) {
/* try to go up one level and load directory */
open_directory(fw, prev_dir(rpath));
}
return;
}
if (fw->path)
g_free(fw->path);
fw->path = g_strdup(rpath);
chdir(fw->path);
get_mtime(fw->path, &fw->mtime);
gtk_window_set_title(GTK_WINDOW(fw->win), fw->path);
read_files(fw, dir);
closedir(dir);
}
gchar*
prev_dir(gchar *path)
{
gchar *p;
if ((p = g_strrstr(path, "/"))) {
if (p == path)
*(p + 1) = '\0';
else
*p = '\0';
}
return path;
}
/* reads files in to fw's list store from an opened DIR struct */
void
read_files(FmWindow *fw, DIR *dir)
{
struct dirent *e;
struct stat st;
struct tm *time;
gchar *name_str;
gchar *mtime_str;
gchar *perms_str;
gchar *size_str;
GtkListStore *store = GTK_LIST_STORE(
gtk_tree_view_get_model(GTK_TREE_VIEW(fw->tree)));
GtkTreeIter iter;
GtkTreeSortable *sortable = GTK_TREE_SORTABLE(store);
/* remove previous entries */
gtk_list_store_clear(store);
/* disable sort to speed up insertion */
gtk_tree_sortable_set_sort_column_id(sortable,
GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
GTK_SORT_ASCENDING);
while ((e = readdir(dir))) {
if (valid_filename(e->d_name, fw->show_dot)
&& (stat(e->d_name, &st) == 0)) {
if (S_ISDIR(st.st_mode))
name_str = g_strdup_printf("%s/", e->d_name);
else
name_str = g_strdup(e->d_name);
time = localtime(&st.st_mtime);
mtime_str = create_time_str(timefmt, time);
perms_str = create_perm_str(st.st_mode);
size_str = create_size_str(st.st_size);
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
NAME_STR, name_str,
PERMS_STR, perms_str,
SIZE_STR, size_str,
MTIME_STR, mtime_str,
IS_DIR, S_ISDIR(st.st_mode),
-1);
g_free(name_str);
g_free(mtime_str);
g_free(perms_str);
g_free(size_str);
}
}
/* reenable sort */
gtk_tree_sortable_set_sort_column_id(sortable, NAME_STR, GTK_SORT_ASCENDING);
}
/* reload a FmWindow */
void
reload(FmWindow *fw)
{
open_directory(fw, fw->path);
}
void
set_path(FmWindow *fw, const Arg *arg)
{
char *path;
if ((path = arg->v)) {
open_directory(fw, path);
} else if ((path = text_dialog(GTK_WINDOW(fw->win), "path", fw->path))) {
open_directory(fw, path);
g_free(path);
}
}
/* change working directory and spawns a program to the background */
void
spawn(const gchar * const *argv, const gchar *path)
{
if (fork() == 0) {
g_setenv("DFM_PATH", path, TRUE);
chdir(path);
execvp(*argv, (gchar **)argv);
g_warning("spawn: %s", strerror(errno));
}
}
gchar*
text_dialog(GtkWindow *p, const gchar *title, const gchar *text)
{
GtkWidget *dialog = gtk_dialog_new_with_buttons(title, p,
GTK_DIALOG_MODAL, NULL);
GtkWidget *entry = gtk_entry_new();
GtkWidget *area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
gchar *str = NULL;
if (text)
gtk_entry_set_text(GTK_ENTRY(entry), text);
g_signal_connect(G_OBJECT(entry), "activate",
G_CALLBACK(text_dialog_enter), dialog);
gtk_container_add(GTK_CONTAINER(area), entry);
gtk_widget_show(entry);
if (gtk_dialog_run(GTK_DIALOG(dialog)) == 1)
str = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
/* clean up */
gtk_widget_destroy(dialog);
return str;
}
void
text_dialog_enter(GtkWidget *w, GtkDialog *dialog)
{
gtk_dialog_response(dialog, 1);
}
/* toggle preferences in a FmWindow, and reload if necessary */
void
toggle_pref(FmWindow *fw, const Arg *arg)
{
switch (arg->i) {
case DOTFILES:
fw->show_dot = !fw->show_dot;
reload(fw);
break;
}
}
void
update(FmWindow *fw)
{
time_t mtime = 0;
if (fw->path) {
if (get_mtime(fw->path, &mtime) != 0 || mtime > fw->mtime) {
/* directory updated or removed, reload */
reload(fw);
}
}
}
void*
update_thread(void *v)
{
GList *p;
for (;;) {
sleep(polltime);
gdk_threads_enter();
for (p = windows; p != NULL; p = g_list_next(p))
update((FmWindow *)p->data);
gdk_threads_leave();
}
return NULL;
}
/* returns 1 if valid filename, i.e. not '.' or '..' (or .* if show_dot = 0) */
int
valid_filename(const char *s, int show_dot)
{
return show_dot ?
(g_strcmp0(s, ".") != 0 && g_strcmp0(s, "..") != 0) :
*s != '.';
}
int
main(int argc, char *argv[])
{
Arg arg;
pthread_t u_tid;
pid_t pid;
gboolean silent = FALSE;
int i;
/* read arguments */
for(i = 1; i < argc && argv[i][0] == '-'; i++) {
switch(argv[i][1]) {
case 'v':
g_print("%s\n", VERSION);
exit(EXIT_SUCCESS);
case 'd':
show_dotfiles = TRUE;
break;
case 's':
silent = TRUE;
break;
default:
g_printerr("Usage: %s [-v] [-d] [-s] PATH\n", argv[0]);
exit(EXIT_FAILURE);
}
}
arg.v = i < argc ? argv[i] : ".";
if ((pid = fork()) > 0)
return EXIT_SUCCESS;
else if (pid < 0)
printf("fork: %s\n", g_strerror(errno));
if (silent) {
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
/* initialize threads */
g_thread_init(NULL);
gdk_threads_init();
gdk_threads_enter();
gtk_init(&argc, &argv);
newwin(NULL, &arg);
/* create update thread */
pthread_create(&u_tid, NULL, update_thread, NULL);
gtk_main();
gdk_threads_leave();
return EXIT_SUCCESS;
}

Binary file not shown.

View File

@ -1,28 +0,0 @@
#! /bin/bash
#
# Simple program executor
# Directs all output to /dev/null
DEFAULT_PROGRAM="gvim"
function get_mime() {
MIME=`file --mime-type "$1" | cut -d ':' -f 2- | cut -b 2-`
echo $MIME
}
M=$(get_mime "$1")
PROGRAM=$DEFAULT_PROGRAM
echo $M
case $M in
"application/ogg" )
PROGRAM="mplayer" ;;
"application/pdf" )
PROGRAM="xpdf" ;;
"image/jpeg" )
PROGRAM="gpicview" ;;
esac
$PROGRAM "$1" &> /dev/null

View File

@ -1,4 +0,0 @@
#ifndef _VERSION_H_
#define _VERSION_H_
#define VERSION "dfm commit e59b1aa (2020-11-30 22:13:27 -0800)"
#endif