e16-epplets/epplets/E-Mountbox.c

1812 lines
42 KiB
C

/* E-Mountbox.c
*
* Copyright (C) 1999-2000 Christian Kreibich
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <dirent.h>
#include "config.h"
#include "epplet.h"
#define FSTAB "/etc/fstab"
#define PROCMOUNTS "/proc/mounts"
#define ETCMTAB "/etc/mtab"
#define __BG_IMAGE "E-Mountbox-bg.png"
#define __DEFAULT "E-Mountbox-blockdev.png"
static struct {
const char *key, *value;
} defaults[] = {
{"BG_IMAGE", "E-Mountbox-bg.png"},
{"DEFAULT", "E-Mountbox-blockdev.png"},
{"EJECT_MODE", "2"},
{"DO_POLL", "1"},
{"POLLINTVAL", "5"}
};
static const char *default_types[] = {
"cd E-Mountbox-cd.png",
"fd E-Mountbox-floppy.png",
"zip E-Mountbox-zip.png",
"jazz E-Mountbox-jazz.png"
};
typedef enum {
NO_EJECT,
MANUAL_EJECT,
AUTO_EJECT
} EjectMode;
typedef struct _tile Tile;
typedef struct _mountpointtype MountPointType;
typedef struct {
EjectMode eject_mode;
int do_polling;
int polling_interval;
int anim_mount;
int show_buttons;
} Mode;
struct _mountpointtype {
char *key;
char *imagefile;
Imlib_Image *image;
MountPointType *next;
MountPointType *prev;
};
typedef struct {
char *device;
char *path;
char mounted;
} MountPoint;
struct _tile {
Imlib_Image *image;
MountPoint *mountpoint;
Tile *prev;
Tile *next;
};
static Mode mode;
static Tile *tiles = NULL;
static Tile *current_tile = NULL;
static int current_tile_index = 0;
static int num_tiles = 0;
static MountPointType *types = NULL;
static int num_types = 0;
static Imlib_Image *bg_image = NULL;
static Imlib_Image *default_image = NULL;
static Epplet_gadget action_area, button_close, button_config, button_help;
/* stuff for the config win */
static Epplet_gadget tbox_key, tbox_file, tbox_default, tbox_bg;
static Epplet_gadget arrow_left, arrow_right, button_add, button_del,
button_add_long;
static Epplet_gadget label_key, label_file, label_interval, label_slider,
hslider_interval;
static Epplet_gadget togglebutton_no_eject, togglebutton_manual_eject,
togglebutton_auto_eject;
static int ejectbuttons[3];
static Window config_win = 0;
static MountPointType *current_type = NULL;
static RGB_buf window_buf = NULL; /* the currently displayed mountpoint */
static RGB_buf widescreen_buf = NULL; /* the wide image of all mountpoints */
static RGB_buf widescreen_canvas_buf = NULL; /* only the background */
/* graphx handling */
static int IsTransparent(Imlib_Image * im, int x, int y);
static void FreeImages(void);
/* mount handling */
static void SetupMounts(void);
static void FreeMounts(void);
static void FreeMountPointTypes(void);
static void AddMountPointType(char *key, char *image);
static void ModifyMountPointType(MountPointType * mpt, const char *key,
const char *imagefile);
static void DeleteMountPointType(MountPointType * mpt);
static void UpdatePolling(void);
/* miscellaneous nitty gritty */
static int ParseFstab(void);
static int ParseProcMounts(void);
static int ParseEtcMtab(void);
static void VisitMountPoints(void);
static void SyncConfigs(void);
/* callbacks/ handlers */
/*
static void CallbackEnter(void *data, Window w);
static void CallbackLeave(void *data, Window w);
*/
static void CallbackSlideLeft(void *data);
static void CallbackSlideRight(void *data);
static void Callback_DefaultChange(void *data);
static void Callback_BGChange(void *data);
static void Callback_TypeChange(void *data);
#ifdef HAVE_EJECT
static void Callback_EjectType(void *data);
#endif
/* config stuff */
static void SetupDefaults(void);
static void SetupGraphx(void);
static void
error_exit(void)
{
Esync();
exit(1);
}
static void
UpdateGraphics(void)
{
/* ok, this is cheap. */
FreeMounts();
FreeMountPointTypes();
FreeImages();
SetupDefaults();
SetupMounts();
SetupGraphx();
}
static void
ConfigUpdateDialog(void *data __UNUSED__)
{
if (current_type)
{
Epplet_gadget_hide(button_add_long);
Epplet_gadget_show(tbox_key);
Epplet_gadget_show(tbox_file);
Epplet_gadget_show(arrow_left);
Epplet_gadget_show(button_add);
Epplet_gadget_show(button_del);
Epplet_gadget_show(arrow_right);
Epplet_gadget_show(label_key);
Epplet_gadget_show(label_file);
}
else
{
Epplet_gadget_show(button_add_long);
Epplet_gadget_hide(tbox_key);
Epplet_gadget_hide(tbox_file);
Epplet_gadget_hide(arrow_left);
Epplet_gadget_hide(button_add);
Epplet_gadget_hide(button_del);
Epplet_gadget_hide(arrow_right);
Epplet_gadget_hide(label_key);
Epplet_gadget_hide(label_file);
}
if (mode.do_polling)
{
Epplet_gadget_show(hslider_interval);
Epplet_gadget_show(label_slider);
Epplet_gadget_show(label_interval);
}
else
{
Epplet_gadget_hide(hslider_interval);
Epplet_gadget_hide(label_slider);
Epplet_gadget_hide(label_interval);
}
}
static void
CallbackShowMore(void *data __UNUSED__)
{
if (!mode.show_buttons)
{
Epplet_gadget_show(button_help);
Epplet_gadget_show(button_config);
Epplet_gadget_show(button_close);
}
else
{
Epplet_gadget_hide(button_help);
Epplet_gadget_hide(button_config);
Epplet_gadget_hide(button_close);
}
mode.show_buttons = !(mode.show_buttons);
}
#if 0
/* don't need that right now. */
static void
CallbackEnter(void *data, Window w)
{
Epplet_gadget_show(button_more);
}
static void
CallbackLeave(void *data, Window w)
{
Epplet_gadget_hide(button_more);
}
#endif
static void
CallbackKeyPress(void *data __UNUSED__, Window win __UNUSED__, char *key)
{
if (key)
{
if (!strcmp(key, "Left"))
{
CallbackSlideLeft(NULL);
}
else if (!strcmp(key, "Right"))
{
CallbackSlideRight(NULL);
}
}
}
static void
CallbackHelp(void *data __UNUSED__)
{
Epplet_show_about("E-Mountbox");
CallbackShowMore(NULL);
}
static void
Callback_ConfigOK(void *data __UNUSED__)
{
Callback_DefaultChange(NULL);
Callback_BGChange(NULL);
Callback_TypeChange(NULL);
SyncConfigs();
Epplet_save_config();
UpdatePolling();
UpdateGraphics();
Epplet_window_hide(config_win);
config_win = 0;
}
static void
Callback_ConfigApply(void *data __UNUSED__)
{
Callback_DefaultChange(NULL);
Callback_BGChange(NULL);
Callback_TypeChange(NULL);
SyncConfigs();
UpdatePolling();
UpdateGraphics();
/* Oh man. Of course current_type is now invalid. Banging head ... */
current_type = types;
if (current_type)
{
Epplet_change_textbox(tbox_key, current_type->key);
Epplet_change_textbox(tbox_file, current_type->imagefile);
}
else
{
Epplet_change_textbox(tbox_key, "");
Epplet_change_textbox(tbox_file, "");
}
}
static void
Callback_ConfigCancel(void *data __UNUSED__)
{
Epplet_load_config();
UpdateGraphics();
Epplet_window_hide(config_win);
config_win = 0;
}
static void
Callback_DefaultChange(void *data __UNUSED__)
{
Epplet_modify_config("DEFAULT", Epplet_textbox_contents(tbox_default));
}
static void
Callback_BGChange(void *data __UNUSED__)
{
Epplet_modify_config("BG_IMAGE", Epplet_textbox_contents(tbox_bg));
}
static void
Callback_TypeChange(void *data __UNUSED__)
{
ModifyMountPointType(current_type, Epplet_textbox_contents(tbox_key),
Epplet_textbox_contents(tbox_file));
}
static void
Callback_ConfigLeft(void *data __UNUSED__)
{
if (current_type)
{
if (current_type->prev)
{
ModifyMountPointType(current_type,
Epplet_textbox_contents(tbox_key),
Epplet_textbox_contents(tbox_file));
current_type = current_type->prev;
Epplet_change_textbox(tbox_key, current_type->key);
Epplet_change_textbox(tbox_file, current_type->imagefile);
}
}
}
static void
Callback_ConfigRight(void *data __UNUSED__)
{
if (current_type)
{
if (current_type->next)
{
ModifyMountPointType(current_type,
Epplet_textbox_contents(tbox_key),
Epplet_textbox_contents(tbox_file));
current_type = current_type->next;
Epplet_change_textbox(tbox_key, current_type->key);
Epplet_change_textbox(tbox_file, current_type->imagefile);
}
}
}
static void
Callback_ConfigAdd(void *data __UNUSED__)
{
if (num_types == 0)
{
current_type = NULL;
ConfigUpdateDialog(NULL);
}
ModifyMountPointType(current_type, Epplet_textbox_contents(tbox_key),
Epplet_textbox_contents(tbox_file));
AddMountPointType(NULL, NULL);
current_type = types;
Epplet_reset_textbox(tbox_key);
Epplet_reset_textbox(tbox_file);
}
static void
Callback_ConfigDel(void *data __UNUSED__)
{
if (current_type)
{
if (current_type->next)
{
current_type = current_type->next;
DeleteMountPointType(current_type->prev);
}
else if (current_type->prev)
{
current_type = current_type->prev;
DeleteMountPointType(current_type->next);
}
else
{
DeleteMountPointType(current_type);
current_type = NULL;
}
}
if (current_type)
{
Epplet_change_textbox(tbox_key, current_type->key);
Epplet_change_textbox(tbox_file, current_type->imagefile);
}
else
{
ConfigUpdateDialog(NULL);
}
}
static void
Callback_ConfigInterval(void *data __UNUSED__)
{
char s[64];
Esnprintf(s, sizeof(s), "%i s", mode.polling_interval);
Epplet_change_label(label_interval, s);
}
#ifdef HAVE_EJECT
static void
Callback_EjectType(void *data)
{
EjectMode ej_mode = (EjectMode) data;
mode.eject_mode = ej_mode;
switch (ej_mode)
{
case NO_EJECT:
ejectbuttons[0] = 1;
ejectbuttons[1] = 0;
ejectbuttons[2] = 0;
break;
case MANUAL_EJECT:
ejectbuttons[0] = 0;
ejectbuttons[1] = 1;
ejectbuttons[2] = 0;
break;
case AUTO_EJECT:
default:
ejectbuttons[0] = 0;
ejectbuttons[1] = 0;
ejectbuttons[2] = 1;
break;
}
Epplet_gadget_data_changed(togglebutton_no_eject);
Epplet_gadget_data_changed(togglebutton_manual_eject);
Epplet_gadget_data_changed(togglebutton_auto_eject);
}
#endif
static void
CallbackConfigure(void *data __UNUSED__)
{
current_type = types;
if (!config_win)
{
/* the position of some dialog items depends */
/* on whether eject is available or not ... */
#ifdef HAVE_EJECT
config_win =
Epplet_create_window_config(420, 280, "E-Mountbox Configuration",
Callback_ConfigOK, &config_win,
Callback_ConfigApply, &config_win,
Callback_ConfigCancel, &config_win);
#else
config_win =
Epplet_create_window_config(420, 220, "E-Mountbox Configuration",
Callback_ConfigOK, &config_win,
Callback_ConfigApply, &config_win,
Callback_ConfigCancel, &config_win);
#endif
Epplet_gadget_show(Epplet_create_label(12, 10, "Default icon", 2));
Epplet_gadget_show((tbox_default =
Epplet_create_textbox(NULL,
Epplet_query_config
("DEFAULT"), 10, 23, 400, 20,
2, Callback_DefaultChange,
NULL)));
Epplet_gadget_show(Epplet_create_label(12, 55, "Background", 2));
Epplet_gadget_show((tbox_bg =
Epplet_create_textbox(NULL,
Epplet_query_config
("BG_IMAGE"), 10, 68, 400, 20,
2, Callback_BGChange, NULL)));
label_key = Epplet_create_label(12, 100, "Pattern", 2);
label_file = Epplet_create_label(72, 100, "Image file", 2);
if (current_type)
{
tbox_key =
Epplet_create_textbox(NULL, current_type->key, 10, 113, 60, 20,
2, Callback_TypeChange, NULL);
tbox_file =
Epplet_create_textbox(NULL, current_type->imagefile, 70, 113,
340, 20, 2, Callback_TypeChange, NULL);
}
else
{
tbox_key =
Epplet_create_textbox(NULL, "", 10, 113, 60, 20, 2,
Callback_TypeChange, NULL);
tbox_file =
Epplet_create_textbox(NULL, "", 70, 113, 340, 20, 2,
Callback_TypeChange, NULL);
}
arrow_left =
Epplet_create_button(NULL, NULL, 170, 140, 0, 0, "ARROW_LEFT", 0,
NULL, Callback_ConfigLeft, NULL);
button_add =
Epplet_create_button("Add", NULL, 187, 140, 24, 12, NULL, 0, NULL,
Callback_ConfigAdd, NULL);
button_add_long =
Epplet_create_button("Add mountpoint type", NULL, 165, 120, 110, 16,
NULL, 0, NULL, Callback_ConfigAdd, NULL);
button_del =
Epplet_create_button("Delete", NULL, 216, 140, 36, 12, NULL, 0, NULL,
Callback_ConfigDel, NULL);
arrow_right =
Epplet_create_button(NULL, NULL, 257, 140, 0, 0, "ARROW_RIGHT", 0,
NULL, Callback_ConfigRight, NULL);
#ifdef HAVE_EJECT
switch (mode.eject_mode)
{
case NO_EJECT:
ejectbuttons[0] = 1;
ejectbuttons[1] = 0;
ejectbuttons[2] = 0;
break;
case MANUAL_EJECT:
ejectbuttons[0] = 0;
ejectbuttons[1] = 1;
ejectbuttons[2] = 0;
break;
case AUTO_EJECT:
default:
ejectbuttons[0] = 0;
ejectbuttons[1] = 0;
ejectbuttons[2] = 1;
break;
}
Epplet_gadget_show(Epplet_create_label
(170, 160, "Don't eject media when unmounting", 2));
Epplet_gadget_show((togglebutton_no_eject =
Epplet_create_togglebutton("", NULL, 150, 160, 12,
12, &ejectbuttons[0],
Callback_EjectType,
(void *)NO_EJECT)));
Epplet_gadget_show(Epplet_create_label
(170, 180, "Manually eject unmounted media", 2));
Epplet_gadget_show((togglebutton_manual_eject =
Epplet_create_togglebutton("", NULL, 150, 180, 12,
12, &ejectbuttons[1],
Callback_EjectType,
(void *)MANUAL_EJECT)));
Epplet_gadget_show(Epplet_create_label
(170, 200, "Eject media when unmounting", 2));
Epplet_gadget_show((togglebutton_auto_eject =
Epplet_create_togglebutton("", NULL, 150, 200, 12,
12, &ejectbuttons[2],
Callback_EjectType,
(void *)AUTO_EJECT)));
Epplet_gadget_show(Epplet_create_label
(170, 220, "Watch status of mountpoints", 2));
Epplet_gadget_show(Epplet_create_togglebutton
("", NULL, 150, 220, 12, 12, &mode.do_polling,
ConfigUpdateDialog, NULL));
Epplet_gadget_show(label_slider =
Epplet_create_label(170, 240, "Interval:", 2));
Epplet_gadget_show(hslider_interval =
Epplet_create_hslider(230, 242, 60, 1, 60, 1, 10,
&mode.polling_interval,
Callback_ConfigInterval,
NULL));
Epplet_gadget_show(label_interval =
Epplet_create_label(300, 240, "", 2));
#else
Epplet_gadget_show(Epplet_create_label
(170, 160, "Watch status of mountpoints", 2));
Epplet_gadget_show(Epplet_create_togglebutton
("", NULL, 150, 160, 12, 12, &mode.do_polling,
ConfigUpdateDialog, NULL));
Epplet_gadget_show(label_slider =
Epplet_create_label(170, 180, "Interval:", 2));
Epplet_gadget_show(hslider_interval =
Epplet_create_hslider(230, 182, 60, 1, 60, 1, 10,
&mode.polling_interval,
Callback_ConfigInterval,
NULL));
Epplet_gadget_show(label_interval =
Epplet_create_label(300, 180, "", 2));
#endif
Callback_ConfigInterval(NULL);
Epplet_window_pop_context();
}
ConfigUpdateDialog(NULL);
Epplet_window_show(config_win);
CallbackShowMore(NULL);
}
static void
CallbackAnimate(void *data __UNUSED__)
{
static double k = 0.0;
static double step = M_PI / 10.0;
int i, j, linear, linear_w;
double ratio;
unsigned char *current_tile_data;
imlib_context_set_image(current_tile->image);
current_tile_data = (unsigned char *)imlib_image_get_data();
if (k < M_PI)
{
if (mode.anim_mount)
ratio = ((cos(k) + 1.0) / 4.0) * 1.3;
else
ratio = ((cos(k + M_PI) + 1.0) / 4.0) * 1.3;
for (i = 0; i < 32; i++)
{
for (j = 0; j < 44; j++)
{
if (!IsTransparent(current_tile->image, j, i))
{
linear = 4 * (i * 44 + j);
linear_w =
(i * 44 * 4 * num_tiles) +
(current_tile_index * 44 * 4) + 4 * j;
Epplet_get_rgb_pointer(window_buf)[linear] =
Epplet_get_rgb_pointer(widescreen_buf)[linear_w] =
ratio *
(Epplet_get_rgb_pointer(widescreen_canvas_buf)
[linear_w]) + (1.0 -
ratio) * (current_tile_data[linear]);
Epplet_get_rgb_pointer(window_buf)[linear + 1] =
Epplet_get_rgb_pointer(widescreen_buf)[linear_w + 1] =
ratio *
(Epplet_get_rgb_pointer(widescreen_canvas_buf)
[linear_w + 1]) + (1.0 -
ratio) *
(current_tile_data[linear + 1]);
Epplet_get_rgb_pointer(window_buf)[linear + 2] =
Epplet_get_rgb_pointer(widescreen_buf)[linear_w + 2] =
ratio *
(Epplet_get_rgb_pointer(widescreen_canvas_buf)
[linear_w + 2]) + (1.0 -
ratio) *
(current_tile_data[linear + 2]);
}
}
}
Epplet_paste_buf(window_buf, Epplet_get_drawingarea_window(action_area),
-2, -2);
k += step;
Epplet_timer(CallbackAnimate, NULL, 0.05, "Anim");
}
else
k = 0.0;
}
static void
UpdateView(int dir, int fast)
{
int i, j;
double start_t, delta_t, wait;
double step = M_PI / 44;
if (dir == 0)
{
for (i = 0; i < 32; i++)
{
memcpy(Epplet_get_rgb_pointer(window_buf) + i * 44 * 4,
Epplet_get_rgb_pointer(widescreen_buf) +
(i * 44 * 4 * num_tiles) + (current_tile_index * 44 * 4),
44 * 4 * sizeof(unsigned char));
}
Epplet_paste_buf(window_buf, Epplet_get_drawingarea_window(action_area),
-2, -2);
}
else
{
for (j = 0; j <= 44; j++)
{
if (!fast)
{
start_t = Epplet_get_time();
wait = fabs(cos(j * step)) / 100.0;
while ((delta_t = Epplet_get_time() - start_t) < wait);
}
for (i = 0; i < 32; i++)
{
memcpy(Epplet_get_rgb_pointer(window_buf) + i * 44 * 4,
Epplet_get_rgb_pointer(widescreen_buf) +
(i * 44 * 4 * num_tiles) +
(current_tile_index * 44 * 4) + (dir) * j * 4,
44 * 4 * sizeof(unsigned char));
}
Epplet_paste_buf(window_buf,
Epplet_get_drawingarea_window(action_area), -2,
-2);
}
}
}
static int
IsTransparent(Imlib_Image * im, int x, int y)
{
int linear;
unsigned char *data;
if (!im || x < 0 || y < 0)
return 0;
imlib_context_set_image(im);
if (x >= imlib_image_get_width() || y >= imlib_image_get_height())
return 0;
linear = 4 * (y * imlib_image_get_width() + x);
data = (unsigned char *)imlib_image_get_data();
if (data[linear + 3] != 0xff)
return 0; /* FIXME - Should return 1 but blending needs to be fixed */
return 0;
}
/* mount handling */
static void
SetupMounts(void)
{
/* first, parse /etc/fstab to see what user-mountable mountpoints we have */
if (!(ParseFstab()))
{
/* Couldn't read /etc/fstab */
Epplet_dialog_ok("Could not read mountpoint information.");
error_exit();
}
/* do we have user-mountable fs's at all? */
if (num_tiles == 0)
{
Epplet_dialog_ok("Could not find any usable mountpoints.");
error_exit();
}
/* now, check if these are actually mounted already */
/* check for /proc/mounts */
if (!(ParseProcMounts()))
/* no? ok, check for /etc/mtab */
if (!(ParseEtcMtab()))
/* damnit, look if files exist in the mountpoints. */
VisitMountPoints();
/* Man, this code has far too many comments :) */
}
static void
AddMountPoint(char *device, char *path)
{
Tile *newtile = NULL;
char *tmp_dev = NULL;
char *tmp_path = NULL;
int i;
const char *s;
MountPointType *type = NULL;
Imlib_Image *tmp_image = NULL;
static Tile *tail_tile = NULL;
if (!tiles)
{
tiles = (Tile *) malloc(sizeof(Tile));
if (tiles)
{
memset(tiles, 0, sizeof(Tile));
num_tiles = 1;
current_tile = tail_tile = tiles;
}
}
else
{
newtile = (Tile *) malloc(sizeof(Tile));
if (newtile)
{
memset(newtile, 0, sizeof(Tile));
newtile->next = NULL;
newtile->prev = tail_tile;
tail_tile->next = newtile;
tail_tile = newtile;
num_tiles++;
}
}
current_tile_index = 0;
if (tail_tile)
{
tail_tile->mountpoint = (MountPoint *) malloc(sizeof(MountPoint));
if (tail_tile->mountpoint)
{
memset(tail_tile->mountpoint, 0, sizeof(MountPoint));
if (device)
tail_tile->mountpoint->device = strdup(device);
if (path)
tail_tile->mountpoint->path = strdup(path);
}
if (device && path)
{
tmp_path = strdup(path);
tmp_dev = strdup(device);
for (i = 0; i < (int)strlen(tmp_path); i++)
tmp_path[i] = (char)(tolower(tmp_path[i]));
for (i = 0; i < (int)strlen(tmp_dev); i++)
tmp_dev[i] = (char)(tolower(tmp_dev[i]));
if (tmp_path && tmp_dev)
{
type = types;
while (type)
{
if (strstr(tmp_dev, type->key))
{
tail_tile->image = type->image;
break;
}
else if (strstr(tmp_path, type->key))
{
tail_tile->image = type->image;
break;
}
type = type->next;
}
if (!tail_tile->image)
{
s = Epplet_query_config("DEFAULT");
if (!default_image)
{
tmp_image = imlib_load_image(s);
if (!tmp_image)
{
char buf[1024];
Esnprintf(buf, sizeof(buf), "%s/%s",
Epplet_data_dir(), __DEFAULT);
tmp_image = imlib_load_image(buf);
}
if (!tmp_image)
{
Epplet_dialog_ok
(" E-Mountbox could not load a default icon\n "
" for the mountpoints. Check your installation. ");
error_exit();
}
imlib_context_set_image(tmp_image);
default_image =
imlib_create_cropped_scaled_image(0, 0,
imlib_image_get_width
(),
imlib_image_get_height
(), 44, 32);
imlib_free_image();
}
tail_tile->image = default_image;
}
free(tmp_path);
free(tmp_dev);
}
}
}
}
static void
AddMountPointType(char *key, char *image)
{
MountPointType *newtype = NULL;
Imlib_Image *tmp_image = NULL;
if (!types)
{
types = (MountPointType *) malloc(sizeof(MountPointType));
if (types)
{
memset(types, 0, sizeof(MountPointType));
num_types = 1;
}
}
else
{
newtype = (MountPointType *) malloc(sizeof(MountPointType));
if (newtype)
{
memset(newtype, 0, sizeof(MountPointType));
newtype->next = types;
types->prev = newtype;
types = newtype;
num_types++;
}
}
if (types)
{
if ((!types->key) && (!types->image))
{
if (key)
types->key = strdup(key);
if (image)
types->imagefile = strdup(image);
tmp_image = imlib_load_image(image);
if (tmp_image)
{
imlib_context_set_image(tmp_image);
types->image =
imlib_create_cropped_scaled_image(0, 0,
imlib_image_get_width(),
imlib_image_get_height(),
44, 32);
imlib_free_image();
}
}
}
}
static void
ModifyMountPointType(MountPointType * mpt, const char *key,
const char *imagefile)
{
if (mpt)
{
if (key)
{
if (mpt->key)
free(mpt->key);
mpt->key = strdup(key);
}
if (imagefile)
{
if (mpt->imagefile)
free(mpt->imagefile);
mpt->imagefile = strdup(imagefile);
}
}
}
static void
DeleteMountPointType(MountPointType * mpt)
{
if (mpt)
{
/* is it in the middle */
if (mpt->next && mpt->prev)
{
mpt->prev->next = mpt->next;
mpt->next->prev = mpt->prev;
}
/* or at the beginning */
else if (mpt->next)
{
mpt->next->prev = NULL;
types = mpt->next;
}
/* or at the end ... */
else if (mpt->prev)
{
mpt->prev->next = NULL;
}
num_types--;
if (num_types == 0)
{
types = NULL;
}
/* free it */
if (mpt->key)
{
free(mpt->key);
}
if (mpt->imagefile)
{
free(mpt->imagefile);
}
if (mpt->image)
{
imlib_context_set_image(mpt->image);
imlib_free_image();
mpt->image = NULL;
}
free(mpt);
}
}
static void
FreeImages(void)
{
if (bg_image)
{
imlib_context_set_image(bg_image);
imlib_free_image();
bg_image = NULL;
}
if (default_image)
{
imlib_context_set_image(default_image);
imlib_free_image();
default_image = NULL;
}
}
static void
FreeMounts(void)
{
Tile *current, *tmp;
current = tiles;
while (current)
{
if (current->mountpoint)
{
if (current->mountpoint->device)
free(current->mountpoint->device);
if (current->mountpoint->path)
free(current->mountpoint->path);
free(current->mountpoint);
}
/* images need _not_ be freed here */
tmp = current;
current = current->next;
free(tmp);
}
tiles = NULL;
num_tiles = 0;
}
static void
FreeMountPointTypes(void)
{
MountPointType *current, *tmp;
current = types;
while (current)
{
if (current->key)
{
free(current->key);
}
if (current->imagefile)
{
free(current->imagefile);
}
if (current->image)
{
imlib_context_set_image(current->image);
imlib_free_image();
current->image = NULL;
}
tmp = current;
current = current->next;
free(tmp);
}
types = NULL;
num_types = 0;
}
static void
Mount(MountPoint * mp)
{
char s[1024];
if (mp)
{
if (mp->mounted)
return;
if (mp->path)
{
Esnprintf(s, sizeof(s), "%s %s", MOUNT, mp->path);
if (!Epplet_run_command(s))
{
mp->mounted = 1;
mode.anim_mount = 1;
Epplet_timer(CallbackAnimate, NULL, 0, "Anim");
}
else
{
Epplet_dialog_ok("Could not mount %s.", mp->path);
}
}
}
}
static void
Umount(MountPoint * mp)
{
char s[1024];
s[0] = 0;
if (mp)
{
if (!(mp->mounted))
return;
if (mp->path)
{
Esnprintf(s, sizeof(s), "%s %s", UMOUNT, mp->path);
if (!Epplet_run_command(s))
{
mp->mounted = 0;
mode.anim_mount = 0;
Epplet_timer(CallbackAnimate, NULL, 0, "Anim");
#ifdef HAVE_EJECT
if (mode.eject_mode == AUTO_EJECT)
{
Esnprintf(s, sizeof(s), "%s %s", EJECT, mp->device);
Epplet_run_command(s);
}
#endif
}
else
{
Epplet_dialog_ok("Could not unmount %s.", mp->path);
}
}
}
}
static int
ParseFstab(void)
{
FILE *f;
char s[1024];
char *token = NULL;
char *info[4];
int i;
if (!(f = fopen(FSTAB, "r")))
return 0;
*s = 0;
for (; fgets(s, sizeof(s), f);)
{
/* skip comments and blank lines */
if (!(*s) || (*s == '\n') || (*s == '#'))
{
continue;
}
for (i = 0; i < 4; i++)
info[i] = NULL;
/* parse out tokens we need */
i = 0;
token = strtok(s, " \t");
if (token)
{
info[i++] = strdup(token);
}
while ((token = strtok(NULL, " \t")))
{
info[i++] = strdup(token);
}
/* see if device is user-mountable */
if (strstr(info[3], "user"))
{
AddMountPoint(info[0], info[1]);
}
for (i = 0; i < 4; i++)
if (info[i])
free(info[i]);
}
fclose(f);
return 1;
}
static int
ParseProcMounts(void)
{
FILE *f;
char s[1024];
char *token = NULL, *device = NULL, *path = NULL;
Tile *tile;
if (!(f = fopen(PROCMOUNTS, "r")))
return 0;
*s = 0;
for (; fgets(s, sizeof(s), f);)
{
/* skip comments and blank lines (shouldn't be there, actually ...) */
if (!(*s) || (*s == '\n') || (*s == '#'))
{
continue;
}
/* parse out tokens we need */
token = strtok(s, " \t");
if (token)
{
device = strdup(token);
}
token = NULL;
token = strtok(NULL, " \t");
if (token)
{
path = strdup(token);
}
/* set that device mounted in our list ... */
tile = tiles;
while (tile)
{
if (tile->mountpoint)
{
if (!strcmp(tile->mountpoint->path, path))
{
tile->mountpoint->mounted = 1;
}
}
tile = tile->next;
}
if (device)
free(device);
if (path)
free(path);
}
fclose(f);
return 1;
}
static int
ParseEtcMtab(void)
{
FILE *f;
char s[1024];
char *token = NULL, *device = NULL, *path = NULL;
Tile *tile;
if (!(f = fopen(ETCMTAB, "r")))
return 0;
*s = 0;
for (; fgets(s, sizeof(s), f);)
{
/* skip comments and blank lines (shouldn't be there, actually ...) */
if (!(*s) || (*s == '\n') || (*s == '#'))
{
continue;
}
/* parse out tokens we need */
token = strtok(s, " \t");
if (token)
{
device = strdup(token);
}
token = NULL;
token = strtok(NULL, " \t");
if (token)
{
path = strdup(token);
}
/* set that device mounted in our list ... */
tile = tiles;
while (tile)
{
if (tile->mountpoint)
{
if (!strcmp(tile->mountpoint->path, path))
{
tile->mountpoint->mounted = 1;
}
}
tile = tile->next;
}
if (device)
free(device);
if (path)
free(path);
}
fclose(f);
return 1;
}
static void
VisitMountPoints(void)
{
DIR *dir;
int num_entries;
struct dirent *dp;
Tile *tile = NULL;
tile = tiles;
while (tile)
{
if (tile->mountpoint)
{
if (tile->mountpoint->path)
{
dir = NULL;
dir = opendir(tile->mountpoint->path);
if (dir)
{
num_entries = 0;
for (num_entries = 0; (dp = readdir(dir));
num_entries++);
if (num_entries > 2)
{
tile->mountpoint->mounted = 1;
}
}
}
}
tile = tile->next;
}
}
static MountPoint *
FindMountPointByClick(int x, int y)
{
if (!IsTransparent(current_tile->image, x, y))
return current_tile->mountpoint;
return NULL;
}
static void
PollMountpoints(void *data __UNUSED__)
{
Tile *tile;
int i, j, k, linear, linear_w, status = 0;
unsigned char *widescreen_data, *widescreen_canvas_data, *tile_data;
if (current_tile->mountpoint)
{
status = current_tile->mountpoint->mounted;
}
/* reset mount status */
tile = tiles;
while (tile)
{
if (tile->mountpoint)
{
tile->mountpoint->mounted = 0;
}
tile = tile->next;
}
/* get new mount status */
if (!(ParseProcMounts()))
if (!(ParseEtcMtab()))
VisitMountPoints();
/* build new image */
tile = tiles;
imlib_context_set_image(widescreen_buf->im);
widescreen_data = (unsigned char *)imlib_image_get_data();
imlib_context_set_image(widescreen_canvas_buf->im);
widescreen_canvas_data = (unsigned char *)imlib_image_get_data();
for (k = 0; k < num_tiles; k++, tile = tile->next)
{
imlib_context_set_image(tile->image);
tile_data = (unsigned char *)imlib_image_get_data();
for (i = 0; i < 32; i++)
{
for (j = 0; j < 44; j++)
{
if (!IsTransparent(tile->image, j, i))
{
linear = 4 * (i * 44 + j);
linear_w =
(i * 44 * 4 * num_tiles) + (k * 44 * 4) + 4 * j;
if (tile->mountpoint->mounted)
{
widescreen_data[linear_w] = tile_data[linear];
widescreen_data[linear_w + 1] =
tile_data[linear + 1];
widescreen_data[linear_w + 2] =
tile_data[linear + 2];
}
else
{
widescreen_data[linear_w] =
0.65 * widescreen_canvas_data[linear_w] +
0.35 * tile_data[linear];
widescreen_data[linear_w + 1] =
0.65 * widescreen_canvas_data[linear_w + 1] +
0.35 * tile_data[linear + 1];
widescreen_data[linear_w + 2] =
0.65 * widescreen_canvas_data[linear_w + 2] +
0.35 * tile_data[linear + 2];
}
}
}
}
}
/* see if current mountpoint is affected */
if (current_tile->mountpoint)
{
if (current_tile->mountpoint->mounted != status)
{
mode.anim_mount = current_tile->mountpoint->mounted;
CallbackAnimate(NULL);
}
}
Epplet_timer(PollMountpoints, NULL, (double)mode.polling_interval,
"POLLING");
}
static void
CallbackExit(void *data __UNUSED__)
{
FreeMounts();
FreeMountPointTypes();
FreeImages();
Epplet_unremember();
Esync();
exit(0);
}
static void
CallbackButtonUp(void *data __UNUSED__, Window win, int x, int y, int b)
{
MountPoint *mountpoint = NULL;
char s[1024];
if (win == Epplet_get_drawingarea_window(action_area))
{
mountpoint = FindMountPointByClick(x, y);
if (mountpoint)
{
if (b == 1)
{
if (mountpoint->mounted)
Umount(mountpoint);
else
Mount(mountpoint);
}
#ifdef HAVE_EJECT
else if (b == 3 && mode.eject_mode == MANUAL_EJECT)
{
Esnprintf(s, sizeof(s), "%s %s", EJECT, mountpoint->device);
Epplet_run_command(s);
}
#endif
else
{
Epplet_gadget popup = Epplet_create_popup();
s[0] = 0;
Esnprintf(s, sizeof(s), "%s at %s.", mountpoint->device,
mountpoint->path);
Epplet_add_popup_entry(popup, s, NULL, NULL, NULL);
Epplet_pop_popup(popup, 0);
}
}
}
}
static void
CallbackSlideLeft(void *data __UNUSED__)
{
if (current_tile->prev)
{
UpdateView(-1, 0);
current_tile = current_tile->prev;
current_tile_index--;
}
else
{
while (current_tile->next)
{
UpdateView(+1, 1);
current_tile = current_tile->next;
current_tile_index++;
}
}
}
static void
CallbackSlideRight(void *data __UNUSED__)
{
if (current_tile->next)
{
UpdateView(1, 0);
current_tile = current_tile->next;
current_tile_index++;
}
else
{
while (current_tile->prev)
{
UpdateView(-1, 1);
current_tile = current_tile->prev;
current_tile_index--;
}
}
}
static void
CallbackExpose(void *data __UNUSED__, Window win __UNUSED__, int x __UNUSED__,
int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
{
UpdateView(0, 0);
}
static void
SetupDefaults(void)
{
int i, instance, num_results;
char *s, s2[256], *key = NULL, *image = NULL, *token;
char **results = NULL;
for (i = 0; i < (int)(sizeof(defaults) / sizeof(ConfigItem)); i++)
{
if (!Epplet_query_config(defaults[i].key))
Epplet_add_config(defaults[i].key, defaults[i].value);
}
instance = atoi(Epplet_query_config_def("INSTANCE", "0"));
Esnprintf(s2, sizeof(s2), "%i", ++instance);
Epplet_modify_config("INSTANCE", s2);
mode.eject_mode = (EjectMode) atoi(Epplet_query_config("EJECT_MODE"));
mode.do_polling = atoi(Epplet_query_config("DO_POLL"));
mode.polling_interval = atoi(Epplet_query_config("POLLINTVAL"));
mode.anim_mount = 0;
mode.show_buttons = 0;
results = Epplet_query_multi_config("TYPEDEF", &num_results);
if ((!results) && (instance == 1))
{
Epplet_modify_multi_config("TYPEDEF", (char **)default_types,
(int)(sizeof(default_types) /
sizeof(char *)));
results = Epplet_query_multi_config("TYPEDEF", &num_results);
if (!results)
{
Epplet_dialog_ok(" Could not set up mountpoint types. \n"
" Check your installation. \n");
error_exit();
}
}
for (i = 0; i < num_results; i++)
{
if (results[i])
{
s = strdup(results[i]);
token = strtok(s, " \t");
if (token)
key = strdup(token);
token = strtok(NULL, " \t");
if (token)
image = strdup(token);
if (key && image)
{
AddMountPointType(key, image);
}
free(key);
free(image);
free(s);
}
}
free(results);
}
static void
SetupGraphx(void)
{
static int first_time = 1;
int i, j, k, linear, linear_w;
Imlib_Image *tmp = NULL;
Tile *tile;
const char *s;
char buf[1024];
unsigned char *widescreen_data, *widescreen_canvas_data, *tile_data,
*bg_data;
s = Epplet_query_config("BG_IMAGE");
tmp = imlib_load_image(s);
if (!tmp)
{
Esnprintf(buf, sizeof(buf), "%s/%s", Epplet_data_dir(), __BG_IMAGE);
tmp = imlib_load_image(buf);
}
if (!tmp)
{
/* Even the fallbacks didn't work. If we don't exit
* here, we'll seg fault. -- mej */
Epplet_dialog_ok("Could not load all images.");
Esync();
exit(-1);
}
/*
* sscanf(Epplet_query_config("BG_BORDER"), "%i %i %i %i",
* &(border.left), &(border.right), &(border.top), &(border.bottom));
* Imlib_set_image_border(id, tmp, &border);
*/
imlib_context_set_image(tmp);
bg_image =
imlib_create_cropped_scaled_image(0, 0, imlib_image_get_width(),
imlib_image_get_height(),
44 * num_tiles, 32);
imlib_free_image();
/* setup widescreen according to current mounts */
if (!window_buf)
window_buf = Epplet_make_rgb_buf(44, 32);
if (widescreen_buf)
Epplet_free_rgb_buf(widescreen_buf);
widescreen_buf = Epplet_make_rgb_buf((44 * num_tiles), 32);
if (widescreen_canvas_buf)
Epplet_free_rgb_buf(widescreen_canvas_buf);
widescreen_canvas_buf = Epplet_make_rgb_buf((44 * num_tiles), 32);
imlib_context_set_image(widescreen_buf->im);
widescreen_data = (unsigned char *)imlib_image_get_data();
imlib_context_set_image(widescreen_canvas_buf->im);
widescreen_canvas_data = (unsigned char *)imlib_image_get_data();
imlib_context_set_image(bg_image);
bg_data = (unsigned char *)imlib_image_get_data();
memcpy(widescreen_data, bg_data,
sizeof(unsigned char) * 44 * 4 * num_tiles * 32);
memcpy(widescreen_canvas_data, bg_data,
sizeof(unsigned char) * 44 * 4 * num_tiles * 32);
tile = tiles;
for (k = 0; k < num_tiles; k++, tile = tile->next)
{
imlib_context_set_image(tile->image);
tile_data = (unsigned char *)imlib_image_get_data();
for (i = 0; i < 32; i++)
{
for (j = 0; j < 44; j++)
{
if (!IsTransparent(tile->image, j, i))
{
linear = 4 * (i * 44 + j);
linear_w =
(i * 44 * 4 * num_tiles) + (k * 44 * 4) + 4 * j;
if (tile->mountpoint->mounted)
{
widescreen_data[linear_w] = tile_data[linear];
widescreen_data[linear_w + 1] =
tile_data[linear + 1];
widescreen_data[linear_w + 2] =
tile_data[linear + 2];
}
else
{
widescreen_data[linear_w] =
0.65 * widescreen_data[linear_w] +
0.35 * tile_data[linear];
widescreen_data[linear_w + 1] =
0.65 * widescreen_data[linear_w + 1] +
0.35 * tile_data[linear + 1];
widescreen_data[linear_w + 2] =
0.65 * widescreen_data[linear_w + 2] +
0.35 * tile_data[linear + 2];
}
}
}
}
}
if (first_time)
{
first_time = 0;
Epplet_gadget_show((Epplet_create_button(NULL, NULL,
2, 34, 0, 0, "ARROW_LEFT", 0,
NULL, CallbackSlideLeft,
NULL)));
Epplet_gadget_show((Epplet_create_button
(NULL, NULL, 33, 34, 0, 0, "ARROW_RIGHT", 0, NULL,
CallbackSlideRight, NULL)));
Epplet_gadget_show((action_area =
Epplet_create_drawingarea(2, 2, 44, 32)));
Epplet_gadget_show((Epplet_create_button
("...", NULL, 14, 34, 20, 12, NULL, 0, NULL,
CallbackShowMore, NULL)));
button_help =
Epplet_create_button(NULL, NULL, 3, 3, 0, 0, "HELP", 0, NULL,
CallbackHelp, NULL);
button_close =
Epplet_create_button(NULL, NULL, 33, 3, 0, 0, "CLOSE", 0, NULL,
CallbackExit, NULL);
button_config =
Epplet_create_button(NULL, NULL, 18, 3, 0, 0, "CONFIGURE", 0, NULL,
CallbackConfigure, NULL);
/*
* Epplet_register_focus_in_handler(CallbackEnter, NULL);
* Epplet_register_focus_out_handler(CallbackLeave, NULL);
*/
Epplet_register_expose_handler(CallbackExpose, NULL);
Epplet_register_button_release_handler(CallbackButtonUp, NULL);
Epplet_register_key_press_handler(CallbackKeyPress, NULL);
/* Setup the current view */
Epplet_show();
}
UpdateView(0, 0);
}
static void
UpdatePolling(void)
{
if (mode.do_polling)
{
Epplet_timer(PollMountpoints, NULL, (double)mode.polling_interval,
"POLLING");
}
else
{
Epplet_remove_timer("POLLING");
}
}
static void
SyncConfigs(void)
{
char **strings = NULL;
char s[1024];
int i;
MountPointType *mpt = NULL;
Esnprintf(s, sizeof(s), "%i", (int)mode.eject_mode);
Epplet_modify_config("EJECT_MODE", s);
Esnprintf(s, sizeof(s), "%i", mode.do_polling);
Epplet_modify_config("DO_POLL", s);
Esnprintf(s, sizeof(s), "%i", mode.polling_interval);
Epplet_modify_config("POLLINTVAL", s);
strings = (char **)malloc(sizeof(char *) * num_types);
if (strings)
{
for (mpt = types, i = 0; mpt; mpt = mpt->next, i++)
{
Esnprintf(s, sizeof(s), "%s %s", mpt->key, mpt->imagefile);
strings[i] = strdup(s);
}
Epplet_modify_multi_config("TYPEDEF", strings, num_types);
for (i = 0; i < num_types; i++)
if (strings[i])
free(strings[i]);
free(strings);
}
}
int
main(int argc, char **argv)
{
atexit(Epplet_cleanup);
Epplet_Init("E-Mountbox", "0.1", "Enlightenment Mount Epplet",
3, 3, argc, argv, 0);
Epplet_load_config();
SetupDefaults();
SetupMounts();
SetupGraphx();
UpdatePolling();
Epplet_Loop();
error_exit();
return 0;
}