summary refs log blame commit diff stats
path: root/plugins/mpcinfo/functions.c
blob: ba6ba51959a689842828acf5c7300cbe282ca195 (plain) (tree)






















































































































                                                                                                 
                                                              














































                                                                                            
/*
 *  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.
 */

/*
typedef int (*MYPROC)(HWND,HWND,char*,char*,BOOL,BOOL); 

int dllProc(char *name, char *data){
    HINSTANCE hinstLib; 
    hinstLib = LoadLibrary("mpcinfo");
    //MYPROC proc;
    int res;
    if (hinstLib != NULL){
       //proc = ;
       if ((MYPROC) GetProcAddress(hinstLib, name)!=NULL){
          res=(MYPROC)(NULL,NULL,data,NULL,TRUE,TRUE);
       }
       else{fprintf(stderr,"can't get proc: %s\n",name);res=-2;}
    }
    else{fprintf(stderr,"can't access dll\n");return -1;}
    FreeLibrary(hinstLib);
    return res;
}
*/

/*
int dllProc(char *name, char *data)
{
	static HMODULE lib = NULL;
	if (!lib)
	{
		lib = LoadLibraryA ("mpcinfo");
		if (!lib)
		{
			return FALSE;
		}
		FreeLibrary (lib);
	}

	return TRUE;
}
*/

char *split(char *text, char seperator){
     //if (DEBUG==1) putlog("splitting");
     int i;int pos=-1;
     for (i=0;i<strlen(text);i++){
         if (text[i]==seperator){pos=i;i=strlen(text)+1;}
     }
     if (pos==-1) return text;
     text[pos]=0;
     return &(text[pos+1]);
}

int endsWith(char *text, char *suffix){
    char *tmp=strstr(text,suffix);
    if (tmp==NULL) return 0;
    if (strlen(tmp)==strlen(suffix)) return 1;
    return 0;
}

int inStr(char *s1, int sl1, char *s2){
    //if (DEBUG==1) putlog("checking instr");
	int i;int j;
	for(i=0;i<sl1-strlen(s2);i++){
		for (j=0;j<strlen(s2);j++){
			if (s1[i+j]!=s2[j]) j=strlen(s2)+2;
		}
		if (j==strlen(s2)) return i;
	}
	return -1;
}

static char *subString(char *text, int first, int length, int spcKill){
//if (DEBUG==1) putlog("creating substring");
	char *ret=(char*) calloc (length+1,sizeof(char)); //malloc(sizeof(char)*(length+1));
	int i;
	ret[length]=0;
	for (i=0;i<length;i++){
		ret[i]=text[i+first];
		//if (ret[i]==0) ret[i]='0';
	}
	if (spcKill==1){
	   for (i=length-1;i>=0;i--){
           if (ret[i]==32) ret[i]=0;
           else i=-1;
       }
    }
    //if (DEBUG==1) putlog("substring created");
	return ret;
}

static char *substring(char *text, int first, int length){return subString(text,first,length,0);}


char *readLine(FILE *f){
     //if (DEBUG==1) putlog("reading line from file");
     char *buffer=(char*)calloc(1024,sizeof(char)); //malloc(sizeof(char)*1024);
     int pos=0;
     int cc=0;
     while((cc!=EOF)&&(pos<1024)&&(cc!=10)){
          cc=fgetc(f);
          if ((cc!=10)&&(cc!=13)){
             if (cc==EOF) buffer[pos]=0;
             else buffer[pos]=(char)cc;pos++;
          }
     }
     if (buffer[pos]==EOF) hexchat_printf(ph,"EOF: %i\n",pos);
     return buffer;
}

char *toUpper(char *text){
     //if (DEBUG==1) putlog("converting text to upper case");
     char *ret=(char*) calloc(strlen(text)+1,sizeof(char));
     int i;
     for (i=0;i<strlen(text);i++) ret[i]=toupper(text[i]);
     ret[strlen(text)]=0;
     //if (DEBUG==1) putlog("uc done");
     return ret;
}

static char *str3cat(char *s1, char *s2, char *s3){
       //if (DEBUG==1) putlog("cating 3 strings");
       char *ret=(char*)calloc(strlen(s1)+strlen(s2)+strlen(s3)+1,sizeof(char));
       strcpy(ret,s1);strcat(ret,s2);strcat(ret,s3);
       ret[strlen(s1)+strlen(s2)+strlen(s3)]=0;
       //if (DEBUG==1) putlog("strings cated");
       return ret;
}

char *replace(char *text, char *from, char *to){
     //if (DEBUG==1) putlog("replacing");
     char *ret=(char*)calloc( strlen(text)+(strlen(to)-strlen(from)),sizeof(char));
     char *left;
     char *right;
     int pos=inStr(text,strlen(text),from);
     if (pos!=-1){
           left=substring(text,0,pos);
           right=substring(text,pos+strlen(from),strlen(text)-(pos+strlen(from)));          
           ret=str3cat(left,to,right);
           return replace(ret,from,to);
     }
     //if (DEBUG==1) putlog("replaced");
     return text;
}

char *intReplaceF(char *text, char *from, int to, char *form){
     //if (DEBUG==1) putlog("replaceF");
     char *buffer=(char*) calloc(16,sizeof(char));
     sprintf(buffer,form,to);
     //if (DEBUG==1) putlog("replaceF done");
     return replace(text,from,buffer);
}

char *intReplace(char *text, char *from, int to){return intReplaceF(text,from,to,"%i");}
l.h> #include <gtk/gtkstock.h> #include <gtk/gtkmessagedialog.h> #include <gtk/gtktable.h> #include <gtk/gtktreeview.h> #include <gtk/gtkexpander.h> #include <gtk/gtkliststore.h> #include <gtk/gtktreeselection.h> #include <gtk/gtkcellrendererpixbuf.h> #include <gtk/gtkcellrenderertext.h> #include <gtk/gtkcheckmenuitem.h> #include <gtk/gtkradiobutton.h> #include <gtk/gtkversion.h> #include "../common/hexchat.h" #include "../common/hexchatc.h" #include "../common/fe.h" #include "../common/util.h" #include "../common/network.h" #include "gtkutil.h" #include "palette.h" #include "maingui.h" enum /* DCC SEND/RECV */ { COL_TYPE, COL_STATUS, COL_FILE, COL_SIZE, COL_POS, COL_PERC, COL_SPEED, COL_ETA, COL_NICK, COL_DCC, /* struct DCC * */ COL_COLOR, /* GdkColor */ N_COLUMNS }; enum /* DCC CHAT */ { CCOL_STATUS, CCOL_NICK, CCOL_RECV, CCOL_SENT, CCOL_START, CCOL_DCC, /* struct DCC * */ CCOL_COLOR, /* GdkColor * */ CN_COLUMNS }; struct dccwindow { GtkWidget *window; GtkWidget *list; GtkListStore *store; GtkTreeSelection *sel; GtkWidget *abort_button; GtkWidget *accept_button; GtkWidget *resume_button; GtkWidget *open_button; GtkWidget *file_label; GtkWidget *address_label; }; struct my_dcc_send { struct session *sess; char *nick; int maxcps; int passive; }; static struct dccwindow dccfwin = {NULL, }; /* file */ static struct dccwindow dcccwin = {NULL, }; /* chat */ static GdkPixbuf *pix_up = NULL; /* down arrow */ static GdkPixbuf *pix_dn = NULL; /* up arrow */ static int win_width = 600; static int win_height = 256; static short view_mode; /* 1=download 2=upload 3=both */ #define VIEW_DOWNLOAD 1 #define VIEW_UPLOAD 2 #define VIEW_BOTH 3 #define KILOBYTE 1024 #define MEGABYTE (KILOBYTE * 1024) #define GIGABYTE (MEGABYTE * 1024) static void proper_unit (DCC_SIZE size, char *buf, int buf_len) { if (size <= KILOBYTE) { snprintf (buf, buf_len, "%"DCC_SFMT"B", size); } else if (size > KILOBYTE && size <= MEGABYTE) { snprintf (buf, buf_len, "%"DCC_SFMT"kB", size / KILOBYTE); } else { snprintf (buf, buf_len, "%.2fMB", (float)size / MEGABYTE); } } static void dcc_send_filereq_file (struct my_dcc_send *mdc, char *file) { if (file) dcc_send (mdc->sess, mdc->nick, file, mdc->maxcps, mdc->passive); else { free (mdc->nick); free (mdc); } } void fe_dcc_send_filereq (struct session *sess, char *nick, int maxcps, int passive) { char tbuf[128]; struct my_dcc_send *mdc; mdc = malloc (sizeof (*mdc)); mdc->sess = sess; mdc->nick = strdup (nick); mdc->maxcps = maxcps; mdc->passive = passive; snprintf (tbuf, sizeof tbuf, _("Send file to %s"), nick); gtkutil_file_req (tbuf, dcc_send_filereq_file, mdc, prefs.hex_dcc_dir, NULL, FRF_MULTIPLE|FRF_FILTERISINITIAL); } static void dcc_prepare_row_chat (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter, gboolean update_only) { static char pos[16], siz[16]; char *date; date = ctime (&dcc->starttime); date[strlen (date) - 1] = 0; /* remove the \n */ proper_unit (dcc->pos, pos, sizeof (pos)); proper_unit (dcc->size, siz, sizeof (siz)); gtk_list_store_set (store, iter, CCOL_STATUS, _(dccstat[dcc->dccstat].name), CCOL_NICK, dcc->nick, CCOL_RECV, pos, CCOL_SENT, siz, CCOL_START, date, CCOL_DCC, dcc, CCOL_COLOR, dccstat[dcc->dccstat].color == 1 ? NULL : colors + dccstat[dcc->dccstat].color, -1); } static void dcc_prepare_row_send (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter, gboolean update_only) { static char pos[16], size[16], kbs[14], perc[14], eta[14]; int to_go; float per; if (!pix_up) pix_up = gtk_widget_render_icon (dccfwin.window, "gtk-go-up", GTK_ICON_SIZE_MENU, NULL); /* percentage ack'ed */ per = (float) ((dcc->ack * 100.00) / dcc->size); proper_unit (dcc->size, size, sizeof (size)); proper_unit (dcc->pos, pos, sizeof (pos)); snprintf (kbs, sizeof (kbs), "%.1f", ((float)dcc->cps) / 1024); /* proper_unit (dcc->ack, ack, sizeof (ack));*/ snprintf (perc, sizeof (perc), "%.0f%%", per); if (dcc->cps != 0) { to_go = (dcc->size - dcc->ack) / dcc->cps; snprintf (eta, sizeof (eta), "%.2d:%.2d:%.2d", to_go / 3600, (to_go / 60) % 60, to_go % 60); } else strcpy (eta, "--:--:--"); if (update_only) gtk_list_store_set (store, iter, COL_STATUS, _(dccstat[dcc->dccstat].name), COL_POS, pos, COL_PERC, perc, COL_SPEED, kbs, COL_ETA, eta, COL_COLOR, dccstat[dcc->dccstat].color == 1 ? NULL : colors + dccstat[dcc->dccstat].color, -1); else gtk_list_store_set (store, iter, COL_TYPE, pix_up, COL_STATUS, _(dccstat[dcc->dccstat].name), COL_FILE, file_part (dcc->file), COL_SIZE, size, COL_POS, pos, COL_PERC, perc, COL_SPEED, kbs, COL_ETA, eta, COL_NICK, dcc->nick, COL_DCC, dcc, COL_COLOR, dccstat[dcc->dccstat].color == 1 ? NULL : colors + dccstat[dcc->dccstat].color, -1); } static void dcc_prepare_row_recv (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter, gboolean update_only) { static char size[16], pos[16], kbs[16], perc[14], eta[16]; float per; int to_go; if (!pix_dn) pix_dn = gtk_widget_render_icon (dccfwin.window, "gtk-go-down", GTK_ICON_SIZE_MENU, NULL); proper_unit (dcc->size, size, sizeof (size)); if (dcc->dccstat == STAT_QUEUED) proper_unit (dcc->resumable, pos, sizeof (pos)); else proper_unit (dcc->pos, pos, sizeof (pos)); snprintf (kbs, sizeof (kbs), "%.1f", ((float)dcc->cps) / 1024); /* percentage recv'ed */ per = (float) ((dcc->pos * 100.00) / dcc->size); snprintf (perc, sizeof (perc), "%.0f%%", per); if (dcc->cps != 0) { to_go = (dcc->size - dcc->pos) / dcc->cps; snprintf (eta, sizeof (eta), "%.2d:%.2d:%.2d", to_go / 3600, (to_go / 60) % 60, to_go % 60); } else strcpy (eta, "--:--:--"); if (update_only) gtk_list_store_set (store, iter, COL_STATUS, _(dccstat[dcc->dccstat].name), COL_POS, pos, COL_PERC, perc, COL_SPEED, kbs, COL_ETA, eta, COL_COLOR, dccstat[dcc->dccstat].color == 1 ? NULL : colors + dccstat[dcc->dccstat].color, -1); else gtk_list_store_set (store, iter, COL_TYPE, pix_dn, COL_STATUS, _(dccstat[dcc->dccstat].name), COL_FILE, file_part (dcc->file), COL_SIZE, size, COL_POS, pos, COL_PERC, perc, COL_SPEED, kbs, COL_ETA, eta, COL_NICK, dcc->nick, COL_DCC, dcc, COL_COLOR, dccstat[dcc->dccstat].color == 1 ? NULL : colors + dccstat[dcc->dccstat].color, -1); } static gboolean dcc_find_row (struct DCC *find_dcc, GtkTreeModel *model, GtkTreeIter *iter, int col) { struct DCC *dcc; if (gtk_tree_model_get_iter_first (model, iter)) { do { gtk_tree_model_get (model, iter, col, &dcc, -1); if (dcc == find_dcc) return TRUE; } while (gtk_tree_model_iter_next (model, iter)); } return FALSE; } static void dcc_update_recv (struct DCC *dcc) { GtkTreeIter iter; if (!dccfwin.window) return; if (!dcc_find_row (dcc, GTK_TREE_MODEL (dccfwin.store), &iter, COL_DCC)) return; dcc_prepare_row_recv (dcc, dccfwin.store, &iter, TRUE); } static void dcc_update_chat (struct DCC *dcc) { GtkTreeIter iter; if (!dcccwin.window) return; if (!dcc_find_row (dcc, GTK_TREE_MODEL (dcccwin.store), &iter, CCOL_DCC)) return; dcc_prepare_row_chat (dcc, dcccwin.store, &iter, TRUE); } static void dcc_update_send (struct DCC *dcc) { GtkTreeIter iter; if (!dccfwin.window) return; if (!dcc_find_row (dcc, GTK_TREE_MODEL (dccfwin.store), &iter, COL_DCC)) return; dcc_prepare_row_send (dcc, dccfwin.store, &iter, TRUE); } static void close_dcc_file_window (GtkWindow *win, gpointer data) { dccfwin.window = NULL; } static void dcc_append (struct DCC *dcc, GtkListStore *store, gboolean prepend) { GtkTreeIter iter; if (prepend) gtk_list_store_prepend (store, &iter); else gtk_list_store_append (store, &iter); if (dcc->type == TYPE_RECV) dcc_prepare_row_recv (dcc, store, &iter, FALSE); else dcc_prepare_row_send (dcc, store, &iter, FALSE); } static void dcc_fill_window (int flags) { struct DCC *dcc; GSList *list; GtkTreeIter iter; int i = 0; gtk_list_store_clear (GTK_LIST_STORE (dccfwin.store)); if (flags & VIEW_UPLOAD) { list = dcc_list; while (list) { dcc = list->data; if (dcc->type == TYPE_SEND) { dcc_append (dcc, dccfwin.store, FALSE); i++; } list = list->next; } } if (flags & VIEW_DOWNLOAD) { list = dcc_list; while (list) { dcc = list->data; if (dcc->type == TYPE_RECV) { dcc_append (dcc, dccfwin.store, FALSE); i++; } list = list->next; } } /* if only one entry, select it (so Accept button can work) */ if (i == 1) { gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dccfwin.store), &iter); gtk_tree_selection_select_iter (dccfwin.sel, &iter); } } /* return list of selected DCCs */ static GSList * treeview_get_selected (GtkTreeModel *model, GtkTreeSelection *sel, int column) { GtkTreeIter iter; GSList *list = NULL; void *ptr; if (gtk_tree_model_get_iter_first (model, &iter)) { do { if (gtk_tree_selection_iter_is_selected (sel, &iter)) { gtk_tree_model_get (model, &iter, column, &ptr, -1); list = g_slist_prepend (list, ptr); } } while (gtk_tree_model_iter_next (model, &iter)); } return g_slist_reverse (list); } static GSList * dcc_get_selected (void) { return treeview_get_selected (GTK_TREE_MODEL (dccfwin.store), dccfwin.sel, COL_DCC); } static void resume_clicked (GtkWidget * wid, gpointer none) { struct DCC *dcc; char buf[512]; GSList *list; list = dcc_get_selected (); if (!list) return; dcc = list->data; g_slist_free (list); if (dcc->type == TYPE_RECV && !dcc_resume (dcc)) { switch (dcc->resume_error) { case 0: /* unknown error */ fe_message (_("That file is not resumable."), FE_MSG_ERROR); break; case 1: snprintf (buf, sizeof (buf), _( "Cannot access file: %s\n" "%s.\n" "Resuming not possible."), dcc->destfile, errorstring (dcc->resume_errno)); fe_message (buf, FE_MSG_ERROR); break; case 2: fe_message (_("File in download directory is larger " "than file offered. Resuming not possible."), FE_MSG_ERROR); break; case 3: fe_message (_("Cannot resume the same file from two people."), FE_MSG_ERROR); } } } static void abort_clicked (GtkWidget * wid, gpointer none) { struct DCC *dcc; GSList *start, *list; start = list = dcc_get_selected (); for (; list; list = list->next) { dcc = list->data; dcc_abort (dcc->serv->front_session, dcc); } g_slist_free (start); } static void accept_clicked (GtkWidget * wid, gpointer none) { struct DCC *dcc; GSList *start, *list; start = list = dcc_get_selected (); for (; list; list = list->next) { dcc = list->data; if (dcc->type != TYPE_SEND) dcc_get (dcc); } g_slist_free (start); } static void browse_folder (char *dir) { #ifdef WIN32 /* no need for file:// in ShellExecute() */ fe_open_url (dir); #else char buf[512]; snprintf (buf, sizeof (buf), "file://%s", dir); fe_open_url (buf); #endif } static void browse_dcc_folder (void) { if (prefs.hex_dcc_completed_dir[0]) browse_folder (prefs.hex_dcc_completed_dir); else browse_folder (prefs.hex_dcc_dir); } static void dcc_details_populate (struct DCC *dcc) { char buf[128]; if (!dcc) { gtk_label_set_text (GTK_LABEL (dccfwin.file_label), NULL); gtk_label_set_text (GTK_LABEL (dccfwin.address_label), NULL); return; } /* full path */ if (dcc->type == TYPE_RECV) gtk_label_set_text (GTK_LABEL (dccfwin.file_label), dcc->destfile); else gtk_label_set_text (GTK_LABEL (dccfwin.file_label), dcc->file); /* address and port */ snprintf (buf, sizeof (buf), "%s : %d", net_ip (dcc->addr), dcc->port); gtk_label_set_text (GTK_LABEL (dccfwin.address_label), buf); } static void dcc_row_cb (GtkTreeSelection *sel, gpointer user_data) { struct DCC *dcc; GSList *list; list = dcc_get_selected (); if (!list) { gtk_widget_set_sensitive (dccfwin.accept_button, FALSE); gtk_widget_set_sensitive (dccfwin.resume_button, FALSE); gtk_widget_set_sensitive (dccfwin.abort_button, FALSE); dcc_details_populate (NULL); return; } gtk_widget_set_sensitive (dccfwin.abort_button, TRUE); if (list->next) /* multi selection */ { gtk_widget_set_sensitive (dccfwin.accept_button, TRUE); gtk_widget_set_sensitive (dccfwin.resume_button, TRUE); dcc_details_populate (list->data); } else { /* turn OFF/ON appropriate buttons */ dcc = list->data; if (dcc->dccstat == STAT_QUEUED && dcc->type == TYPE_RECV) { gtk_widget_set_sensitive (dccfwin.accept_button, TRUE); gtk_widget_set_sensitive (dccfwin.resume_button, TRUE); } else { gtk_widget_set_sensitive (dccfwin.accept_button, FALSE); gtk_widget_set_sensitive (dccfwin.resume_button, FALSE); } dcc_details_populate (dcc); } g_slist_free (list); } static void dcc_dclick_cb (GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data) { struct DCC *dcc; GSList *list; list = dcc_get_selected (); if (!list) return; dcc = list->data; g_slist_free (list); if (dcc->type == TYPE_RECV) { accept_clicked (0, 0); return; } switch (dcc->dccstat) { case STAT_FAILED: case STAT_ABORTED: case STAT_DONE: dcc_abort (dcc->serv->front_session, dcc); } } static void dcc_add_column (GtkWidget *tree, int textcol, int colorcol, char *title, gboolean right_justified) { GtkCellRenderer *renderer; renderer = gtk_cell_renderer_text_new (); if (right_justified) g_object_set (G_OBJECT (renderer), "xalign", (float) 1.0, NULL); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree), -1, title, renderer, "text", textcol, "foreground-gdk", colorcol, NULL); gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (renderer), 1); } static GtkWidget * dcc_detail_label (char *text, GtkWidget *box, int num) { GtkWidget *label; char buf[64]; label = gtk_label_new (NULL); snprintf (buf, sizeof (buf), "<b>%s</b>", text); gtk_label_set_markup (GTK_LABEL (label), buf); gtk_misc_set_alignment (GTK_MISC (label), 0, 0); gtk_table_attach (GTK_TABLE (box), label, 0, 1, 0 + num, 1 + num, GTK_FILL, GTK_FILL, 0, 0); label = gtk_label_new (NULL); gtk_label_set_selectable (GTK_LABEL (label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0); gtk_table_attach (GTK_TABLE (box), label, 1, 2, 0 + num, 1 + num, GTK_FILL, GTK_FILL, 0, 0); return label; } static void dcc_exp_cb (GtkWidget *exp, GtkWidget *box) { #if GTK_CHECK_VERSION(2,20,0) if (gtk_widget_get_visible (box)) #else if (GTK_WIDGET_VISIBLE (box)) #endif gtk_widget_hide (box); else gtk_widget_show (box); } static void dcc_toggle (GtkWidget *item, gpointer data) { if (GTK_TOGGLE_BUTTON (item)->active) { view_mode = GPOINTER_TO_INT (data); dcc_fill_window (GPOINTER_TO_INT (data)); } } static gboolean dcc_configure_cb (GtkWindow *win, GdkEventConfigure *event, gpointer data) { /* remember the window size */ gtk_window_get_size (win, &win_width, &win_height); return FALSE; } int fe_dcc_open_recv_win (int passive) { GtkWidget *radio, *table, *vbox, *bbox, *view, *exp, *detailbox; GtkListStore *store; GSList *group; if (dccfwin.window) { if (!passive) mg_bring_tofront (dccfwin.window); return TRUE; } dccfwin.window = mg_create_generic_tab ("Transfers", _(DISPLAY_NAME": Uploads and Downloads"), FALSE, TRUE, close_dcc_file_window, NULL, win_width, win_height, &vbox, 0); gtk_container_set_border_width (GTK_CONTAINER (dccfwin.window), 3); gtk_box_set_spacing (GTK_BOX (vbox), 3); store = gtk_list_store_new (N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, GDK_TYPE_COLOR); view = gtkutil_treeview_new (vbox, GTK_TREE_MODEL (store), NULL, -1); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE); /* Up/Down Icon column */ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), -1, NULL, gtk_cell_renderer_pixbuf_new (), "pixbuf", COL_TYPE, NULL); dcc_add_column (view, COL_STATUS, COL_COLOR, _("Status"), FALSE); dcc_add_column (view, COL_FILE, COL_COLOR, _("File"), FALSE); dcc_add_column (view, COL_SIZE, COL_COLOR, _("Size"), TRUE); dcc_add_column (view, COL_POS, COL_COLOR, _("Position"), TRUE); dcc_add_column (view, COL_PERC, COL_COLOR, "%", TRUE); dcc_add_column (view, COL_SPEED, COL_COLOR, "KB/s", TRUE); dcc_add_column (view, COL_ETA, COL_COLOR, _("ETA"), FALSE); dcc_add_column (view, COL_NICK, COL_COLOR, _("Nick"), FALSE); gtk_tree_view_column_set_expand (gtk_tree_view_get_column (GTK_TREE_VIEW (view), COL_FILE), TRUE); gtk_tree_view_column_set_expand (gtk_tree_view_get_column (GTK_TREE_VIEW (view), COL_NICK), TRUE); dccfwin.list = view; dccfwin.store = store; dccfwin.sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); view_mode = VIEW_BOTH; gtk_tree_selection_set_mode (dccfwin.sel, GTK_SELECTION_MULTIPLE); if (!prefs.hex_gui_tab_utils) g_signal_connect (G_OBJECT (dccfwin.window), "configure_event", G_CALLBACK (dcc_configure_cb), 0); g_signal_connect (G_OBJECT (dccfwin.sel), "changed", G_CALLBACK (dcc_row_cb), NULL); /* double click */ g_signal_connect (G_OBJECT (view), "row-activated", G_CALLBACK (dcc_dclick_cb), NULL); table = gtk_table_new (1, 3, FALSE); gtk_table_set_col_spacings (GTK_TABLE (table), 16); gtk_box_pack_start (GTK_BOX (vbox), table, 0, 0, 0); radio = gtk_radio_button_new_with_mnemonic (NULL, _("Both")); g_signal_connect (G_OBJECT (radio), "toggled", G_CALLBACK (dcc_toggle), GINT_TO_POINTER (VIEW_BOTH)); gtk_table_attach (GTK_TABLE (table), radio, 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0); group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)); radio = gtk_radio_button_new_with_mnemonic (group, _("Uploads")); g_signal_connect (G_OBJECT (radio), "toggled", G_CALLBACK (dcc_toggle), GINT_TO_POINTER (VIEW_UPLOAD)); gtk_table_attach (GTK_TABLE (table), radio, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0); group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)); radio = gtk_radio_button_new_with_mnemonic (group, _("Downloads")); g_signal_connect (G_OBJECT (radio), "toggled", G_CALLBACK (dcc_toggle), GINT_TO_POINTER (VIEW_DOWNLOAD)); gtk_table_attach (GTK_TABLE (table), radio, 2, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0); exp = gtk_expander_new (_("Details")); gtk_table_attach (GTK_TABLE (table), exp, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); detailbox = gtk_table_new (3, 3, FALSE); gtk_table_set_col_spacings (GTK_TABLE (detailbox), 6); gtk_table_set_row_spacings (GTK_TABLE (detailbox), 2); gtk_container_set_border_width (GTK_CONTAINER (detailbox), 6); g_signal_connect (G_OBJECT (exp), "activate", G_CALLBACK (dcc_exp_cb), detailbox); gtk_table_attach (GTK_TABLE (table), detailbox, 0, 4, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); dccfwin.file_label = dcc_detail_label (_("File:"), detailbox, 0); dccfwin.address_label = dcc_detail_label (_("Address:"), detailbox, 1); bbox = gtk_hbutton_box_new (); gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD); gtk_box_pack_end (GTK_BOX (vbox), bbox, FALSE, FALSE, 2); dccfwin.abort_button = gtkutil_button (bbox, GTK_STOCK_CANCEL, 0, abort_clicked, 0, _("Abort")); dccfwin.accept_button = gtkutil_button (bbox, GTK_STOCK_APPLY, 0, accept_clicked, 0, _("Accept")); dccfwin.resume_button = gtkutil_button (bbox, GTK_STOCK_REFRESH, 0, resume_clicked, 0, _("Resume")); dccfwin.open_button = gtkutil_button (bbox, 0, 0, browse_dcc_folder, 0, _("Open Folder...")); gtk_widget_set_sensitive (dccfwin.accept_button, FALSE); gtk_widget_set_sensitive (dccfwin.resume_button, FALSE); gtk_widget_set_sensitive (dccfwin.abort_button, FALSE); dcc_fill_window (3); gtk_widget_show_all (dccfwin.window); gtk_widget_hide (detailbox); return FALSE; } int fe_dcc_open_send_win (int passive) { /* combined send/recv GUI */ return fe_dcc_open_recv_win (passive); } /* DCC CHAT GUIs BELOW */ static GSList * dcc_chat_get_selected (void) { return treeview_get_selected (GTK_TREE_MODEL (dcccwin.store), dcccwin.sel, CCOL_DCC); } static void accept_chat_clicked (GtkWidget * wid, gpointer none) { struct DCC *dcc; GSList *start, *list; start = list = dcc_chat_get_selected (); for (; list; list = list->next) { dcc = list->data; dcc_get (dcc); } g_slist_free (start); } static void abort_chat_clicked (GtkWidget * wid, gpointer none) { struct DCC *dcc; GSList *start, *list; start = list = dcc_chat_get_selected (); for (; list; list = list->next) { dcc = list->data; dcc_abort (dcc->serv->front_session, dcc); } g_slist_free (start); } static void dcc_chat_close_cb (void) { dcccwin.window = NULL; } static void dcc_chat_append (struct DCC *dcc, GtkListStore *store, gboolean prepend) { GtkTreeIter iter; if (prepend) gtk_list_store_prepend (store, &iter); else gtk_list_store_append (store, &iter); dcc_prepare_row_chat (dcc, store, &iter, FALSE); } static void dcc_chat_fill_win (void) { struct DCC *dcc; GSList *list; GtkTreeIter iter; int i = 0; gtk_list_store_clear (GTK_LIST_STORE (dcccwin.store)); list = dcc_list; while (list) { dcc = list->data; if (dcc->type == TYPE_CHATSEND || dcc->type == TYPE_CHATRECV) { dcc_chat_append (dcc, dcccwin.store, FALSE); i++; } list = list->next; } /* if only one entry, select it (so Accept button can work) */ if (i == 1) { gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dcccwin.store), &iter); gtk_tree_selection_select_iter (dcccwin.sel, &iter); } } static void dcc_chat_row_cb (GtkTreeSelection *sel, gpointer user_data) { struct DCC *dcc; GSList *list; list = dcc_chat_get_selected (); if (!list) { gtk_widget_set_sensitive (dcccwin.accept_button, FALSE); gtk_widget_set_sensitive (dcccwin.abort_button, FALSE); return; } gtk_widget_set_sensitive (dcccwin.abort_button, TRUE); if (list->next) /* multi selection */ gtk_widget_set_sensitive (dcccwin.accept_button, TRUE); else { /* turn OFF/ON appropriate buttons */ dcc = list->data; if (dcc->dccstat == STAT_QUEUED && dcc->type == TYPE_CHATRECV) gtk_widget_set_sensitive (dcccwin.accept_button, TRUE); else gtk_widget_set_sensitive (dcccwin.accept_button, FALSE); } g_slist_free (list); } static void dcc_chat_dclick_cb (GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data) { accept_chat_clicked (0, 0); } int fe_dcc_open_chat_win (int passive) { GtkWidget *view, *vbox, *bbox; GtkListStore *store; if (dcccwin.window) { if (!passive) mg_bring_tofront (dcccwin.window); return TRUE; } dcccwin.window = mg_create_generic_tab ("DCCChat", _(DISPLAY_NAME": DCC Chat List"), FALSE, TRUE, dcc_chat_close_cb, NULL, 550, 180, &vbox, 0); gtk_container_set_border_width (GTK_CONTAINER (dcccwin.window), 3); gtk_box_set_spacing (GTK_BOX (vbox), 3); store = gtk_list_store_new (CN_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, GDK_TYPE_COLOR); view = gtkutil_treeview_new (vbox, GTK_TREE_MODEL (store), NULL, -1); dcc_add_column (view, CCOL_STATUS, CCOL_COLOR, _("Status"), FALSE); dcc_add_column (view, CCOL_NICK, CCOL_COLOR, _("Nick"), FALSE); dcc_add_column (view, CCOL_RECV, CCOL_COLOR, _("Recv"), TRUE); dcc_add_column (view, CCOL_SENT, CCOL_COLOR, _("Sent"), TRUE); dcc_add_column (view, CCOL_START, CCOL_COLOR, _("Start Time"), FALSE); gtk_tree_view_column_set_expand (gtk_tree_view_get_column (GTK_TREE_VIEW (view), 1), TRUE); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE); dcccwin.list = view; dcccwin.store = store; dcccwin.sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); gtk_tree_selection_set_mode (dcccwin.sel, GTK_SELECTION_MULTIPLE); g_signal_connect (G_OBJECT (dcccwin.sel), "changed", G_CALLBACK (dcc_chat_row_cb), NULL); /* double click */ g_signal_connect (G_OBJECT (view), "row-activated", G_CALLBACK (dcc_chat_dclick_cb), NULL); bbox = gtk_hbutton_box_new (); gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD); gtk_box_pack_end (GTK_BOX (vbox), bbox, FALSE, FALSE, 2); dcccwin.abort_button = gtkutil_button (bbox, GTK_STOCK_CANCEL, 0, abort_chat_clicked, 0, _("Abort")); dcccwin.accept_button = gtkutil_button (bbox, GTK_STOCK_APPLY, 0, accept_chat_clicked, 0, _("Accept")); gtk_widget_set_sensitive (dcccwin.accept_button, FALSE); gtk_widget_set_sensitive (dcccwin.abort_button, FALSE); dcc_chat_fill_win (); gtk_widget_show_all (dcccwin.window); return FALSE; } void fe_dcc_add (struct DCC *dcc) { switch (dcc->type) { case TYPE_RECV: if (dccfwin.window && (view_mode & VIEW_DOWNLOAD)) dcc_append (dcc, dccfwin.store, TRUE); break; case TYPE_SEND: if (dccfwin.window && (view_mode & VIEW_UPLOAD)) dcc_append (dcc, dccfwin.store, TRUE); break; default: /* chat */ if (dcccwin.window) dcc_chat_append (dcc, dcccwin.store, TRUE); } } void fe_dcc_update (struct DCC *dcc) { switch (dcc->type) { case TYPE_SEND: dcc_update_send (dcc); break; case TYPE_RECV: dcc_update_recv (dcc); break; default: dcc_update_chat (dcc); } } void fe_dcc_remove (struct DCC *dcc) { GtkTreeIter iter; switch (dcc->type) { case TYPE_SEND: case TYPE_RECV: if (dccfwin.window) { if (dcc_find_row (dcc, GTK_TREE_MODEL (dccfwin.store), &iter, COL_DCC)) gtk_list_store_remove (dccfwin.store, &iter); } break; default: /* chat */ if (dcccwin.window) { if (dcc_find_row (dcc, GTK_TREE_MODEL (dcccwin.store), &iter, CCOL_DCC)) gtk_list_store_remove (dcccwin.store, &iter); } break; } }