pkg://xcdroast-debuginfo-0.98a15-14.fc7.ppc.rpm:614443/
usr/
src/
debug/
xcdroast-0.98alpha15/
src/menus.c
info downloads
/*
menus.c
27.3.99 tn
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define GTK_ENABLE_BROKEN
#include <gtk/gtk.h>
#if GTK_MAJOR_VERSION < 2
#include <gdk/gdk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#endif
#include "largefile.h"
#if HAVE_LOCALE_H
#include <locale.h>
#else
# define setlocale(Category, Locale)
#endif
#include "gettext.h"
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <errno.h>
#include <ctype.h>
#if ENABLE_NLS
# define _(String) gettext (String)
# define N_(String) gettext_noop (String)
#else
# define _(String) (String)
# define N_(String) (String)
#endif
#include "xcdrdata.h"
#include "xcdroast.h"
#include "main.h"
#include "../xpms/treefolderopen.xpm"
#include "../xpms/treefolderclosed.xpm"
#include "../xpms/filesmall.xpm"
#include "../xpms/minidata.xpm"
#include "../xpms/miniaudio.xpm"
#include "../xpms/mininodata.xpm"
extern gint debug;
extern GtkWidget *toplevel;
extern GtkWidget *splitspace;
extern GtkWidget *sidespace;
extern GtkWidget *workspace;
extern GtkWidget *actionspace;
extern scsi_devices_t **scsidevices;
extern writer_driver_t **blankmodes;
extern setup_data_t setupdata;
extern master_param_t masterparam;
extern cd_info_t cdinfo;
extern track_info_t **trackinfo;
extern GList *imagelist;
extern current_set_t curset;
extern track_read_set_t trackreadset;
extern gint read_done;
extern GList *tocfiles;
extern gint read_abort_mark;
extern gchar sharedir[MAXLINE];
extern GtkWidget *cdlist_l1, *imglist_l2;
extern GtkCList *cdlist, *imglist2;
extern gchar configdir[MAXLINE];
extern GtkWidget *isoopts[24];
extern master_param_t masterparam;
extern GtkWidget *mkisofs_calc_timeout_dialog;
extern GdkFont *fixedfont;
GtkWidget *ctree_okbutton;
GtkWidget *cddb_info_label;
GtkCList *cddb_clist;
GtkWidget *viewmode_dialog;
GtkWidget *readtrack_info_label, *readtrack_textview;
GtkWidget *readtrack_pbar1, *readtrack_pbar2;
GtkWidget *readtrack_pbar3, *readtrack_pbar4, *readtrack_spd;
GtkWidget *readtrack_small_info, *readtrack_small_info2, *readtrack_info_tbl;
gint dialog_done, dialog_done2, dialog_done3;
static GtkWidget *ctree_window;
static GtkWidget *ctree_entry;
static gint ctree_showfiles, ctree_showhidden;
static GtkCTreeNode *parent_node, *lastactive_node;
static GtkCTree *ctree_base;
static gchar *ctree_basedir;
static GtkWidget *cddb_info_okbutton;
static GtkWidget *cddb_window;
static GtkWidget *readtrack_button, *readtrack_savebutton;
static GtkWidget *readtrack_info_frame;
static GdkPixmap *pixmap1, *pixmap2, *pixmap3;
static GdkBitmap *mask1, *mask2, *mask3;
static GtkWidget *viewmode_scrolled;
static GtkWidget *blank_infolabel;
static GtkWidget *blank_text_window;
static GtkWidget *redir_entry;
static gint misc_timer;
static GtkWidget *cdtext_entry1[MAXTRACKS+1];
static GtkWidget *cdtext_entry2[MAXTRACKS+1];
static GtkWidget *varirec_label, *varirec_scale;
static GtkWidget *isolevel_label, *isolevel_scale;
extern void writeoptions_selected(GtkWidget *item, gpointer nr);
extern void isooptions_selected(GtkWidget *item, gpointer nr);
static gint dialog_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) {
dialog_done = -1;
return(TRUE);
}
static gint dialog_delete_event2(GtkWidget *widget, GdkEvent *event, gpointer data) {
dialog_done2 = -1;
return(TRUE);
}
static gint dialog_delete_event3(GtkWidget *widget, GdkEvent *event, gpointer data) {
dialog_done3 = -1;
return(TRUE);
}
static void dialog_btn_press(GtkWidget *widget, gpointer data) {
dialog_done = GPOINTER_TO_INT(data);
}
static void dialog_btn_press2(GtkWidget *widget, gpointer data) {
dialog_done2 = GPOINTER_TO_INT(data);
}
/* popup a modal window, set cursor to watch, return button pressed
or -1 when delete_event found.
Up to three buttons. Set unused buttons to NULL
Centers automatically above the toplevel-widow
if no toplevel window available center on display
specialcase: when defbutton -1, then dont set the window cursor
*/
gint show_dialog(gchar *icon_file, gchar *ttext, gchar *btn1, gchar *btn2, gchar *btn3, gint defbutton) {
GtkWidget *dialog;
GtkWidget *button1;
GtkWidget *button2;
GtkWidget *button3;
GtkWidget *box1,*box2;
GtkWidget *b1_t,*b1_sep,*pix,*lab;
gint xpos, ypos;
gint xsize, ysize;
GdkCursor *cursor;
/* GtkStyle *style; */
GtkRequisition rq;
#if GTK_MAJOR_VERSION < 2
GdkPixbuf *im;
GdkPixmap *pixmap;
GdkBitmap *mask;
gchar tmp[MAXLINE];
#else
gchar *ico;
#endif
/* if another dialog is running, ignore */
if (dialog_done == 999) {
return -1;
}
dodebug(8, "displaying show_dialog: %s\n", ttext);
/* mark our dialog as running */
dialog_done = 999;
/* create new window and position it relative to the main window */
dialog = my_gtk_dialog_new();
set_xcdr_title(dialog, NULL, -1);
/* make sure our window is always on top */
gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(toplevel));
gtk_signal_connect (GTK_OBJECT (dialog), "delete_event",
GTK_SIGNAL_FUNC (dialog_delete_event), (gpointer) dialog);
/* create layout for dialog */
box1 = gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(dialog),box1);
b1_t = gtk_table_new(1,10, TRUE);
gtk_container_border_width(GTK_CONTAINER(b1_t),10);
gtk_box_pack_start(GTK_BOX(box1),b1_t,FALSE,TRUE,10);
/* realize table to be able to put a pixmap in it */
gtk_widget_realize(b1_t);
/* style = gtk_widget_get_style(b1_t);
pixmap = gdk_pixmap_create_from_xpm_d(b1_t->window, &mask,
&style->bg[GTK_STATE_NORMAL],(gchar **)icon_xpm);
*/
#if GTK_MAJOR_VERSION < 2
g_snprintf(tmp,MAXLINE,"%s/%s", sharedir,icon_file);
dodebug(9, "dialog: trying to load %s\n", tmp);
im=gdk_pixbuf_new_from_file(tmp);
if (im) {
gdk_pixbuf_render_pixmap_and_mask(im, &pixmap, &mask, 128);
pix = gtk_pixmap_new(pixmap,mask);
gtk_table_attach_defaults(GTK_TABLE(b1_t), pix, 0,2,0,1);
gtk_widget_show(pix);
gdk_pixbuf_unref(im);
}
#else
ico = lookup_stock_icon(icon_file);
if (ico) {
pix = gtk_image_new_from_stock(ico, GTK_ICON_SIZE_DIALOG);
gtk_table_attach_defaults(GTK_TABLE(b1_t), pix, 0,2,0,1);
gtk_widget_show(pix);
}
#endif
lab = gtk_label_new(ttext);
gtk_table_attach_defaults(GTK_TABLE(b1_t), lab, 2,10,0,1);
b1_sep = gtk_hseparator_new();
gtk_box_pack_start(GTK_BOX(box1),b1_sep,FALSE,TRUE,0);
box2 = gtk_hbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,TRUE,10);
if (btn1 != NULL) {
button1 = gtk_button_new_with_label (btn1);
gtk_box_pack_start(GTK_BOX(box2),button1,TRUE,TRUE,10);
gtk_widget_show(button1);
gtk_signal_connect(GTK_OBJECT(button1),"clicked",
GTK_SIGNAL_FUNC(dialog_btn_press), GINT_TO_POINTER(0));
GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT);
if (defbutton == 0) gtk_widget_grab_default (button1);
}
if (btn2 != NULL) {
button2 = gtk_button_new_with_label (btn2);
gtk_box_pack_start(GTK_BOX(box2),button2,TRUE,TRUE,10);
gtk_widget_show(button2);
gtk_signal_connect(GTK_OBJECT(button2),"clicked",
GTK_SIGNAL_FUNC(dialog_btn_press), GINT_TO_POINTER(1));
GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT);
if (defbutton == 1) gtk_widget_grab_default (button2);
}
if (btn3 != NULL) {
button3 = gtk_button_new_with_label (btn3);
gtk_box_pack_start(GTK_BOX(box2),button3,TRUE,TRUE,10);
gtk_widget_show(button3);
gtk_signal_connect(GTK_OBJECT(button3),"clicked",
GTK_SIGNAL_FUNC(dialog_btn_press), GINT_TO_POINTER(2));
GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT);
if (defbutton == 2) gtk_widget_grab_default (button3);
}
gtk_widget_show(box2);
gtk_widget_show(b1_sep);
gtk_widget_show(lab);
gtk_widget_show(b1_t);
gtk_widget_show(box1);
cursor = NULL;
/* grab cursor and change to watch */
if (GTK_WIDGET_MAPPED(toplevel)) {
gtk_grab_add(dialog);
if (defbutton != -1) {
cursor = gdk_cursor_new(GDK_WATCH);
gdk_window_set_cursor(GTK_WIDGET(toplevel)->window,cursor);
dodebug(9, "showdialog: set cursor\n");
}
}
/* only center window when toplevel visible */
if ( GTK_WIDGET_VISIBLE(toplevel)) {
gtk_window_position(GTK_WINDOW(dialog),GTK_WIN_POS_NONE);
gdk_window_get_origin(GTK_WIDGET(toplevel)->window,&xpos,&ypos);
gdk_window_get_size(GTK_WIDGET(toplevel)->window,&xsize,&ysize);
gtk_widget_size_request(dialog,&rq);
gtk_widget_set_uposition(GTK_WIDGET(dialog),xpos+xsize/2-rq.width/2,ypos+ysize/2-rq.height/2);
} else {
/* otherwise center in screen */
gtk_window_position(GTK_WINDOW(dialog),GTK_WIN_POS_NONE);
xsize = gdk_screen_width();
ysize = gdk_screen_height();
gtk_widget_size_request(dialog,&rq);
gtk_widget_set_uposition(GTK_WIDGET(dialog),xsize/2-rq.width/2,ysize/2-rq.height/2);
}
gtk_widget_show(dialog);
/* if this is a warning sound bell (if requested in setup) */
if (strcmp(icon_file, ICO_WARN) == 0) {
dobeep(2);
}
/* now wait until button is pressed */
while (dialog_done == 999) {
wait_and_process_events();
}
if (GTK_WIDGET_MAPPED(toplevel)) {
gtk_grab_remove(GTK_WIDGET(dialog));
if (defbutton != -1) {
gdk_window_set_cursor(GTK_WIDGET(toplevel)->window,NULL);
if (cursor) gdk_cursor_destroy (cursor);
dodebug(9, "showdialog: restored cursor\n");
}
}
/* remove dialog window */
gtk_widget_destroy(dialog);
return dialog_done;
}
/* another version of the dialog -> with nice xcdroast logo on top */
gint show_fancy_dialog(gchar *htext, gchar *ttext, gchar *btn1) {
GtkWidget *dialog, *xcdroast_logo, *vbox;
GdkPixbuf *im, *im2;
GdkPixmap *p;
GdkBitmap *m;
GtkWidget *button1;
GtkWidget *box1,*box2, *f1, *l1, *lab;
gint xpos, ypos;
gint xsize, ysize;
GdkCursor *cursor;
GtkRequisition rq;
gchar tmp[MAXLINE];
/* if another dialog is running, ignore */
if (dialog_done == 999) {
return -1;
}
dodebug(8, "displaying show_fancy_dialog: %s\n", ttext);
/* mark our dialog as running */
dialog_done = 999;
/* create new window and position it relative to the main window */
dialog = my_gtk_dialog_new();
set_xcdr_title(dialog, NULL, -1);
/* make sure our window is always on top */
gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(toplevel));
gtk_signal_connect (GTK_OBJECT (dialog), "delete_event",
GTK_SIGNAL_FUNC (dialog_delete_event), (gpointer) dialog);
/* create layout for dialog */
box1 = gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(dialog),box1);
gtk_widget_show(box1);
/* load the half scaled logo */
g_snprintf(tmp,MAXLINE,"%s/%s", sharedir, XCDRLOGO);
#if GTK_MAJOR_VERSION < 2
im=gdk_pixbuf_new_from_file(tmp);
#else
im=gdk_pixbuf_new_from_file(tmp,NULL);
#endif
if (im) {
im2 = gdk_pixbuf_scale_simple(im,
gdk_pixbuf_get_width(im)/2,
gdk_pixbuf_get_height(im)/2,
GDK_INTERP_TILES);
gdk_pixbuf_render_pixmap_and_mask(im2, &p, &m, 128);
xcdroast_logo = gtk_pixmap_new(p,m);
gdk_pixbuf_unref(im);
gdk_pixbuf_unref(im2);
} else {
xcdroast_logo = gtk_label_new("[LOGO]");
}
gtk_box_pack_start(GTK_BOX(box1),xcdroast_logo,FALSE,FALSE,0);
gtk_widget_show(xcdroast_logo);
g_snprintf(tmp,MAXLINE,_("Version %s"),XCDROAST_VERSION);
l1 = gtk_label_new(tmp);
gtk_label_set_justify(GTK_LABEL(l1),GTK_JUSTIFY_CENTER);
set_font_and_color(l1,NULL,"red");
gtk_box_pack_start(GTK_BOX(box1),l1,FALSE,FALSE,0);
gtk_widget_show(l1);
f1 = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(box1),f1,TRUE,TRUE,0);
gtk_container_set_border_width(GTK_CONTAINER (f1),5);
gtk_widget_show(f1);
vbox = gtk_vbox_new(FALSE,0);
gtk_container_set_border_width(GTK_CONTAINER (vbox),10);
gtk_container_add(GTK_CONTAINER(f1),vbox);
gtk_widget_show(vbox);
/* print header text? */
if (htext) {
lab = gtk_label_new(htext);
set_font_and_color(lab,BOLDFONT,NULL);
gtk_label_set_justify(GTK_LABEL(lab),GTK_JUSTIFY_CENTER);
gtk_box_pack_start(GTK_BOX(vbox),lab,FALSE,FALSE,0);
gtk_widget_show(lab);
}
lab = gtk_label_new(ttext);
gtk_label_set_justify(GTK_LABEL(lab),GTK_JUSTIFY_CENTER);
gtk_box_pack_start(GTK_BOX(vbox),lab,FALSE,FALSE, 5);
gtk_widget_show(lab);
box2 = gtk_hbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,TRUE,10);
gtk_widget_show(box2);
if (btn1 != NULL) {
button1 = gtk_button_new_with_label (btn1);
gtk_box_pack_start(GTK_BOX(box2),button1,TRUE,TRUE,10);
gtk_widget_show(button1);
gtk_signal_connect(GTK_OBJECT(button1),"clicked",
GTK_SIGNAL_FUNC(dialog_btn_press), GINT_TO_POINTER(0));
GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT);
gtk_widget_grab_default (button1);
}
cursor = NULL;
/* grab cursor and change to watch */
if (GTK_WIDGET_MAPPED(toplevel)) {
gtk_grab_add(dialog);
cursor = gdk_cursor_new(GDK_WATCH);
gdk_window_set_cursor(GTK_WIDGET(toplevel)->window,cursor);
dodebug(9, "showdialog: set cursor\n");
}
/* only center window when toplevel visible */
if ( GTK_WIDGET_VISIBLE(toplevel)) {
gtk_window_position(GTK_WINDOW(dialog),GTK_WIN_POS_NONE);
gdk_window_get_origin(GTK_WIDGET(toplevel)->window,&xpos,&ypos);
gdk_window_get_size(GTK_WIDGET(toplevel)->window,&xsize,&ysize);
gtk_widget_size_request(dialog,&rq);
gtk_widget_set_uposition(GTK_WIDGET(dialog),xpos+xsize/2-rq.width/2,ypos+ysize/2-rq.height/2);
} else {
/* otherwise center in screen */
gtk_window_position(GTK_WINDOW(dialog),GTK_WIN_POS_NONE);
xsize = gdk_screen_width();
ysize = gdk_screen_height();
gtk_widget_size_request(dialog,&rq);
gtk_widget_set_uposition(GTK_WIDGET(dialog),xsize/2-rq.width/2,ysize/2-rq.height/2);
}
gtk_widget_show(dialog);
/* now wait until button is pressed */
while (dialog_done == 999) {
wait_and_process_events();
}
if (GTK_WIDGET_MAPPED(toplevel)) {
gtk_grab_remove(GTK_WIDGET(dialog));
gdk_window_set_cursor(GTK_WIDGET(toplevel)->window,NULL);
if (cursor) gdk_cursor_destroy (cursor);
dodebug(9, "showdialog: restored cursor\n");
}
/* remove dialog window */
gtk_widget_destroy(dialog);
return dialog_done;
}
/* clears the left sidebar */
void clear_sidespace() {
gtk_widget_destroy(sidespace);
sidespace = gtk_vbox_new(FALSE,0);
gtk_paned_add1(GTK_PANED(splitspace), sidespace);
set_sidebar_width();
}
/* clears the right workspace */
void clear_workspace() {
gtk_widget_destroy(workspace);
workspace = gtk_vbox_new(FALSE,0);
gtk_paned_add2(GTK_PANED(splitspace), workspace);
}
/* clears the actionspace subwindow */
void clear_actionspace() {
gtk_widget_destroy(actionspace);
actionspace = gtk_vbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(workspace), actionspace,TRUE,TRUE,0);
/* strange, why we need that...*/
while (gtk_events_pending())
gtk_main_iteration();
}
/* add subdirectory nodes to an existing ctree */
static void ctree_add_dir_nodes(gchar *path, GtkCTree *ctree, GtkCTreeNode *parent, gint showfiles, gint showhidden) {
struct dirent *ent;
DIR *dir;
gchar *text[1];
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
GtkCTreeNode *sibling;
gchar *textdata;
GList *dir_list;
GList *file_list;
dir_list = NULL;
file_list = NULL;
dir = opendir(path);
/* invalid directory */
if (dir == NULL)
return;
/* read entries */
while ( (ent = readdir(dir)) ) {
if (strcmp(ent->d_name,".") == 0 ||
strcmp(ent->d_name,"..") == 0)
continue;
if (!showhidden) {
/* skip files starting with a dot */
if (ent->d_name[0] == '.')
continue;
}
strcpy(tmp,path);
/* add slash when not there */
if (tmp[strlen(tmp)-1] != '/')
strcat(tmp,"/");
strcat(tmp,ent->d_name);
/* add only directories */
if (is_directory(tmp) == 1) {
dir_list = g_list_append(dir_list, g_strdup(ent->d_name));
} else {
if (showfiles)
file_list = g_list_append(file_list, g_strdup(ent->d_name));
}
}
closedir(dir);
/* sort the directory-list */
if (dir_list == NULL && showfiles == 0)
return;
sort_glist(dir_list);
/* sort the file-list */
if (file_list != NULL && showfiles) {
sort_glist(file_list);
}
/* draw entries */
while (dir_list) {
/* allocate directory names */
strncpy(tmp2, dir_list->data, MAXLINE);
convert_for_gtk2(tmp2);
text[0] = tmp2;
strcpy(tmp,path);
/* add slash when not there */
if (tmp[strlen(tmp)-1] != '/')
strcat(tmp,"/");
if ((strlen(tmp) + strlen(dir_list->data)) > MAXLINE-1) {
/* getting to long..writing dummy*/
strcat(tmp,"+");
} else {
strcat(tmp,dir_list->data);
}
textdata = g_strdup(tmp);
/* now check if there are subdirs in that dir */
if (is_subdirs(tmp)) {
sibling = gtk_ctree_insert_node (ctree,parent,
NULL,text,3,pixmap1,mask1,
pixmap2,mask2,FALSE,FALSE);
/* create dummy node */
gtk_ctree_insert_node (ctree,sibling,
NULL,text,3,NULL,NULL,NULL,NULL,TRUE,FALSE);
} else {
/* no subdirs */
if (!showfiles || !is_subfiles(tmp)) {
/* if do not show files, dont allow
changing into empty directory */
sibling = gtk_ctree_insert_node (ctree,parent,
NULL,text,3,pixmap1,mask1,
pixmap2,mask2,TRUE,FALSE);
} else {
/* let user browse directory */
sibling = gtk_ctree_insert_node (ctree,parent,
NULL,text,3,pixmap1,mask1,
pixmap2,mask2,FALSE,FALSE);
gtk_ctree_insert_node (ctree,sibling,
NULL,text,3,NULL,NULL,NULL,NULL,TRUE,FALSE);
}
}
/* save the full path name in the node-data */
gtk_ctree_node_set_row_data(ctree,sibling,textdata);
dir_list = dir_list->next;
}
/* add files */
while (file_list) {
strncpy(tmp2, file_list->data, MAXLINE);
convert_for_gtk2(tmp2);
text[0] = tmp2;
strcpy(tmp,path);
/* add slash when not there */
if (tmp[strlen(tmp)-1] != '/')
strcat(tmp,"/");
if ((strlen(tmp) + strlen(file_list->data)) > MAXLINE-1) {
/* getting to long..writing dummy*/
strcat(tmp,"+");
} else {
strcat(tmp,file_list->data);
}
textdata = g_strdup(tmp);
sibling = gtk_ctree_insert_node (ctree,parent,
NULL,text,3,pixmap3,mask3,
pixmap3,mask3,TRUE,FALSE);
/* save the full path name in the node-data */
gtk_ctree_node_set_row_data(ctree,sibling,textdata);
file_list = file_list->next;
}
/* free list */
free_glist(&dir_list);
free_glist(&file_list);
}
/* recursively remove all children of a node in a ctree */
static void ctree_remove_children(GtkCTree * tree, GtkCTreeNode * node) {
GtkCTreeNode *child;
GList *sibling_list;
gchar *strpnt;
/* Get the child node and make sure it's not NULL. */
child = GTK_CTREE_ROW (node)->children;
if (child == NULL)
return;
/* Get the list of siblings. */
sibling_list = NULL;
for (; child; child = GTK_CTREE_ROW (child)->sibling)
sibling_list = g_list_append (sibling_list, child);
/* break out from recusion */
if (sibling_list == NULL)
return;
/* Remove all of the sibling nodes. */
gtk_clist_freeze (GTK_CLIST (tree));
for (; sibling_list; sibling_list = sibling_list->next) {
/* go recursive */
ctree_remove_children(tree, GTK_CTREE_NODE(sibling_list->data));
/* free allocated node-data */
strpnt = gtk_ctree_node_get_row_data (tree,
GTK_CTREE_NODE (sibling_list->data));
g_free(strpnt);
gtk_ctree_remove_node (tree,
GTK_CTREE_NODE (sibling_list->data));
}
gtk_clist_thaw (GTK_CLIST (tree));
/* Free up memory. */
g_list_free (g_list_first(sibling_list));
}
/* called when the users expands a directory in the ctree */
static gint ctree_expand (GtkCTree *tree, GtkCTreeNode *node, gpointer data) {
gchar *newdir;
GdkCursor *clock_cursor;
/* fetch full path the node stands for */
newdir = gtk_ctree_node_get_row_data (tree, node);
/* save clicked node */
lastactive_node = node;
/* skip root-dir */
if (newdir == NULL) return TRUE;
clock_cursor = gdk_cursor_new (GDK_WATCH);
gdk_window_set_cursor (GTK_WIDGET (ctree_window)->window, clock_cursor);
/* gives gtk a break and time to update REALLY the cursor */
/* I dont think this slowes things down */
gtk_main_iteration_do(FALSE);
gtk_clist_freeze (GTK_CLIST (tree));
/* remove first everything and then add new nodes */
ctree_remove_children(tree,node);
ctree_add_dir_nodes(newdir,tree,node,ctree_showfiles,ctree_showhidden);
/* now scroll to position (OPTIONAL) */
/* gtk_ctree_node_moveto(tree,node,0,0.1,0); */
/* unfreeze and change cursor back */
gtk_clist_thaw (GTK_CLIST (tree));
gdk_window_set_cursor (GTK_WIDGET (ctree_window)->window, NULL);
gdk_cursor_destroy (clock_cursor);
return TRUE;
}
/* just save the last clicked node */
static gint ctree_collapse (GtkCTree *tree, GtkCTreeNode *node, gpointer data) {
/* save clicked node */
lastactive_node = node;
/* process default callback now */
return FALSE;
}
/* returns a list of the selected paths */
/* you have to free that list afterwards */
void ctree_get_selected(GList **retsel) {
GList *sel;
GtkCList *clist;
GtkCTreeNode *lnode;
gchar *p;
clist = GTK_CLIST(ctree_base);
sel = clist->selection;
while (sel) {
lnode = sel->data;
p = gtk_ctree_node_get_row_data (ctree_base, lnode);
if (p) {
*retsel = g_list_append(*retsel, g_strdup(p));
}
sel = sel->next;
}
}
/* called when the user selects a row in a ctree */
static gint ctree_select_row (GtkCTree *tree, GtkCTreeNode *node, gpointer data) {
gchar *pnt;
GList *sel;
GtkCList *clist;
gint selcount;
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
/* how many paths selected right now? */
clist = GTK_CLIST(tree);
sel = clist->selection;
selcount = g_list_length(sel);
pnt = gtk_ctree_node_get_row_data (tree, node);
if (selcount <= 1) {
if (pnt == NULL) {
/* no path set */
gtk_entry_set_text(GTK_ENTRY(ctree_entry),"");
if (ctree_okbutton)
gtk_widget_set_sensitive(ctree_okbutton,FALSE);
} else {
strncpy(tmp2, pnt, MAXLINE);
convert_for_gtk2(tmp2);
gtk_entry_set_text(GTK_ENTRY(ctree_entry),tmp2);
if (ctree_okbutton)
gtk_widget_set_sensitive(ctree_okbutton,TRUE);
}
} else {
/* more than one path selected */
g_snprintf(tmp,MAXLINE,_("(%d paths selected)"), selcount);
gtk_entry_set_text(GTK_ENTRY(ctree_entry),tmp);
if (ctree_okbutton)
gtk_widget_set_sensitive(ctree_okbutton,TRUE);
}
return TRUE;
}
/* called when the user unselects a row in a ctree */
static gint ctree_unselect_row (GtkCTree *tree, GtkCTreeNode *node, gpointer data) {
gchar *pnt;
GList *sel;
GtkCList *clist;
gint selcount;
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
/* how many paths selected right now? */
clist = GTK_CLIST(tree);
sel = clist->selection;
selcount = g_list_length(sel);
if (selcount == 0) {
/* no path set */
gtk_entry_set_text(GTK_ENTRY(ctree_entry),"");
if (ctree_okbutton)
gtk_widget_set_sensitive(ctree_okbutton,FALSE);
} else
if (selcount == 1) {
pnt = gtk_ctree_node_get_row_data (tree, sel->data);
if (pnt) {
strncpy(tmp2, pnt, MAXLINE);
convert_for_gtk2(tmp2);
gtk_entry_set_text(GTK_ENTRY(ctree_entry),tmp2);
if (ctree_okbutton)
gtk_widget_set_sensitive(ctree_okbutton,TRUE);
}
} else {
/* more than one path selected */
g_snprintf(tmp,MAXLINE,_("(%d paths selected)"), selcount);
gtk_entry_set_text(GTK_ENTRY(ctree_entry),tmp);
if (ctree_okbutton)
gtk_widget_set_sensitive(ctree_okbutton,TRUE);
}
return TRUE;
}
/* unselect all in ctree */
void ctree_unselect_all() {
gtk_clist_unselect_all(GTK_CLIST(ctree_base));
gtk_entry_set_text(GTK_ENTRY(ctree_entry),"");
}
/* frees the ctree from memory */
static void ctree_cleanup() {
ctree_remove_children(ctree_base,parent_node);
gtk_ctree_collapse_recursive(ctree_base, parent_node);
}
/* can be used to change the view mode (dirs only or with files) */
/* will collaps the tree to its base mode */
void ctree_change_viewmode(gint showfiles, gint showhidden) {
gchar *text;
gchar tmp[MAXLINE];
/* do nothing if the state is the same */
if (showfiles == ctree_showfiles && showhidden == ctree_showhidden)
return;
/* remember the last touched node */
strcpy(tmp,"");
if (lastactive_node) {
text = gtk_ctree_node_get_row_data(ctree_base, lastactive_node);
if (text) {
strncpy(tmp,text,MAXLINE);
}
}
gtk_clist_freeze(GTK_CLIST(ctree_base));
ctree_showfiles = showfiles;
ctree_showhidden = showhidden;
/* collapse whole tree to ensure correct redraw */
ctree_remove_children(ctree_base,parent_node);
gtk_ctree_collapse_recursive(ctree_base, parent_node);
/* now redraw with correct setting */
ctree_add_dir_nodes(ctree_basedir,ctree_base,parent_node,
ctree_showfiles, ctree_showhidden);
gtk_ctree_expand(ctree_base,parent_node);
/* jump to last clicked position */
if (strcmp(tmp,"")) {
ctree_expand_manualpath(NULL, tmp);
}
gtk_clist_thaw(GTK_CLIST(ctree_base));
}
/* search current branch of ctree for a certain string */
static GtkCTreeNode *ctree_search_nodes(GtkCTree *tree, GtkCTreeNode *node,
gchar *cmpstr) {
GtkCTreeNode *child;
GList *sibling_list;
gchar *strpnt;
/* Get the child node and make sure it's not NULL. */
child = GTK_CTREE_ROW (node)->children;
if (child == NULL)
return NULL;
/* Get the list of siblings. */
sibling_list = NULL;
for (; child; child = GTK_CTREE_ROW (child)->sibling)
sibling_list = g_list_append (sibling_list, child);
for (; sibling_list; sibling_list = sibling_list->next) {
/* get data entry */
child = GTK_CTREE_NODE (sibling_list->data);
strpnt = gtk_ctree_node_get_row_data (tree, child);
if (strpnt && (strcmp(strpnt,cmpstr) == 0)) {
g_list_free (g_list_first(sibling_list));
return child;
}
}
/* nothing found */
g_list_free (g_list_first(sibling_list));
return NULL;
}
/* interprets a manual entered path and adopts the tree-listing */
void ctree_expand_manualpath(GtkWidget* entry, gchar *altstring) {
gchar *p1;
gchar path[MAXLINE];
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
GtkCTreeNode *sibling, *node;
if (entry) {
strncpy(path,gtk_entry_get_text(GTK_ENTRY(entry)),MAXLINE);
convert_for_gtk2_filename(path);
} else {
if (altstring) {
strncpy(path, altstring, MAXLINE);
} else
return;
}
/* must begin with a slash */
if (path[0] != '/')
return;
if (strlen(path) > MAXLINE)
return;
/* walk through directory tree as if user clicked */
sibling = parent_node;
strcpy(tmp,path);
strcpy(tmp2,"");
p1 = strtok(tmp,"/");
while (p1) {
strcat(tmp2,"/");
strcat(tmp2,p1);
/* now look in current sibling for a matching string */
node = ctree_search_nodes(ctree_base, sibling, tmp2);
/* something found? */
if (node) {
/* now expand this node if possible */
ctree_expand(ctree_base, node, NULL);
gtk_ctree_expand(ctree_base,node);
gtk_clist_unselect_all(GTK_CLIST(ctree_base));
/* select only if data from entry */
if (entry)
gtk_ctree_select(ctree_base,node);
/* now scroll to position */
gtk_ctree_node_moveto(ctree_base,node,0,0.1,0);
/* prepare next level */
sibling = node;
}
p1 = strtok(NULL,"/");
}
/* restore entry string */
if (entry) {
convert_for_gtk2(path);
gtk_entry_set_text(GTK_ENTRY(entry),path);
}
}
/* return the current selected directories via drag & drop */
static void ctree_request_dnddata(GtkWidget *widget, GdkDragContext *dc,
GtkSelectionData *selection_data, guint info, guint t,
gpointer data) {
gboolean data_sent = FALSE;
gint focusrow, bufcount;
GtkCTree *ctree;
GtkCList *clist;
GtkCTreeNode *focusnode, *lnode;
GList *sel;
gchar *text;
gint use_selection;
gchar tmp[MAXLINE];
gchar bigtmp[MAXLINE*10];
use_selection = 0;
ctree = GTK_CTREE(widget);
/* Get the focused row on the clist (we clicked on it) */
clist = GTK_CLIST(ctree);
focusrow = clist->focus_row;
focusnode = gtk_ctree_node_nth(ctree, focusrow);
/* see if any other rows are selected */
sel = clist->selection;
while (sel) {
lnode = sel->data;
if (lnode == focusnode) {
/* we focused a row that is selected, remember */
use_selection = 1;
}
sel = sel->next;
}
/* Selected row in bounds? */
if ((focusrow >= 0) && (focusrow < clist->rows)) {
/* return single directory from focused line */
if (use_selection == 0) {
/* determine what node got focus */
lnode = gtk_ctree_node_nth(ctree, focusrow);
text = gtk_ctree_node_get_row_data(ctree, lnode);
if (text) {
g_snprintf(tmp,MAXLINE,"file:%s", text);
gtk_selection_data_set(
selection_data,
GDK_SELECTION_TYPE_STRING, 8,
tmp, strlen(tmp));
data_sent = TRUE;
}
} else {
/* return not from focus but all selected */
strcpy(bigtmp,"");
bufcount = 0;
sel = clist->selection;
while (sel) {
lnode = sel->data;
if (lnode) {
text = gtk_ctree_node_get_row_data(ctree, lnode);
if (text) {
g_snprintf(tmp,MAXLINE,"file:%s\r\n", text);
bufcount+=strlen(tmp);
if (bufcount < MAXLINE*10) {
strcat(bigtmp,tmp);
}
}
}
sel = sel->next;
}
if (bufcount > 0) {
gtk_selection_data_set(
selection_data,
GDK_SELECTION_TYPE_STRING, 8,
bigtmp, strlen(bigtmp));
data_sent = TRUE;
}
}
}
/* we have to send something even in an error case */
if (!data_sent) {
const gchar *cstrptr = "Error";
gtk_selection_data_set(
selection_data,
GDK_SELECTION_TYPE_STRING, 8,
cstrptr, strlen(cstrptr));
}
}
/* we received a drag on the ctree */
static void ctree_drag_received(GtkWidget *widget,
GdkDragContext *dc, gint x, gint y, GtkSelectionData *selection_data,
guint info, guint t, gpointer data) {
gchar *text;
gchar newdir[MAXLINE];
gint mastermenu;
GList *input;
input = NULL;
mastermenu = GPOINTER_TO_INT(data);
/* nothing received? ignore */
if(selection_data == NULL)
return;
if(selection_data->length < 0)
return;
if ((info == DRAG_TAR_INFO_0) ||
(info == DRAG_TAR_INFO_1) ||
(info == DRAG_TAR_INFO_2)) {
text = selection_data->data;
/* this drag was received in the master menu file tree */
if (mastermenu) {
/* check if it was a remove operation */
if (extract_glist_drag_filenames(text, selection_data->length, "xrmv:", &input)) {
/* handle the remove from the master path list */
remove_master_dir_by_drag(input);
free_glist(&input);
return;
}
}
if (extract_single_drag_filename(text, selection_data->length, newdir)) {
/* extracted the plain filename from drag */
if (strcmp(newdir,"") != 0) {
dodebug(3,"Received from drag: %s\n", newdir);
convert_for_gtk2(newdir);
gtk_entry_set_text(GTK_ENTRY(ctree_entry), newdir);
/* scroll to received path */
ctree_expand_manualpath(ctree_entry, NULL);
}
}
}
}
/* creates a ctree for directory browsing */
GtkCTree *create_directory_ctree(gchar *basedir,gchar *title, GtkWidget *win, GtkWidget *entry, gint showfiles, gint showhidden, gint mastermenu) {
gchar tmp[MAXLINE];
GtkCTree *ctree;
GtkCTreeNode *parent;
gchar *titles[1];
gchar *text[1];
GtkStyle *style;
GtkTargetEntry target_entry[3];
target_entry[0].target = DRAG_TAR_NAME_0;
target_entry[0].flags = 0;
target_entry[0].info = DRAG_TAR_INFO_0;
target_entry[1].target = DRAG_TAR_NAME_1;
target_entry[1].flags = 0;
target_entry[1].info = DRAG_TAR_INFO_1;
target_entry[2].target = DRAG_TAR_NAME_2;
target_entry[2].flags = 0;
target_entry[2].info = DRAG_TAR_INFO_2;
/* save the parent window for cursor handling */
ctree_window = win;
ctree_entry = entry;
ctree_showfiles = showfiles;
ctree_showhidden = showhidden;
ctree_basedir = basedir;
lastactive_node = NULL;
/* do we want a title? */
if (title == NULL) {
ctree = GTK_CTREE (gtk_ctree_new (1, 0));
} else {
titles[0] = title;
ctree = GTK_CTREE (gtk_ctree_new_with_titles (1, 0, titles));
}
ctree_base = ctree;
gtk_clist_set_row_height(GTK_CLIST(ctree),tbf(16));
/* create folder pixmaps */
style = gtk_widget_get_style(GTK_WIDGET(ctree));
pixmap1 = gdk_pixmap_create_from_xpm_d(win->window,
&mask1,&style->bg[GTK_STATE_NORMAL],
(gchar **) treefolderclosed_xpm);
pixmap2 = gdk_pixmap_create_from_xpm_d(win->window,
&mask2,&style->bg[GTK_STATE_NORMAL],
(gchar **) treefolderopen_xpm);
pixmap3 = gdk_pixmap_create_from_xpm_d(win->window,
&mask3,&style->bg[GTK_STATE_NORMAL],
(gchar **) filesmall_xpm);
/* connect our signal stuff */
gtk_signal_connect(GTK_OBJECT(ctree),"tree_expand",
GTK_SIGNAL_FUNC(ctree_expand),NULL);
gtk_signal_connect(GTK_OBJECT(ctree),"tree_collapse",
GTK_SIGNAL_FUNC(ctree_collapse),NULL);
gtk_signal_connect(GTK_OBJECT(ctree),"tree_select_row",
GTK_SIGNAL_FUNC(ctree_select_row),NULL);
gtk_signal_connect(GTK_OBJECT(ctree),"tree_unselect_row",
GTK_SIGNAL_FUNC(ctree_unselect_row),NULL);
/* setup drag&drop */
if (!GTK_WIDGET_NO_WINDOW(GTK_WIDGET(ctree))) {
/* we can drag out of the tree */
gtk_drag_source_set(
GTK_WIDGET(ctree),
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
target_entry,
sizeof(target_entry) / sizeof(GtkTargetEntry),
GDK_ACTION_MOVE | GDK_ACTION_COPY);
gtk_signal_connect(
GTK_OBJECT(ctree), "drag_data_get",
GTK_SIGNAL_FUNC(ctree_request_dnddata), NULL);
/* and we can receive drags */
gtk_drag_dest_set(GTK_WIDGET(ctree), GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
target_entry, sizeof(target_entry) / sizeof(GtkTargetEntry),
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gtk_signal_connect(GTK_OBJECT(ctree), "drag_data_received",
GTK_SIGNAL_FUNC(ctree_drag_received), GINT_TO_POINTER(mastermenu));
}
/* make root entry in clist */
strcpy(tmp,basedir);
convert_for_gtk2(tmp);
text[0]=tmp;
parent = gtk_ctree_insert_node (ctree,NULL,
NULL,text,3,pixmap1,mask1,pixmap2,mask2,FALSE,TRUE);
gtk_ctree_node_set_row_data(ctree,parent,g_strdup(basedir));
parent_node = parent;
ctree_add_dir_nodes(basedir,ctree,parent,
ctree_showfiles,ctree_showhidden);
return ctree;
}
static void show_dir_btn_press(GtkWidget *widget, gpointer data) {
dialog_done = GPOINTER_TO_INT(data);
}
/* popup a modal window, set cursor to watch, return path or NULL-string
when cancel or delete_event found.
Centers automatically above the toplevel-widow
*/
void show_dir_tree(gchar *retvalue) {
GtkWidget *dialog;
GtkWidget *button1;
GtkWidget *button2;
GtkWidget *box1,*box2,*box3;
GtkWidget *entry1,*b1_sep;
GtkWidget *scrolled_win;
gchar base_tree[MAXLINE];
gchar *p;
GtkCTree *ctree;
gint xpos, ypos;
gint xsize, ysize;
GdkCursor *cursor;
GtkRequisition rq;
/* if another dialog is running, ignore */
if (dialog_done == 999) {
return;
}
dodebug(8, "displaying show_dir_tree\n");
/* mark our dialog as running */
dialog_done = 999;
/* create new window and position it relative to the main window */
dialog = my_gtk_dialog_new();
set_xcdr_title(dialog, NULL, -1);
gtk_widget_set_usize(dialog,tbf(350),tbf(300));
/* make sure our window is always on top */
gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(toplevel));
gtk_signal_connect (GTK_OBJECT (dialog), "delete_event",
GTK_SIGNAL_FUNC (dialog_delete_event), (gpointer) dialog);
/* create layout for dialog */
box1 = gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(dialog),box1);
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start(GTK_BOX(box1),scrolled_win,TRUE,TRUE,0);
gtk_widget_realize(scrolled_win);
gtk_widget_show(scrolled_win);
box3 = gtk_hbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(box1),box3,FALSE,TRUE,10);
entry1 = gtk_entry_new();
gtk_entry_set_editable(GTK_ENTRY(entry1),FALSE);
gtk_box_pack_start(GTK_BOX(box3),entry1,TRUE,TRUE,10);
gtk_widget_show(entry1);
/* special case, use homedir as filetree base? */
if (strcmp(FILETREEBASE,"$HOME") == 0) {
p = get_pw_home((gint)geteuid());
if (p) {
strncpy(base_tree, p, MAXLINE);
} else {
/* fallback in case user got no home dir? */
strncpy(base_tree, "/tmp", MAXLINE);
}
} else {
strncpy(base_tree, FILETREEBASE, MAXLINE);
}
ctree = create_directory_ctree(base_tree,_("Select Directory"),dialog,entry1,0,1,0);
gtk_clist_set_column_auto_resize(GTK_CLIST(ctree),0,TRUE);
gtk_clist_set_selection_mode (GTK_CLIST(ctree), GTK_SELECTION_BROWSE);
gtk_container_add (GTK_CONTAINER (scrolled_win), GTK_WIDGET (ctree));
gtk_widget_show( GTK_WIDGET (ctree));
gtk_widget_show(box3);
gtk_widget_show(box1);
b1_sep = gtk_hseparator_new();
gtk_box_pack_start(GTK_BOX(box1),b1_sep,FALSE,TRUE,0);
gtk_widget_show(b1_sep);
box2 = gtk_hbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,TRUE,10);
gtk_widget_show(box2);
button1 = gtk_button_new_with_label(T_OK);
ctree_okbutton = button1;
gtk_box_pack_start(GTK_BOX(box2),button1,TRUE,TRUE,10);
gtk_widget_show(button1);
GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT);
gtk_widget_set_sensitive(button1,FALSE);
gtk_signal_connect(GTK_OBJECT(button1),"clicked",
GTK_SIGNAL_FUNC(show_dir_btn_press), GINT_TO_POINTER(0));
button2 = gtk_button_new_with_label(T_CANCEL);
gtk_box_pack_start(GTK_BOX(box2),button2,TRUE,TRUE,10);
gtk_widget_show(button2);
GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT);
gtk_widget_grab_default (button2);
gtk_signal_connect(GTK_OBJECT(button2),"clicked",
GTK_SIGNAL_FUNC(show_dir_btn_press), GINT_TO_POINTER(-1));
/* grab cursor and change to watch */
gtk_grab_add(dialog);
cursor = gdk_cursor_new(GDK_WATCH);
gdk_window_set_cursor(GTK_WIDGET(toplevel)->window,cursor);
/* only center window when toplevel visible */
if ( GTK_WIDGET_VISIBLE(toplevel)) {
gtk_window_position(GTK_WINDOW(dialog),GTK_WIN_POS_NONE);
gdk_window_get_origin(GTK_WIDGET(toplevel)->window,&xpos,&ypos);
gdk_window_get_size(GTK_WIDGET(toplevel)->window,&xsize,&ysize);
gtk_widget_size_request(dialog,&rq);
gtk_widget_set_uposition(GTK_WIDGET(dialog),xpos+xsize/2-rq.width/2,ypos+ysize/2-rq.height/2);
}
gtk_widget_show(dialog);
/* now wait until button is pressed */
while (dialog_done == 999) {
wait_and_process_events();
}
gtk_grab_remove(GTK_WIDGET(dialog));
gdk_window_set_cursor(GTK_WIDGET(toplevel)->window,NULL);
gdk_cursor_destroy (cursor);
if (dialog_done != -1) {
strcpy(retvalue,gtk_entry_get_text(GTK_ENTRY(entry1)));
convert_for_gtk2_filename(retvalue);
} else {
/* cancel or delete_event */
strcpy(retvalue,"");
}
/* free ctree */
ctree_cleanup();
ctree_okbutton = NULL;
/* remove dialog window */
gtk_widget_destroy(dialog);
}
/* fileselector-box ok-button callback */
static void file_selector_ok(GtkWidget *widget, GtkFileSelection *fs) {
dialog_done3 = 1;
}
/* display a file-selector box with defname preselected. Return ""
or filename in retvalue */
void show_file_selector(gchar *title, gchar *defname, gchar *retvalue) {
GtkWidget *dialog;
gint xpos, ypos;
gint xsize, ysize;
GdkCursor *cursor;
GtkRequisition rq;
GtkButton *b1;
#if GTK_MAJOR_VERSION < 2
GtkCList *dirs;
#else
/*
GtkTreeView *dirs;
GtkTreeViewColumn *col;
*/
#endif
/* if another dialog is running, ignore */
if (dialog_done3 == 999) {
return;
}
dodebug(8, "displaying show_fileselector\n");
/* mark our dialog as running */
dialog_done3 = 999;
/* create new window and position it relative to the main window */
dialog = gtk_file_selection_new (title);
/* make sure our window is always on top */
gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(toplevel));
gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(dialog));
if (defname != NULL) {
gtk_file_selection_set_filename(GTK_FILE_SELECTION(dialog),
defname);
}
/* translate the default-texts on the selector */
b1 = GTK_BUTTON(GTK_FILE_SELECTION(dialog)->ok_button);
#if GTK_MAJOR_VERSION < 2
gtk_label_set_text(GTK_LABEL(b1->child),T_OK);
#else
gtk_button_set_label(GTK_BUTTON(b1),T_OK);
#endif
b1 = GTK_BUTTON(GTK_FILE_SELECTION(dialog)->cancel_button);
#if GTK_MAJOR_VERSION < 2
gtk_label_set_text(GTK_LABEL(b1->child),T_CANCEL);
#else
gtk_button_set_label(GTK_BUTTON(b1),T_CANCEL);
#endif
#if GTK_MAJOR_VERSION < 2
dirs = GTK_CLIST(GTK_FILE_SELECTION(dialog)->dir_list);
gtk_clist_set_column_title(dirs,0,_("Directories"));
#else
/*
dirs = GTK_TREE_VIEW(GTK_FILE_SELECTION(dialog)->dir_list);
col = gtk_tree_view_get_column(dirs, 0);
gtk_tree_view_column_set_title(col, _("Directories"));
*/
#endif
#if GTK_MAJOR_VERSION < 2
dirs = GTK_CLIST(GTK_FILE_SELECTION(dialog)->file_list);
gtk_clist_set_column_title(dirs,0,_("Files"));
#else
/*
dirs = GTK_TREE_VIEW(GTK_FILE_SELECTION(dialog)->file_list);
col = gtk_tree_view_get_column(dirs, 0);
gtk_tree_view_column_set_title(col, _("Files"));
*/
#endif
gtk_signal_connect (GTK_OBJECT (dialog), "delete_event",
GTK_SIGNAL_FUNC (dialog_delete_event3), dialog);
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(dialog)->ok_button),
"clicked", GTK_SIGNAL_FUNC(file_selector_ok), dialog);
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(dialog)->cancel_button),
"clicked", GTK_SIGNAL_FUNC(dialog_delete_event3), dialog);
/* grab cursor and change to watch */
gtk_grab_add(dialog);
cursor = gdk_cursor_new(GDK_WATCH);
gdk_window_set_cursor(GTK_WIDGET(toplevel)->window,cursor);
/* only center window when toplevel visible */
if ( GTK_WIDGET_VISIBLE(toplevel)) {
gtk_window_position(GTK_WINDOW(dialog),GTK_WIN_POS_NONE);
gdk_window_get_origin(GTK_WIDGET(toplevel)->window,&xpos,&ypos);
gdk_window_get_size(GTK_WIDGET(toplevel)->window,&xsize,&ysize);
gtk_widget_size_request(dialog,&rq);
gtk_widget_set_uposition(GTK_WIDGET(dialog),xpos+xsize/2-rq.width/2,ypos+ysize/2-rq.height/2);
}
/* center does not work with gtk-1.2.1, but ok with 1.2.3, well
what the heck... */
gtk_widget_show(dialog);
/* now wait until button is pressed */
while (dialog_done3 == 999) {
wait_and_process_events();
}
gtk_grab_remove(GTK_WIDGET(dialog));
gdk_window_set_cursor(GTK_WIDGET(toplevel)->window,NULL);
gdk_cursor_destroy (cursor);
if (dialog_done3 != -1) {
strcpy(retvalue,gtk_file_selection_get_filename (GTK_FILE_SELECTION (dialog)));
} else {
/* cancel or delete_event */
strcpy(retvalue,"");
}
/* remove dialog window */
gtk_widget_destroy(dialog);
}
/* what to do when user selects a CD from the database */
static void cddb_select_row(GtkWidget *clist, gint row, gint col,
GdkEventButton *event, gpointer data) {
/* we selected something, unlook ok-button */
gtk_widget_set_sensitive(cddb_info_okbutton,TRUE);
/* got double-click? Simulate ok-button-press */
if (event && event->type == GDK_2BUTTON_PRESS) {
gtk_button_clicked(GTK_BUTTON(cddb_info_okbutton));
}
}
/* called from cancel or ok button */
static void show_cddb_btn_press(GtkWidget *widget, gpointer data) {
GList *sel;
gint row;
/* cancel event */
if (GPOINTER_TO_INT(data) == -1) {
if (read_done == 999) {
/* abort our cddb-process */
kill_readcdda();
}
dialog_done = -1;
return;
}
/* ok button pressed - find out which entry was selected */
sel = cddb_clist->selection;
if (sel != NULL) {
row = GPOINTER_TO_INT(sel->data);
/* now go back to network code and fetch fitting CD */
if (continue_cddb_lookup_action(row) != 0) {
/* disable ok-button */
gtk_widget_set_sensitive(cddb_info_okbutton,FALSE);
} else {
/* data ok received */
dialog_done = 0;
}
}
}
/* called when somebody closes the cddb-window via window-manager */
static gint dialog_cddb_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) {
if (read_done == 999) {
/* abort our cddb-process */
kill_readcdda();
}
dialog_done = -1;
return(TRUE);
}
/* popup a modal window, set cursor to watch, return 0 if correct
data was received from cddb-server, -1 if not or
when cancel or delete_event found.
Centers automatically above the toplevel-widow
*/
gint show_cddb_query(GtkWidget *cdtext_parent, gint onthefly) {
GtkWidget *dialog;
GtkWidget *button1;
GtkWidget *button2;
GtkWidget *box1,*box2,*hbox;
GtkWidget *f1, *cddb_logo;
GdkPixmap *p;
GdkBitmap *m;
GdkPixbuf *im;
GtkWidget *b1_sep, *lbl;
GtkWidget *scrolled_win, *c_list;
GtkCList *clist;
gchar *titles[1];
gint xpos, ypos;
gint xsize, ysize;
GdkCursor *cursor;
GtkRequisition rq;
gchar tmp[MAXLINE];
/* if another dialog is running, ignore */
if (dialog_done == 999) {
return -1;
}
dodebug(8, "displaying show_cddb_query\n");
/* mark our dialog as running */
dialog_done = 999;
/* create new window and position it relative to the main window */
dialog = my_gtk_dialog_new();
set_xcdr_title(dialog, NULL, -1);
gtk_widget_set_usize(dialog,tbf(450),tbf(260));
/* make sure our window is always on top */
if (cdtext_parent) {
gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(cdtext_parent));
} else {
gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(toplevel));
}
cddb_window = dialog;
gtk_signal_connect (GTK_OBJECT (dialog), "delete_event",
GTK_SIGNAL_FUNC (dialog_cddb_delete_event), (gpointer) dialog);
/* create layout for dialog */
box1 = gtk_vbox_new(FALSE,5);
gtk_container_set_border_width (GTK_CONTAINER (box1), 5);
gtk_container_add(GTK_CONTAINER(dialog),box1);
hbox = gtk_hbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(box1),hbox,FALSE,TRUE,5);
gtk_widget_show(hbox);
f1 = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(f1),GTK_SHADOW_IN);
gtk_box_pack_start(GTK_BOX(hbox),f1,TRUE,TRUE,5);
gtk_widget_show(f1);
lbl = gtk_label_new("");
cddb_info_label = lbl;
gtk_container_add(GTK_CONTAINER(f1), lbl);
gtk_misc_set_alignment(GTK_MISC(lbl),0.0,0.5);
gtk_misc_set_padding(GTK_MISC(lbl),10,0);
gtk_widget_show(lbl);
/* load a gif-image and put into a pixmap */
g_snprintf(tmp,MAXLINE,"%s/%s", sharedir,CDDBLOGO);
#if GTK_MAJOR_VERSION < 2
im=gdk_pixbuf_new_from_file(tmp);
#else
im=gdk_pixbuf_new_from_file(tmp,NULL);
#endif
if (im) {
gdk_pixbuf_render_pixmap_and_mask(im, &p, &m, 128);
cddb_logo = gtk_pixmap_new(p,m);
gdk_pixbuf_unref(im);
} else {
cddb_logo = gtk_label_new("[CDDB]");
}
gtk_box_pack_start(GTK_BOX(hbox),cddb_logo,FALSE,FALSE,5);
gtk_widget_show(cddb_logo);
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start(GTK_BOX(box1),scrolled_win,TRUE,TRUE,0);
gtk_widget_show(scrolled_win);
titles[0] = _("Matching database entries");
c_list = gtk_clist_new_with_titles(1,titles);
clist = GTK_CLIST(c_list);
cddb_clist = clist;
gtk_clist_set_column_auto_resize(clist, 0, TRUE);
gtk_container_add (GTK_CONTAINER (scrolled_win), c_list);
gtk_widget_show(c_list);
gtk_signal_connect(GTK_OBJECT(clist), "select_row",
GTK_SIGNAL_FUNC(cddb_select_row), NULL);
gtk_widget_show(box1);
b1_sep = gtk_hseparator_new();
gtk_box_pack_start(GTK_BOX(box1),b1_sep,FALSE,TRUE,0);
gtk_widget_show(b1_sep);
box2 = gtk_hbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,TRUE,10);
gtk_widget_show(box2);
button1 = gtk_button_new_with_label(T_OK);
cddb_info_okbutton = button1;
gtk_box_pack_start(GTK_BOX(box2),button1,TRUE,TRUE,10);
gtk_widget_show(button1);
GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT);
gtk_widget_set_sensitive(button1,FALSE);
gtk_signal_connect(GTK_OBJECT(button1),"clicked",
GTK_SIGNAL_FUNC(show_cddb_btn_press), GINT_TO_POINTER(0));
button2 = gtk_button_new_with_label(T_CANCEL);
gtk_box_pack_start(GTK_BOX(box2),button2,TRUE,TRUE,10);
gtk_widget_show(button2);
GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT);
gtk_widget_grab_default (button2);
gtk_signal_connect(GTK_OBJECT(button2),"clicked",
GTK_SIGNAL_FUNC(show_cddb_btn_press), GINT_TO_POINTER(-1));
/* grab cursor and change to watch */
gtk_grab_add(dialog);
cursor = gdk_cursor_new(GDK_WATCH);
gdk_window_set_cursor(GTK_WIDGET(toplevel)->window,cursor);
/* only center window when toplevel visible */
if ( GTK_WIDGET_VISIBLE(toplevel)) {
gtk_window_position(GTK_WINDOW(dialog),GTK_WIN_POS_NONE);
gdk_window_get_origin(GTK_WIDGET(toplevel)->window,&xpos,&ypos);
gdk_window_get_size(GTK_WIDGET(toplevel)->window,&xsize,&ysize);
gtk_widget_size_request(dialog,&rq);
gtk_widget_set_uposition(GTK_WIDGET(dialog),xpos+xsize/2-rq.wid