#ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include /* Added for printer(), using isprint() */ #include #include #include #include #include "dctc_process.h" #include "main.h" #include "misc_gtk.h" #include "do_connect.h" #include "init_fnc.h" #include "str_array.h" #include "tos_key.h" #include "timed_out_string.h" #include "gui_define.h" #include "ls_cache.h" #include "gdl_ctree.h" #include "find_result_clist.h" #include "user_file_list_clist.h" #include "userinfo.h" #include "user_clist.h" #include "search.xpm" GPtrArray *op_array=NULL; /* forward declaration */ static void notify_private_chat(char *nickname); static void update_users_info(void); /******************************************************************************/ /* count the number of entry inside the given gchar * array (NULL terminated) */ /******************************************************************************/ int gchar_array_len(gchar **array) { int nb=0; if (array==NULL) return 0; while(array[nb]!=NULL) nb++; return nb; } /*************************************************************/ /* close the connection to the current DCTC client if exists */ /*************************************************************/ void close_current_dctc(void) { if(current_dctc==NULL) return; close_and_free_dctc_com(current_dctc); current_dctc=NULL; } /************************************************************/ /* find the index of the given nickname in the "user_clist" */ /************************************************************/ /* input: clst= GtkCList of "user_clist" */ /* nickname= nick to search */ /*****************************************/ /* output: idx or -1 if not found */ /**********************************/ static int get_user_idx_for_user_clist(GtkCList *clst, const char *nickname) { int i; for(i=0;irows;i++) { USER_CL_ENTRY *uce; uce=gtk_clist_get_row_data(clst,i); if((uce!=NULL)&&(!strcmp(uce->nickname,nickname))) { return i; } } return -1; } /*********************************************************/ /* check if the given nickname appears in the user_clist */ /*********************************************************/ /* output: -1=no else position in the clist */ /********************************************/ static int user_here(char *nickname) { GtkWidget *w; w=get_widget_by_widget_name("user_clist"); if(w==NULL) return -1; return get_user_idx_for_user_clist(GTK_CLIST(w),nickname); } /***************************************************/ /* delete the array containing the nick of all ops */ /***************************************************/ void clear_op_array(void) { str_array_destroy(op_array); op_array=NULL; } /********************************/ /* print a line to stdout */ /* filter out unprintable chars */ /* adds a newline to the end */ /********************************/ static void printer(const GString *s) { char *p = s->str; /* printf("DEBUG: printer()\n"); */ while ( p[0] != '\0' ) { if ( isprint(p[0]) ) printf("%c", p[0]); else printf(" "); p++; } printf("\n"); /* printf("DEBUG: printer() END\n"); */ } /************************/ /* get a line from DCTC */ /******************************************************************************/ /* input: with_recv == 1, we read the sock_fd. ==0, we use the data in buffer */ /******************************************************************************/ static GString *get_dctc_line(int with_recv) { GString *s; #if 0 int n; char c; if(current_dctc==NULL) return NULL; s=g_string_sized_new(512); do { n=read(current_dctc->dctc_fd,&c,1); if(n!=1) { /* Using printer() instead printf("%s\n",s->str); */ printer(s); g_string_free(s,TRUE); close_current_dctc(); return NULL; } s=g_string_append_c(s,c); }while(c!='\n'); #else char *tmp; if(current_dctc==NULL) return NULL; /* if we should read the socket, read it and append data to the yet received one */ if(with_recv) { char buf[8192]; int n; read_again: n=recv(current_dctc->dctc_fd,buf,sizeof(buf)-1,MSG_NOSIGNAL); if(n==-1) { if(errno==EINTR) goto read_again; close_current_dctc(); return NULL; } if(n==0) { close_current_dctc(); return NULL; } buf[n]='\0'; current_dctc->incoming_data=g_string_append(current_dctc->incoming_data,buf); } /* full line received ? */ tmp=strchr(current_dctc->incoming_data->str,'\n'); if(tmp==NULL) return NULL; /* split the data in buffer at the first '\n'. The second part becomes the new data in buffer */ /* the first part is returned to the calling function */ s=current_dctc->incoming_data; current_dctc->incoming_data=g_string_sized_new(128); current_dctc->incoming_data=g_string_assign(current_dctc->incoming_data,tmp+1); s=g_string_truncate(s,tmp+1-s->str); #endif #if 0 printf("returned: =='%s'==\n",s->str); #endif return s; } static void dummy_fnc(const GString *s) { /* Using printer() instead printf("--> %s\n",s->str); */ GString *s2 = g_string_new(""); g_string_sprintf(s2, "--> %s", s->str); printer(s2); g_string_free(s2,TRUE); } /*******************************************************************/ /* this function adds the nickname to the user_clist or updates it */ /*******************************************************************/ static void add_or_update_user(char *cnx_type, char *nickname, char *size, unsigned long long share_size,char *email, char *description, unsigned int flag) { GtkWidget *w; GtkCList *clst; int fnd=-1; int row_num; int have_scrollbar=0; gfloat cur_scroll_pos=0; GtkAdjustment *adj; USER_CL_ENTRY *uce; int added=FALSE; w=get_widget_by_widget_name("user_clist"); if(w==NULL) return; clst=GTK_CLIST(w); gtk_clist_freeze(clst); /* @@@ GTK bug: sometimes, when adding add row, the clist is move to the bottom side */ adj=gtk_clist_get_vadjustment(clst); if(adj!=NULL) { have_scrollbar=1; cur_scroll_pos=adj->value; } fnd=get_user_idx_for_user_clist(clst, nickname); if(fnd==-1) { gchar *nw[5]; nw[0]=cnx_type; nw[1]=nickname; nw[2]=size; nw[3]=email; nw[4]=description; row_num=gtk_clist_append(clst,nw); uce=new_user_cl_entry(cnx_type,nickname,share_size,email,description,flag); gtk_clist_set_row_data_full(clst,row_num,uce,(void*)free_user_cl_entry); added=TRUE; } else { uce=gtk_clist_get_row_data(clst,fnd); /* update the cnx_type if necessary */ if(strcmp(cnx_type,uce->cnx_type)) { gtk_clist_set_text(clst,fnd,0,cnx_type); uce->cnx_type=get_const_string_for_cnx_type(cnx_type); } /* it is not necessary to set the nick because it is the same */ if(share_size!=uce->share_size) { gtk_clist_set_text(clst,fnd,2,size); uce->share_size=share_size; } if(strcmp(email,uce->email)) { gtk_clist_set_text(clst,fnd,3,email); free(uce->email); uce->email=strdup(email); } if(strcmp(description,uce->description)) { gtk_clist_set_text(clst,fnd,4,description); free(uce->description); uce->description=strdup(description); } row_num=fnd; } if((flag!=uce->flag)||(added==TRUE)) { if(flag&2) { /* user is away */ gtk_clist_set_background(clst,row_num,&light_grey); } else { /* user is here */ gtk_clist_set_background(clst,row_num,&white); } if(flag&8) { /* fast xfer (>100KB/s) */ gtk_clist_set_cell_style(clst,row_num,0,fast_style); } uce->flag=flag; } gtk_clist_sort(clst); gtk_clist_thaw(clst); /* @@@ GTK bug: sometimes, when adding add row, the clist is move to the bottom side */ if(have_scrollbar) { adj=gtk_clist_get_vadjustment(clst); if((adj!=NULL)&&(adj->value!=cur_scroll_pos)) { gtk_adjustment_set_value(adj,cur_scroll_pos); } } } static void colorize_queued_xfer_list(const char *nickname, GdkColor *bg_color) { GtkWidget *w; GtkCList *clst; int i; w=get_widget_by_widget_name("queue_clist"); if(w==NULL) return; clst=GTK_CLIST(w); gtk_clist_freeze(clst); for(i=0;irows;i++) { char *t; gtk_clist_get_text(clst,i,1,&t); if((t!=NULL)&&(!strcmp(t,nickname))) { gtk_clist_set_background(clst,i,bg_color); } } gtk_clist_thaw(clst); } typedef struct { GdkColor *bg_color; const char *nickname; } NICK_COLOR; /**********************************************************/ /* colorize active segment according to their user status */ /**********************************************************/ static void colorize_gdl_ctree_entry(GtkCTree *ctree, GtkCTreeNode *node, gpointer data) { GDL_CT_ENTRY *gce; NICK_COLOR *nc; if(GTK_CTREE_ROW(node)->level!=2) return; nc=data; gce=gtk_ctree_node_get_row_data(ctree,node); if((gce!=NULL)&&(gce->ct_type==GDL_ACTIVE_SEGMENT)&&(!strcmp(gce->c.active_segment.nickname,nc->nickname))) { gtk_ctree_node_set_background (ctree,node,nc->bg_color); } } static void colorize_gdl_ctree_list(const char *nickname, GdkColor *bg_color) { GtkWidget *w; NICK_COLOR nc; w=get_widget_by_widget_name("gdl_ctree"); if(w==NULL) return; nc.bg_color=bg_color; nc.nickname=nickname; gtk_ctree_pre_recursive_to_depth(GTK_CTREE(w),NULL,2,colorize_gdl_ctree_entry,&nc); } /****************************************************************/ /* the following function processes "USER ]" and "USER+]" lines */ /****************************************************************/ static void user__fnc(const GString *s) { char *t; char *nick; LMP_UINFO lu; int have_lu; /* "USER ]" and "USER+]" work in the same manner */ /* we check if the given user exists. If not, he is added to the user clist */ /* s format: USER ] "xxxxx"nickname| */ t=strchr(s->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; nick=t; t=strchr(nick,'|'); if(t==NULL) return; *t='\0'; if( (get_user_info(current_dctc->user_info_lmp,nick,&lu)) ||(!strcmp(lu.cnx_type,"Not defined")) ) /* entry exists but no information available */ { add_or_update_user("",nick,"",0,"","",0); have_lu=0; } else { GString *fsize=g_string_new(""); double vsize; vsize=lu.share_size; if(vsize>(1024.0*1024.0*1024.0)) #ifndef NO_PRINTF_LOCALE g_string_sprintf(fsize,"%.2fGB",vsize/(1024.0*1024.0*1024.0)); /* NO_PRINTF_LOCAL support added */ #else g_string_sprintf(fsize,"%.2fGB",vsize/(1024.0*1024.0*1024.0)); #endif else if(vsize>(1024.0*1024.0)) g_string_sprintf(fsize,"%.2fMB",vsize/(1024.0*1024.0)); else if(vsize>(1024.0)) g_string_sprintf(fsize,"%.2fKB",vsize/(1024.0)); else g_string_sprintf(fsize,"%.2fB",vsize); add_or_update_user(lu.cnx_type,nick,fsize->str,lu.share_size,lu.uemail,lu.udesc,((unsigned int)(lu.uflag))&255); g_string_free(fsize,TRUE); have_lu=1; update_users_info(); } if((have_lu==0)&&(!strncmp(s->str,"USER ]",6))) { /* retrieve user information only if not here */ GString *ui; ui=g_string_new("/UINFO "); g_string_sprintfa(ui,"%s\n",nick); send_data_to_dctc(ui->str); g_string_free(ui,TRUE); } colorize_queued_xfer_list(nick,&green); colorize_gdl_ctree_list(nick,&green); } /*****************************************************************/ /* remove the user having the given nickname from the user_clist */ /*****************************************************************/ static void remove_user(const char *nickname) { GtkWidget *w; GtkCList *clst; int i; int have_scrollbar=0; gfloat cur_scroll_pos=0; GtkAdjustment *adj; w=get_widget_by_widget_name("user_clist"); if(w==NULL) return; clst=GTK_CLIST(w); i=get_user_idx_for_user_clist(clst, nickname); if(i!=-1) { gtk_clist_freeze(clst); /* @@@ GTK bug: sometimes, when adding add row, the clist is move to the bottom side */ adj=gtk_clist_get_vadjustment(clst); if(adj!=NULL) { have_scrollbar=1; cur_scroll_pos=adj->value; } gtk_clist_remove(clst,i); gtk_clist_thaw(clst); /* @@@ GTK bug: sometimes, when adding add row, the clist is move to the bottom side */ if(have_scrollbar) { adj=gtk_clist_get_vadjustment(clst); if((adj!=NULL)&&(adj->value!=cur_scroll_pos)) { gtk_adjustment_set_value(adj,cur_scroll_pos); } } } colorize_queued_xfer_list(nickname,&white); colorize_gdl_ctree_list(nickname,&white); } static void update_users_info(void) { GtkWidget *w; GtkCList *clst; int i; char buf[5120]; double amount=0; w=get_widget_by_widget_name("user_clist"); if(w==NULL) return; clst=GTK_CLIST(w); for(i=0;irows;i++) { USER_CL_ENTRY *uce; uce=gtk_clist_get_row_data(clst,i); if(uce!=NULL) { amount+=((double)(uce->share_size)); } } #ifndef NO_PRINTF_LOCALE if( (amount/(1024.0*1024.0*1024.0)) > 1024.0) sprintf(buf,"%d users (%.2lfTB)",clst->rows,amount/(1024.0*1024.0*1024.0*1024.0)); /* NO_PRINTF_LOCAL support added */ else sprintf(buf,"%d users (%.2lfGB)",clst->rows,amount/(1024.0*1024.0*1024.0)); /* NO_PRINTF_LOCAL support added */ #else if( (amount/(1024.0*1024.0*1024.0)) > 1024.0) sprintf(buf,"%d users (%.2lfTB)",clst->rows,amount/(1024.0*1024.0*1024.0*1024.0)); else sprintf(buf,"%d users (%.2lfGB)",clst->rows,amount/(1024.0*1024.0*1024.0)); #endif w=get_widget_by_widget_name("users_info_label"); if(w==NULL) return; gtk_label_set(GTK_LABEL(w),buf); } /***************************************************/ /* the following function processes "USER-]" lines */ /***************************************************/ static void user_minus_fnc(const GString *s) { char *t; char *nick; /* "USER ]" and "USER+]" work in the same manner */ /* we check if the given user exists. If yes, he is remove from the user clist */ /* s format: USER ] "xxxxx"nickname| */ t=strchr(s->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; nick=t; t=strchr(nick,'|'); if(t==NULL) return; *t='\0'; /* remove this user from the op array (if exist) */ op_array=str_array_del(op_array,nick); notify_private_chat(nick); remove_user(nick); update_users_info(); } /***************************************************/ /* the following function processes "OP ]" lines */ /***************************************************/ static void op_fnc(const GString *s) { char *t; char *nick; /* s format: OP ] "xxxxx"nickname| */ t=strchr(s->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; nick=t; t=strchr(nick,'|'); if(t==NULL) return; *t='\0'; /* add this operator to the op array */ op_array=str_array_add(op_array,nick); /* colorize the nickname if exists and set the is_op flag */ { GtkWidget *w; GtkCList *clst; int i; w=get_widget_by_widget_name("user_clist"); if(w==NULL) return; clst=GTK_CLIST(w); i=get_user_idx_for_user_clist(clst,nick); if(i!=-1) { USER_CL_ENTRY *uce; gtk_clist_set_foreground(clst,i,&light_red); uce=gtk_clist_get_row_data(clst,i); if(uce!=NULL) uce->is_op=TRUE; } } } /***************************************************/ /* the following function processes "UINFO]" lines */ /***************************************************/ static void uinfo_fnc(const GString *s) { char *t; char *nick; char *size; char *cnx; char *mail; char *description; GString *fsize; double vsize; unsigned int flag; /* s format: UINFO] "xxxxx"nickname size cnx [(flag)misc] 'mail' description| */ t=strchr(s->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; nick=t; t=strchr(nick,' '); if(t==NULL) return; *t++='\0'; size=t; t=strchr(size,' '); if(t==NULL) return; *t++='\0'; cnx=t; t=strchr(cnx,' '); if(t==NULL) return; *t++='\0'; flag=strtoul(t+2,NULL,10); /* +2: we skip the [ and the ( */ t=strchr(t,'\''); if(t==NULL) return; t++; mail=t; t=strchr(mail,'\''); if(t==NULL) return; *t++='\0'; t++; description=t; t=strchr(description,'|'); if(t==NULL) return; *t='\0'; vsize=strtod(size,NULL); fsize=g_string_new(""); if(vsize>(1024.0*1024.0*1024.0)) #ifndef NO_PRINTF_LOCALE g_string_sprintf(fsize,"%.2fGB",vsize/(1024.0*1024.0*1024.0)); /* NO_PRINTF_LOCAL support added */ #else g_string_sprintf(fsize,"%.2fGB",vsize/(1024.0*1024.0*1024.0)); #endif else if(vsize>(1024.0*1024.0)) g_string_sprintf(fsize,"%.2fMB",vsize/(1024.0*1024.0)); else if(vsize>(1024.0)) g_string_sprintf(fsize,"%.2fKB",vsize/(1024.0)); else g_string_sprintf(fsize,"%.2fB",vsize); add_or_update_user(cnx,nick,fsize->str,vsize,mail,description, flag); g_string_free(fsize,TRUE); update_users_info(); } /***************************************************/ /* the following function processes "CHAT ]" lines */ /***************************************************/ static void chat_fnc(const GString *s) { char *t; char *msg; /* s format: CHAT ] "xxxxx"message| */ t=strchr(s->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; msg=t; t=strchr(msg,'|'); if(t==NULL) return; *t='\0'; /* replace \r by \n */ t=msg; while(*t!='\0') { if(*t=='\r') { if(t[1]=='\r') *t++=' '; *t='\n'; } t++; } { GtkWidget *w; char *eonick; /* Morra: Timestamp thingy */ struct tm tm; time_t tt; char timestamp[512]; tt=time(NULL); localtime_r(&tt,&tm); strftime(timestamp,sizeof(timestamp),"[ %H:%M:%S ]",&tm); w=get_widget_by_widget_name("chat_output"); if(w==NULL) return; eonick=strstr(msg,"> "); gtk_text_freeze(GTK_TEXT(w)); if((msg[0]!='<')||(eonick==NULL)) { gtk_text_insert(GTK_TEXT(w),NULL,NULL,NULL,msg,-1); } else { gtk_text_insert(GTK_TEXT(w),NULL,&light_grey,NULL, timestamp, strlen(timestamp)); gtk_text_insert(GTK_TEXT(w),NULL,&light_red,NULL,msg,eonick+1-msg); gtk_text_insert(GTK_TEXT(w),NULL,NULL,NULL,eonick+1,-1); } gtk_text_insert(GTK_TEXT(w),NULL,NULL,NULL,"\n",-1); gtk_text_thaw(GTK_TEXT(w)); /* keep the window at the bottom place */ { GtkAdjustment *v; float t; v=GTK_TEXT(w)->vadj; t=v->upper-v->page_size; gtk_adjustment_set_value(v,t>=0.0?t:0.0); } } } /***************************************************/ /* the following function processes "HUBNM]" lines */ /***************************************************/ static void hubnm_fnc(const GString *s) { char *t; char *msg; /* s format: HUBNM] "xxxxx"hubname| */ t=strchr(s->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; msg=t; t=strchr(msg,'|'); if(t==NULL) return; *t='\0'; { GtkWidget *w; w=get_widget_by_widget_name("xfer_notebook"); if(w==NULL) { printf("no widget app1\n"); return; } w=gtk_widget_get_toplevel(w); /* for an unknown reason, get_widget_by_widget_name doesn't work for "app1" */ gtk_window_set_title(GTK_WINDOW(w),msg); } /* display a message in the chat to notify hub change */ { GString *str; str=g_string_new("CHAT ] \"\">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\r" "entering hub "); g_string_sprintfa(str, "%s\r<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<|",msg); chat_fnc(str); g_string_free(str,TRUE); } } /***************************************************/ /* the following function processes "ERR ]" lines */ /***************************************************/ static void err_fnc(const GString *s) { char *t; char *fnc; char *msg; GString *out; /* s format: ERR ] "xxxxx"errmsg| */ t=strchr(s->str,'"'); if(t==NULL) return; fnc=t; t=strchr(t+1,'"'); if(t==NULL) return; t++; msg=t; t=strrchr(msg,'|'); if(t==NULL) return; *t='\0'; /* replace | by \n */ t=msg; while(*t!='\0') { if(*t=='|') *t='\n'; t++; } if(strstr(msg,"use /QUIT to quit")==NULL) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(get_widget_by_widget_name("disperrorcheckbutton")))==TRUE) { /* don't display the "use /QUIT to quit" message */ out=g_string_new(""); g_string_sprintfa(out,"\n%s\n",msg); gnome_app_error(GNOME_APP(main_window),out->str); g_string_free(out,TRUE); } { GtkWidget *w; struct tm tm; time_t tt; char bbb[512]; w=get_widget_by_widget_name("error_messages_text"); if(w==NULL) return; tt=time(NULL); localtime_r(&tt,&tm); strftime(bbb,sizeof(bbb),"%c: ",&tm); gtk_text_freeze(GTK_TEXT(w)); gtk_text_insert(GTK_TEXT(w),NULL,NULL,NULL,bbb,-1); gtk_text_insert(GTK_TEXT(w),NULL,NULL,NULL,msg,-1); gtk_text_insert(GTK_TEXT(w),NULL,NULL,NULL,"\n",-1); gtk_text_thaw(GTK_TEXT(w)); /* keep the window at the bottom place */ { GtkAdjustment *v; float t; v=GTK_TEXT(w)->vadj; t=v->upper-v->page_size; gtk_adjustment_set_value(v,t>=0.0?t:0.0); } } } } /*****************************************************************/ /* compare the given string to the pattern entered in find_entry */ /*****************************************************************/ /* output: 0=not invalid, !=0: is invalid */ /******************************************/ static int is_invalid_search_result(char *fname) { int i; GString to_find; if(last_started_search==NULL) return 0; /* no filter list -> result is ok */ i=0; while(last_started_search[i]!=NULL) { /* build a fake GString */ to_find.str=last_started_search[i]; to_find.len=strlen(to_find.str); if(my_strcasestr(&to_find,fname)==NULL) return 1; /* filtering string not found -> result is invalid */ i++; } return 0; /* all strings in the filter are available -> result is ok */ } static void set_same_color_as_row(GtkCList *clst, int current_row, int reference_row) { GtkCListRow *clist_row; clist_row=g_list_nth(clst->row_list,reference_row)->data; gtk_clist_set_background(clst,current_row,&(clist_row->background)); } static void set_different_color_as_row(GtkCList *clst, int current_row, int reference_row) { GtkCListRow *clist_row; clist_row=g_list_nth(clst->row_list,reference_row)->data; if(!memcmp(&(clist_row->background),&white,sizeof(GdkColor))) { if(reference_rowbackground),&greyDD,sizeof(GdkColor))) { if(reference_rowrow_list,reference_row)->data; clist_row_next=g_list_nth(clst->row_list,reference_row_next)->data; if(!memcmp(&(clist_row->background),&white,sizeof(GdkColor))) { if(!memcmp(&(clist_row_next->background),&greyEE,sizeof(GdkColor))) gtk_clist_set_background(clst,current_row,&greyDD); else gtk_clist_set_background(clst,current_row,&greyEE); } else if(!memcmp(&(clist_row->background),&greyDD,sizeof(GdkColor))) { if(!memcmp(&(clist_row_next->background),&white,sizeof(GdkColor))) gtk_clist_set_background(clst,current_row,&greyEE); else gtk_clist_set_background(clst,current_row,&white); } else { if(!memcmp(&(clist_row_next->background),&greyDD,sizeof(GdkColor))) gtk_clist_set_background(clst,current_row,&white); else gtk_clist_set_background(clst,current_row,&greyDD); } } /***************************************************/ /* the following function processes "SREST]" lines */ /***************************************************/ static void srest_fnc(const GString *s) { char *t; char *nick; char *fname; char *size; char *dl_ratio; char *hubname; char *hubip; char *localfname; GString *hub; /* s format: SREST] "xxxxx"nickname|file|size|ratio|hubname|hubip| */ /* (result of SEARCH and MSEARCH) */ /* or */ /* s format: SREST] "xxxxx"nickname|file|size|ratio|hubname|hubip|localfname| */ /* (result of CSEARCH) */ t=strchr(s->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; nick=t; t=strchr(nick,'|'); if(t==NULL) return; *t++='\0'; fname=t; t=strchr(fname,'|'); if(t==NULL) return; *t++='\0'; /* check post-filtering option */ { GtkWidget *w; w=get_widget_by_widget_name("postfiltering_checkbutton"); if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))==TRUE) { /* we must do post-filtering */ if(is_invalid_search_result(fname)) return; } } size=t; t=strchr(size,'|'); if(t==NULL) return; *t++='\0'; dl_ratio=t; t=strchr(dl_ratio,'|'); if(t==NULL) return; *t++='\0'; hubname=t; t=strchr(hubname,'|'); if(t==NULL) return; *t++='\0'; hubip=t; t=strchr(hubip,'|'); if(t==NULL) return; *t++='\0'; localfname=t; t=strchr(localfname,'|'); if(t==NULL) localfname=""; else *t++='\0'; hub=g_string_new(""); g_string_sprintf(hub,"%s (%s)",hubname,hubip); { GtkWidget *w; GtkCList *clst; w=get_widget_by_widget_name("find_result"); if(w!=NULL) { int have_scrollbar=0; GtkAdjustment *adj; gfloat cur_scroll_pos=0; clst=GTK_CLIST(w); gtk_clist_freeze(clst); /* @@@ GTK bug: sometimes, when adding add row, the clist is move to the bottom side */ adj=gtk_clist_get_vadjustment(clst); if(adj!=NULL) { have_scrollbar=1; cur_scroll_pos=adj->value; } { int num_row; FIND_CL_ENTRY *fce; unsigned long fsize; unsigned int free_slot,ttl_slot; char buf_size[64]; FIND_CL_ENTRY *other_fce; LMP_UINFO nickuinfo; gchar *nw[6]; if(get_user_info(current_dctc->user_info_lmp,nick,&nickuinfo)) { nickuinfo.cnx_type[0]='\0'; /* no information available */ } sscanf(size,"%lu",&fsize); #ifndef NO_PRINTF_LOCALE sprintf(buf_size,"%lu",fsize); /* NO_PRINTF_LOCAL support added */ #else sprintf(buf_size,"%lu",fsize); #endif sscanf(dl_ratio,"%u/%u",&free_slot,&ttl_slot); nw[0]=nick; nw[1]=fname; nw[2]=buf_size; nw[3]=dl_ratio; nw[4]=nickuinfo.cnx_type; nw[5]=hub->str; /* the list is not in auto-sort mode because auto-sort needs row data information */ /* unfortunatelly, after row data is set, the row is probably at the wrong place */ /* thus we must sort the list. The big problem is after sorting the list, the row */ /* number we have becomes incorrect, we must search the correct row number using */ /* the row data we have inserted. */ num_row=gtk_clist_insert(clst,0,nw); fce=new_cl_entry(nick,fname,fsize,free_slot,ttl_slot,hub->str,nickuinfo.cnx_type); gtk_clist_set_row_data_full(clst,num_row,fce,(void*)free_find_cl_entry); gtk_clist_sort(clst); num_row=gtk_clist_find_row_from_data(clst,fce); /* put operator result in red */ if(str_array_is_inside(op_array,nw[0])) { gtk_clist_set_foreground(clst,num_row,&light_red); } if(clst->sort_column==FRC_SIZE_COL) /* sort by size ? => colorize row */ { if(clst->rows==1) { /* only one row in the list ? */ gtk_clist_set_background(clst,num_row,&white); } else if(num_row==0) { /* first row of the list ? */ other_fce=gtk_clist_get_row_data(clst,num_row+1); if(other_fce->file_size==fsize) set_same_color_as_row(clst,num_row,num_row+1); else set_different_color_as_row(clst,num_row,num_row+1); } else if(num_row==clst->rows-1) { /* last row of the list ? */ other_fce=gtk_clist_get_row_data(clst,num_row-1); if(other_fce->file_size==fsize) set_same_color_as_row(clst,num_row,num_row-1); else set_different_color_as_row(clst,num_row,num_row-1); } else { /* row in the middle of the list */ other_fce=gtk_clist_get_row_data(clst,num_row-1); if(other_fce->file_size==fsize) set_same_color_as_row(clst,num_row,num_row-1); else { other_fce=gtk_clist_get_row_data(clst,num_row+1); if(other_fce->file_size==fsize) set_same_color_as_row(clst,num_row,num_row+1); else set_different_color_as_2_rows(clst,num_row,num_row-1,num_row+1); } } } } gtk_clist_thaw(clst); /* @@@ GTK bug: sometimes, when adding add row, the clist is move to the bottom side */ if(have_scrollbar) { adj=gtk_clist_get_vadjustment(clst); if((adj!=NULL)&&(adj->value!=cur_scroll_pos)) { gtk_adjustment_set_value(adj,cur_scroll_pos); } } } } g_string_free(hub,TRUE); } #if 0 #else static void update_lists(const GString *s) { send_data_to_dctc("/XFER\n/SLOWGDLLST\n"); } static void update_lists_force_gdl(const GString *s) { send_data_to_dctc("/GDLLST\n"); } /****************************************************************/ /* free the given GPtrArray of gchar ** (freed with g_strfreev) */ /****************************************************************/ static void free_temp_array(GPtrArray **temp_array) { int i; if(*temp_array==NULL) return; for(i=0;i<(*temp_array)->len;i++) { gchar **k; k=g_ptr_array_index((*temp_array),i); if(k) g_strfreev(k); } g_ptr_array_free((*temp_array),TRUE); *temp_array=NULL; } static GPtrArray *xferr_temp_array=NULL; /* it is an array of gchar ** (each has been obtain using g_strsplit on one line of XFERR) */ static GPtrArray *xferq_temp_array=NULL; /* it is an array of gchar ** (each has been obtain using g_strsplit on one line of XFERQ) */ static GPtrArray *cmdkb_temp_array=NULL; /* it is an array of gchar ** (each has been obtain using g_strsplit on one line of CMDKB) */ /******************************/ /* beginning of the xfer list */ /******************************/ static void begin_xfer_list_fnc(const GString *s) { free_temp_array(&xferr_temp_array); xferr_temp_array=g_ptr_array_new(); free_temp_array(&xferq_temp_array); xferq_temp_array=g_ptr_array_new(); free_temp_array(&cmdkb_temp_array); cmdkb_temp_array=g_ptr_array_new(); } /****************************************/ /* add an xferr entry to its temp array */ /****************************************/ static void add_xferr_fnc(const GString *in) { gchar **fields; char *t; t=strchr(in->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; fields=g_strsplit(t,"|",0); if((fields[0]!=NULL)&&(fields[1]!=NULL)&&(fields[2]!=NULL)) { g_ptr_array_add(xferr_temp_array,fields); } else g_strfreev(fields); } /****************************************/ /* add an xferq entry to its temp array */ /****************************************/ static void add_xferq_fnc(const GString *in) { gchar **fields; char *t; t=strchr(in->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; fields=g_strsplit(t,"|",0); if((fields[0]!=NULL)&&(fields[1]!=NULL)) { g_ptr_array_add(xferq_temp_array,fields); } else g_strfreev(fields); } /****************************************/ /* add an cmdkb entry to its temp array */ /****************************************/ static void add_cmdkb_fnc(const GString *in) { gchar **fields; char *t; t=strchr(in->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; fields=g_strsplit(t,"|",0); if((fields[0]!=NULL)&&(fields[1]!=NULL)&&(fields[2]!=NULL)) { g_ptr_array_add(cmdkb_temp_array,fields); } else g_strfreev(fields); } /*====================================================================================================*/ /*= XFERR clist update =*/ /*======================*/ /***************************************************************/ /* update the given row of the given clist using ptr parameter */ /***************************************************************/ static void update_xferr_dl_row(GtkCList *clst,int num_row, gchar **entry) { if(!strncmp(entry[2],"LS/",3)) { gtk_clist_set_text(clst,num_row,2,""); gtk_clist_set_text(clst,num_row,3,""); gtk_clist_set_text(clst,num_row,4,"File list"); gtk_clist_set_text(clst,num_row,5,""); } else if(!strncmp(entry[2],"DL/",3)) { /* entry[2]+3== the remote filename (followed by a $ and a digit). */ /* entry[3]=local filename */ /* entry[4]=download start position */ /* entry[5]=size of the complete file */ /* entry[6]=download start time (obtained using time()). */ /* entry[7]="the remote host name (the IP or the FQDN)":"the remote host port" */ char *t; t=strrchr(entry[2]+3,'$'); /* remote start position of the remote filename */ if(t!=NULL) { *t='\0'; } gtk_clist_set_text(clst,num_row,2,entry[5]); gtk_clist_set_text(clst,num_row,3,""); gtk_clist_set_text(clst,num_row,4,entry[2]+3); gtk_clist_set_text(clst,num_row,5,entry[3]); update_dl_clist_size(clst,num_row,entry[5],get_var("dl_path")); } } /***************************************************************/ /* update the given row of the given clist using ptr parameter */ /***************************************************************/ static void update_xferr_ul_row(GtkCList *clst,int num_row, gchar **entry) { int set=0; unsigned long val1; unsigned long *ptr_status; int size_status; gtk_clist_set_text(clst,num_row,4,entry[2]+3); /* try to restore the current transfer status */ val1=strtoul(entry[0],NULL,10); if(get_tos_entry(ULST_TOSKEY,(char*)&val1,sizeof(unsigned long),0, (char**)&ptr_status, &size_status)) { if(size_status==(5*sizeof(unsigned long))) { char stt[512]; sprintf(stt,"%lu",ptr_status[2]); gtk_clist_set_text(clst,num_row,2,stt); sprintf(stt,"%lu (%.2f%%)",ptr_status[1]+ptr_status[3] /* => current global position */, 100*((float)(ptr_status[1]+ptr_status[3]))/(float)(ptr_status[2])); gtk_clist_set_text(clst,num_row,3,stt); set=1; } if(ptr_status) free(ptr_status); } if(!set) { gtk_clist_set_text(clst,num_row,2,""); gtk_clist_set_text(clst,num_row,3,""); } } static void create_xferr_row(GtkCList *dl_clst, GtkCList *up_clst, gchar **entry) { char *nw[6]; int num_row; /* entry[0]= id */ /* entry[1]= nickname */ /* entry[2]= the command */ /* entry[3...]= end with null array of command arguments */ nw[0]=entry[0]; nw[1]=entry[1]; if(!strncmp(entry[2],"LS/",3)) { nw[2]=""; nw[3]=""; nw[4]="File list"; nw[5]=""; num_row=gtk_clist_append(dl_clst,nw); /* put operator xfer in red */ if(str_array_is_inside(op_array,nw[1])) { gtk_clist_set_foreground(dl_clst,num_row,&light_red); } } else if(!strncmp(entry[2],"UL/",3)) { unsigned long val1; unsigned long *ptr_status; int size_status; nw[2]=""; nw[3]=""; nw[4]=entry[2]+3; num_row=gtk_clist_append(up_clst,nw); /* try to restore the current transfer status */ val1=strtoul(nw[0],NULL,10); if(get_tos_entry(ULST_TOSKEY,(char*)&val1,sizeof(unsigned long),0, (char**)&ptr_status, &size_status)) { if(size_status==(5*sizeof(unsigned long))) { char stt[512]; #ifndef NO_PRINTF_LOCALE sprintf(stt,"%lu",ptr_status[2]); /* NO_PRINTF_LOCAL support added */ #else sprintf(stt,"%lu",ptr_status[2]); #endif gtk_clist_set_text(up_clst,num_row,2,stt); #ifndef NO_PRINTF_LOCALE sprintf(stt,"%lu (%.2f%%)",ptr_status[1]+ptr_status[3] /* => current global position */, /* NO_PRINTF_LOCAL support added */ 100*((float)(ptr_status[1]+ptr_status[3]))/(float)(ptr_status[2])); #else sprintf(stt,"%lu (%.2f%%)",ptr_status[1]+ptr_status[3] /* => current global position */, 100*((float)(ptr_status[1]+ptr_status[3]))/(float)(ptr_status[2])); #endif gtk_clist_set_text(up_clst,num_row,3,stt); } if(ptr_status) free(ptr_status); } /* put operator xfer in red */ if(str_array_is_inside(op_array,nw[1])) { gtk_clist_set_foreground(up_clst,num_row,&light_red); } } else if(!strncmp(entry[2],"DL/",3)) { /* entry[2]+3== the remote filename (followed by a $ and a digit). */ /* entry[3]=local filename */ /* entry[4]=download start position */ /* entry[5]=size of the complete file */ /* entry[6]=download start time (obtained using time()). */ /* entry[7]="the remote host name (the IP or the FQDN)":"the remote host port" */ char *t; int rw; unsigned long start_pos=strtoul(entry[4],NULL,10); time_t start_time=strtoul(entry[6],NULL,10); nw[2]=entry[5]; /* file full size */ nw[3]=""; /* no speed */ nw[4]=entry[2]+3; /* remote filename */ nw[5]=entry[3]; /* local filename */ t=strrchr(nw[4],'$'); if(t!=NULL) { *t='\0'; } rw=gtk_clist_append(dl_clst,nw); /* put operator xfer in red */ if(str_array_is_inside(op_array,nw[1])) { gtk_clist_set_foreground(dl_clst,rw,&light_red); } { DL_XTRA *xt; xt=malloc(sizeof(DL_XTRA)); if(xt==NULL) { gtk_clist_set_row_data(dl_clst,rw,NULL); } else { xt->start_time=start_time; xt->start_pos=start_pos; gtk_clist_set_row_data_full(dl_clst,rw,xt,free); } } update_dl_clist_size(dl_clst,rw,nw[2],get_var("dl_path")); } } /*******************************************************************************/ /* scan download and upload clist, remove all running xfer which no more exist */ /* and update the matching one */ /*******************************************************************************/ static void clean_running_ul_and_dl_clist(GtkCList *dl_clst, GtkCList *up_clst) { int i; int j; char *xfer_id; /* first, the download clist */ for(i=dl_clst->rows-1;i>=0;i--) { if(gtk_clist_get_text(dl_clst,i,0,&xfer_id)) { if(strlen(xfer_id)) /* xferq entries has an empty string as ID */ { int found=0; for(j=0;jlen;j++) { gchar **ptr; ptr=g_ptr_array_index(xferr_temp_array,j); if((ptr!=NULL)&&(ptr[0][0]!='\001')) { if(!strcmp(xfer_id,ptr[0])) { update_xferr_dl_row(dl_clst,i,ptr); ptr[0][0]='\001'; found=1; break; } } } if(!found) { gtk_clist_remove(dl_clst,i); } } } } /* and the upload clist */ for(i=up_clst->rows-1;i>=0;i--) { if(gtk_clist_get_text(up_clst,i,0,&xfer_id)) { int found=0; for(j=0;jlen;j++) { gchar **ptr; ptr=g_ptr_array_index(xferr_temp_array,j); if((ptr!=NULL)&&(ptr[0][0]!='\001')) { if(!strcmp(xfer_id,ptr[0])) { update_xferr_ul_row(up_clst,i,ptr); ptr[0][0]='\001'; found=1; break; } } } if(!found) { gtk_clist_remove(up_clst,i); } } } } static void end_xfer_update_xferr(void) { GtkWidget *dl_clst, *ul_clst; int i; dl_clst=get_widget_by_widget_name("download_clist"); if(dl_clst==NULL) return; ul_clst=get_widget_by_widget_name("upload_clist"); if(ul_clst==NULL) return; gtk_clist_freeze(GTK_CLIST(dl_clst)); gtk_clist_freeze(GTK_CLIST(ul_clst)); /* remove all entries of the queue_clist which are no more inside cmdkb_temp_array */ clean_running_ul_and_dl_clist(GTK_CLIST(dl_clst),GTK_CLIST(ul_clst)); /* and add all missing entries */ for(i=0;ilen;i++) { gchar **ptr; ptr=g_ptr_array_index(xferr_temp_array,i); if(ptr!=NULL) { if(ptr[0][0]!='\001') { /* unseen entry, time to add it */ create_xferr_row(GTK_CLIST(dl_clst),GTK_CLIST(ul_clst),ptr); } } } gtk_clist_thaw(GTK_CLIST(dl_clst)); gtk_clist_thaw(GTK_CLIST(ul_clst)); /* free temp array buffer */ free_temp_array(&xferr_temp_array); } /*====================================================================================================*/ /*= XFERQ clist update =*/ /*======================*/ static void update_xferq_row(GtkCList *clst,int num_row,gchar **ptr) { if(!strncmp(ptr[1],"LS/",3)) { gtk_clist_set_text(clst,num_row,3,""); gtk_clist_set_text(clst,num_row,4,"File list"); gtk_clist_set_text(clst,num_row,5,""); } else if(!strncmp(ptr[1],"DL/",3)) { /* ptr[2]=remote filename */ /* ptr[3]=local filename */ gtk_clist_set_text(clst,num_row,3,""); gtk_clist_set_text(clst,num_row,4,ptr[3]); /* FIXME: inverted values ? */ gtk_clist_set_text(clst,num_row,5,ptr[2]); } else { gtk_clist_set_text(clst,num_row,3,"?"); gtk_clist_set_text(clst,num_row,4,"?"); gtk_clist_set_text(clst,num_row,5,"?"); } } static void clean_queued_dl_clist(GtkCList *clst) { int i; int j; char *xfer_id; char *nickname; /* first, the download clist */ for(i=clst->rows-1;i>=0;i--) { if(gtk_clist_get_text(clst,i,0,&xfer_id)) { if(strlen(xfer_id)==0) /* xferq entries has an empty string as ID */ { if(gtk_clist_get_text(clst,i,1,&nickname)) { int found=0; for(j=0;jlen;j++) { gchar **ptr; ptr=g_ptr_array_index(xferq_temp_array,j); if((ptr!=NULL)&&(ptr[0][0]!='\001')) { if(!strcmp(nickname,ptr[0])) { update_xferq_row(clst,i,ptr); ptr[0][0]='\001'; found=1; break; } } } if(!found) { gtk_clist_remove(clst,i); } } } } } } static void create_xferq_row(GtkCList *clst,gchar **ptr) { char *nw[6]; int num_row; nw[0]=""; nw[1]=ptr[0]; nw[2]="trying"; nw[3]=""; if(!strncmp(ptr[1],"LS/",3)) { nw[4]="File list"; nw[5]=""; } else if(!strncmp(ptr[1],"DL/",3)) { /* ptr[2]=remote filename */ /* ptr[3]=local filename */ nw[4]=ptr[3]; /* FIXME: inverted values ? */ nw[5]=ptr[2]; } else { nw[3]="?"; nw[4]="?"; nw[5]="?"; } num_row=gtk_clist_append(clst,nw); /* put operator xfer in red */ if(str_array_is_inside(op_array,nw[1])) { gtk_clist_set_foreground(clst,num_row,&light_red); } } static void end_xfer_update_xferq(void) { GtkWidget *dl_clst; /* queued xfers only appear in download clist */ int i; dl_clst=get_widget_by_widget_name("download_clist"); if(dl_clst==NULL) return; gtk_clist_freeze(GTK_CLIST(dl_clst)); /* remove all entries of the queue_clist which are no more inside cmdkb_temp_array */ clean_queued_dl_clist(GTK_CLIST(dl_clst)); /* and add all missing entries */ for(i=0;ilen;i++) { gchar **ptr; ptr=g_ptr_array_index(xferq_temp_array,i); if(ptr!=NULL) { if(ptr[0][0]!='\001') { /* unseen entry, time to add it */ create_xferq_row(GTK_CLIST(dl_clst),ptr); } } } gtk_clist_thaw(GTK_CLIST(dl_clst)); /* free temp array buffer */ free_temp_array(&xferq_temp_array); } /*====================================================================================================*/ /*= CMDKB clist update =*/ /*======================*/ /********************************************************************************************/ /* scan the queue_clist and remove all entries which are not inside cmdkb_temp_array */ /* at the same time, mark ('\001') each cmdkb_temp_array entry which are found in the clist */ /********************************************************************************************/ static void clean_queue_clist(GtkCList *clst) { int i; int j; char *cmdkb_id; for(i=clst->rows-1;i>=0;i--) { if(gtk_clist_get_text(clst,i,0,&cmdkb_id)) { int found=0; for(j=0;jlen;j++) { gchar **ptr; ptr=g_ptr_array_index(cmdkb_temp_array,j); if((ptr!=NULL)&&(ptr[0][0]!='\001')) { if(!strcmp(cmdkb_id,ptr[0])) { ptr[0][0]='\001'; found=1; break; } } } if(!found) { gtk_clist_remove(clst,i); } } } } static void end_xfer_update_cmdkb(void) { char *nw[5]; GtkWidget *w; int i; int num_row; w=get_widget_by_widget_name("queue_clist"); if(w==NULL) return; gtk_clist_freeze(GTK_CLIST(w)); /* remove all entries of the queue_clist which are no more inside cmdkb_temp_array */ clean_queue_clist(GTK_CLIST(w)); /* and add all missing entries */ for(i=0;ilen;i++) { gchar **ptr; ptr=g_ptr_array_index(cmdkb_temp_array,i); if(ptr!=NULL) { if(ptr[0][0]!='\001') { /* unseen entry, time to add it */ if(!strncmp(ptr[2],"/LS ",4)) /* is the waiting command a /LS ? */ { char *nw[5]; nw[0]=ptr[0]; /* the waiting ID */ nw[1]=ptr[2]+4; /* the nickname */ nw[2]="File list"; nw[3]=""; nw[4]=""; num_row=gtk_clist_append(GTK_CLIST(w),nw); if(user_here(nw[1])!=-1) gtk_clist_set_background(GTK_CLIST(w),num_row,&green); /* put operator xfer in red */ if(str_array_is_inside(op_array,nw[1])) { gtk_clist_set_foreground(GTK_CLIST(w),num_row,&light_red); } } else if(!strncmp(ptr[2],"/DL ",4)) { gchar **tmp_split=NULL; int is_set=0; if(ptr[2][4]=='\0') /* the used separator is a | parameters are inside ptr */ { if((ptr[3]!=NULL)&&(ptr[4]!=NULL)&&(ptr[5]!=NULL)&&(ptr[6]!=NULL)) /* nickname,localname,remotename,filesize */ { nw[0]=ptr[0]; /* the waiting ID */ nw[1]=ptr[3]; /* the nickname */ nw[2]=ptr[5]; /* the remote filename */ nw[3]=ptr[6]; /* the size */ nw[4]=ptr[4]; /* the localname */ is_set=1; } } else { /* the used parameter is not a | */ /* thus, it is not yet splited */ char sep[2]; sep[0]=ptr[2][4]; sep[1]='\0'; tmp_split=g_strsplit(ptr[2],sep,0); if((ptr[1]!=NULL)&&(ptr[2]!=NULL)&&(ptr[3]!=NULL)&&(ptr[4]!=NULL)) /* nickname,localname,remotename,filesize */ { nw[0]=ptr[0]; /* the waiting ID */ nw[1]=ptr[1]; /* the nickname */ nw[2]=ptr[3]; /* the remote filename */ nw[3]=ptr[4]; /* the size */ nw[4]=ptr[2]; /* the localname */ is_set=1; } } if(is_set) { num_row=gtk_clist_append(GTK_CLIST(w),nw); if(user_here(nw[1])!=-1) gtk_clist_set_background(GTK_CLIST(w),num_row,&green); /* put operator xfer in red */ if(str_array_is_inside(op_array,nw[1])) { gtk_clist_set_foreground(GTK_CLIST(w),num_row,&light_red); } } if(tmp_split!=NULL) g_strfreev(tmp_split); } } } } gtk_clist_thaw(GTK_CLIST(w)); /* free temp array buffer */ free_temp_array(&cmdkb_temp_array); } /*====================================================================================================*/ /****************************************************************/ /* all temp arrays are filled, now, it is time to do the update */ /****************************************************************/ static void end_xfer_list_fnc(const GString *s) { /* update xferr list */ end_xfer_update_xferr(); /* update xferq list, easiest than previous one */ end_xfer_update_xferq(); /* and the easiest of all, the cmdkb array */ end_xfer_update_cmdkb(); } static void update_ul_list(const GString *in) { unsigned long values[5]; char *t; t=strchr(in->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; values[0]=strtoul(t,&t,10); /* thread id */ if((t==NULL)||(*t!=':')) return; t++; values[1]=strtoul(t,&t,10); /* upload start position */ if((t==NULL)||(*t!='/')) return; t++; values[2]=strtoul(t,&t,10); /* file length */ if((t==NULL)||(*t!='/')) return; t++; values[3]=strtoul(t,&t,10); /* sent data */ if((t==NULL)||(*t!='/')) return; t++; values[4]=strtoul(t,&t,10); /* total to send */ if((t==NULL)||(*t!='|')) return; /* keep a copy of the status so we can refresh the display at anytime */ add_tos_entry_v1_uniq(ULST_TOSKEY,300,(char*)&values[0],sizeof(unsigned long), (char*)&values[0],5*sizeof(unsigned long)); { GtkCList *clst; GtkWidget *w; int i; /* cmd is "UL/ficname" */ w=get_widget_by_widget_name("upload_clist"); if(w==NULL) return; clst=GTK_CLIST(w); /* search and update the row on the clist */ for(i=0;irows;i++) { char *txt; gtk_clist_get_text(clst,i,0,&txt); if(txt!=NULL) { if(values[0]==strtoul(txt,NULL,10)) { char stt[512]; gtk_clist_freeze(clst); #ifndef NO_PRINTF_LOCALE sprintf(stt,"%lu",values[2]); /* NO_PRINTF_LOCAL support added */ #else sprintf(stt,"%lu",values[2]); #endif gtk_clist_set_text(clst,i,2,stt); #ifndef NO_PRINTF_LOCALE sprintf(stt,"%lu (%.2f%%)",values[1]+values[3] /* => current global position */, /* NO_PRINTF_LOCAL support added */ 100*((float)(values[1]+values[3]))/(float)(values[2])); #else sprintf(stt,"%lu (%.2f%%)",values[1]+values[3] /* => current global position */, 100*((float)(values[1]+values[3]))/(float)(values[2])); #endif gtk_clist_set_text(clst,i,3,stt); gtk_clist_thaw(clst); break; } } } } } static int find_xfer_row(GtkWidget *w,char *nick, int col_fname, char *fname) { GtkCList *clst=GTK_CLIST(w); int i; for(i=0;irows;i++) { char *t; gtk_clist_get_text(clst,i,1,&t); if(!strcmp(t,nick)) { gtk_clist_get_text(clst,i,col_fname,&t); if(!strcmp(t,fname)) return i; } } return -1; } /***************************************************/ /* the following function processes "$DL- ]" lines */ /***************************************************/ static void remove_dl_xfer_on_success_fnc(const GString *s) { GtkWidget *w; char *t; char *nick; char *fname; int i; /* s format: ] "xxxxx"nickname|localfile| */ t=strchr(s->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; nick=t; t=strchr(nick,'|'); if(t==NULL) return; *t++='\0'; fname=t; t=strchr(fname,'|'); if(t==NULL) return; *t='\0'; w=get_widget_by_widget_name("download_clist"); if(w==NULL) return; i=find_xfer_row(w,nick,5,fname); if(i!=-1) { GtkWidget *w1; w1=get_widget_by_widget_name("done_clist"); if(w1!=NULL) { char *nw[5]; int j; for(j=1;j<6;j++) { gtk_clist_get_text(GTK_CLIST(w),i,j,&nw[j-1]); } gtk_clist_append(GTK_CLIST(w1),nw); } gtk_clist_remove(GTK_CLIST(w),i); } update_lists(NULL); } #endif /***************************************************/ /* the following function processes "VAR ]" lines */ /***************************************************/ static void var_fnc(const GString *s) { char *t; char *vname; char *vval; /* s format: ] "xxxxx"var_name|var_value| */ /* var value may contain | */ t=strchr(s->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; vname=t; t=strchr(vname,'|'); if(t==NULL) return; *t++='\0'; vval=t; t=strrchr(vval,'|'); if(t==NULL) return; *t='\0'; add_var(vname,vval); fix_pref_window(); } /***************************************************/ /* the following function processes "LUSER]" lines */ /***************************************************/ static void luser_fnc(const GString *s) { char *t; gchar **tmp_split; /* s format: ] "xxxxx"nickname|hubip:port|share size|userip:port */ /* var value may contain | */ t=strchr(s->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; tmp_split=g_strsplit(t,"|",4); if((tmp_split[0]!=NULL)&&(tmp_split[1]!=NULL)&&(tmp_split[2]!=NULL)&&(tmp_split[3]!=NULL)) { char *pattern; gtk_label_get(GTK_LABEL(get_widget_by_widget_name("currently_searched_user_label")),&pattern); if(!strcmp(pattern,tmp_split[0])) { GtkCList *clst=GTK_CLIST(get_widget_by_widget_name("locate_user_clist")); gtk_clist_freeze(clst); gtk_clist_append(clst,&(tmp_split[1])); gtk_clist_sort(clst); gtk_clist_thaw(clst); } } g_strfreev(tmp_split); } /*******************************************************************/ /* return the GTK_TEXT widget of the chat having the LABEL == nick */ /* if nick doesn't have a private chat and create parameter is */ /* true, the function creates one */ /*******************************************************************/ GtkWidget *get_pchat_text_widget_from_nick(char *nick, gboolean create,char **notebook_label,int *notebook_num) { GtkWidget *rhcw; int empty=-1; int i; for(i=0;i<9;i++) { rhcw=get_widget_by_widget_name(lbl_chat[i]); if(rhcw) { char *t; gtk_label_get(GTK_LABEL(rhcw),&t); if(t!=NULL) { if(!strcmp(t,nick)) { /* we have the entry */ (*notebook_label)=lbl_chat[i]; (*notebook_num)=i; return get_widget_by_widget_name(chat_text[i]); } if((empty==-1)&&(!strcmp(t,_("empty")))) { empty=i; } } } } if(empty!=-1 && create) { (*notebook_label)=lbl_chat[empty]; (*notebook_num)=empty; rhcw=get_widget_by_widget_name(lbl_chat[empty]); gtk_label_set(GTK_LABEL(rhcw),nick); return get_widget_by_widget_name(chat_text[empty]); } return NULL; } /***************************************************/ /* the following function processes "PRIV ]" lines */ /***************************************************/ static void pchat_fnc(const GString *s) { char *t; char *nick; char *msg; GtkWidget *chat_text; char *pchat_label; int pchat_num; /* the user has disabled private chat ? */ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(get_widget_by_widget_name("ignore_all_pmsg_checkbutton")))==TRUE) return; /* s format: ] "xxxxx"var_name|var_value| */ /* var value may contain | */ t=strchr(s->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; nick=t; t=strchr(nick,'|'); if(t==NULL) return; *t++='\0'; msg=t; t=strrchr(msg,'|'); if(t==NULL) return; *t='\0'; /* replace \r by \n */ t=msg; while(*t!='\0') { if(*t=='\r') { if(t[1]=='\r') { *t++=' '; } *t='\n'; } t++; } chat_text=get_pchat_text_widget_from_nick(nick,TRUE,&pchat_label,&pchat_num); if(chat_text!=NULL) { char *eonick; /* Morra: Timestamp thingy */ struct tm tm; time_t tt; char timestamp[512]; tt=time(NULL); localtime_r(&tt,&tm); strftime(timestamp,sizeof(timestamp),"[ %H:%M:%S ]",&tm); eonick=strstr(msg,"> "); gtk_text_freeze(GTK_TEXT(chat_text)); if((msg[0]!='<')||(eonick==NULL)) { gtk_text_insert(GTK_TEXT(chat_text),NULL,NULL,NULL,msg,-1); } else { gtk_text_insert(GTK_TEXT(chat_text),NULL,&light_grey,NULL,timestamp,-1); gtk_text_insert(GTK_TEXT(chat_text),NULL,&light_red,NULL,msg,eonick+1-msg); gtk_text_insert(GTK_TEXT(chat_text),NULL,NULL,NULL,eonick+1,-1); } gtk_text_insert(GTK_TEXT(chat_text),NULL,NULL,NULL,"\n",-1); gtk_text_thaw(GTK_TEXT(chat_text)); /* keep the window at the bottom place */ { GtkAdjustment *v; float t; v=GTK_TEXT(chat_text)->vadj; t=v->upper-v->page_size; gtk_adjustment_set_value(v,t>=0.0?t:0.0); } if(gtk_notebook_get_current_page(GTK_NOTEBOOK(get_widget_by_widget_name("main_notebook")))!=PRIVATE_CHAT_TAB) blink_on("private_chat_page"); if(gtk_notebook_get_current_page(GTK_NOTEBOOK(get_widget_by_widget_name("chat_notebook")))!=pchat_num) blink_on(pchat_label); } else { GString *out; out=g_string_new(""); g_string_sprintfa(out,"WARNING: all private chats are busy, close unused one.\n" "From %s\n%s\n",nick,msg); gnome_app_error(GNOME_APP(main_window),out->str); g_string_free(out,TRUE); } } /****************************************************************/ /* When user leaves the hub and a private chat session is open, */ /* display a message in chat window */ /****************************************************************/ static void notify_private_chat(char *nickname) { GString *msg; GtkWidget *chat_text; char *pchat_label; int pchat_num; chat_text=get_pchat_text_widget_from_nick(nickname,FALSE,&pchat_label,&pchat_num); if(chat_text!=NULL) { msg=g_string_new(""); g_string_sprintf(msg,"*** User %s has left the hub ***\n", nickname); gtk_text_freeze(GTK_TEXT(chat_text)); gtk_text_insert(GTK_TEXT(chat_text),NULL,NULL,NULL,msg->str,-1); gtk_text_thaw(GTK_TEXT(chat_text)); /* keep the window at the bottom place */ { GtkAdjustment *v; float t; v=GTK_TEXT(chat_text)->vadj; t=v->upper-v->page_size; gtk_adjustment_set_value(v,t>=0.0?t:0.0); } g_string_free(msg,TRUE); if(gtk_notebook_get_current_page(GTK_NOTEBOOK(get_widget_by_widget_name("main_notebook")))!=PRIVATE_CHAT_TAB) blink_on("private_chat_page"); if(gtk_notebook_get_current_page(GTK_NOTEBOOK(get_widget_by_widget_name("chat_notebook")))!=pchat_num) blink_on(pchat_label); } } typedef struct { char *searched_string; int level; GtkCTreeNode *matching_cnode; } SEARCH_IN_CTREE; int nb_matching=0; int nb_add=0; int nb_tst=0; static GString *last_inserted_path=NULL; static GtkCTreeNode *last_inserted_node=NULL; static int last_tree_level=0; static void is_a_matching_ctree_node(GtkCTree *ctree, GtkCTreeNode *cnode, gpointer data) { SEARCH_IN_CTREE *sic=data; gchar *col_content; nb_matching++; if(sic->matching_cnode!=NULL) /* we have already find the wanted entry ? */ return; if(GTK_CTREE_ROW(cnode)->level!=sic->level) return; nb_tst++; /* the first column of a ctree is always a pixtext */ if(gtk_ctree_node_get_pixtext(ctree,cnode,UFLC_TREE_COL,&col_content,NULL,NULL,NULL)) { if(!strcmp(col_content,sic->searched_string)) { sic->matching_cnode=cnode; } } } /***************************************************************************************/ /* insert the given row into the given ctree, on the given node (can be NULL for root) */ /*******************************************************************************************/ /* nw is a 4 strings array. The first string is allocated with g_malloc, others are static */ /* you can alter nw[0] value and pointer but you should not g_free the original nw[0] */ /*******************************************************************************************/ static void add_row_to_user_file_list_ctree(GtkCTree *ctree,GtkCTreeNode *cnode,char *nw[4], int current_tree_level) { char *delimit; nb_add++; delimit=strchr(nw[0],'\\'); if(delimit==NULL) { /* we have reached the leaf */ GtkCTreeNode *new_node; new_node=gtk_ctree_insert_node(ctree,cnode,NULL,nw,5,NULL,NULL,NULL,NULL,TRUE,TRUE); } else { char *tmp; SEARCH_IN_CTREE sic; tmp=strdup(nw[0]); #if 0 strchr(tmp,'\\')[0]='\0'; /* truncate the string to keep only the current level name */ #else tmp[delimit-nw[0]]='\0'; #endif nw[0]=delimit+1; /* move the pointer to the next level */ sic.searched_string=tmp; sic.matching_cnode=NULL; sic.level=current_tree_level+1; gtk_ctree_post_recursive_to_depth(ctree,cnode,sic.level,is_a_matching_ctree_node,&sic); if(last_inserted_path->len!=0) last_inserted_path=g_string_append_c(last_inserted_path,'\\'); last_inserted_path=g_string_append(last_inserted_path,tmp); last_tree_level=current_tree_level+1; if(sic.matching_cnode==NULL) { /* there is no node having this name, we must create it */ char *ent_array[4]; ent_array[0]=tmp; ent_array[1]=NULL; ent_array[2]=NULL; ent_array[3]=NULL; sic.matching_cnode=gtk_ctree_insert_node(ctree,cnode,NULL,ent_array,5,NULL,NULL,NULL,NULL,FALSE,TRUE); /* it is a leaf */ } last_inserted_node=sic.matching_cnode; free(tmp); add_row_to_user_file_list_ctree(ctree,sic.matching_cnode,nw,current_tree_level+1); } } /* ===================================================================================== */ /* ===================================================================================== */ /* ===================================================================================== */ /* ===================================================================================== */ /**********************************************************************/ /* search in the root node a subtree for the given user and delete it */ /**********************************************************************/ static void discard_sub_ctree_of_user(GtkCTree *ctree, char *nick) { gchar *tmp; SEARCH_IN_CTREE sic; tmp=g_strconcat("~",nick,NULL); sic.searched_string=tmp; sic.matching_cnode=NULL; sic.level=1; gtk_ctree_post_recursive_to_depth(ctree,NULL,sic.level,is_a_matching_ctree_node,&sic); if(sic.matching_cnode!=NULL) { /* */ gtk_ctree_remove_node(ctree,sic.matching_cnode); } g_free(tmp); } static gint find_matching_user_file_dir(gconstpointer in_tree, gconstpointer given_param) { USER_FILE_CL_ENTRY *a=(void*)in_tree; if(a==NULL) return 1; if(a->entry_type!=UFL_DIR_ENTRY) return 1; /* not a directory */ return strcmp(a->c.dir_name,((USER_FILE_CL_ENTRY*)given_param)->c.dir_name); } /***************************************************************************************************************************/ /* search if an offspring of the last_inserted_node match the wanted dir_string (its first dir_string_len characters only) */ /***************************************************************************************************************************/ /* input: parent_node is ALWAYS an UFL_DIR_ENTRY */ /* output: FALSE= not found, TRUE= found, offspring_node and offspring_path_is filled */ /**************************************************************************************/ static int find_offspring_as_named_dir(GtkCTree *ctree, GtkCTreeNode *parent_node, USER_FILE_CL_ENTRY *parent_path, GtkCTreeNode **offspring_node, USER_FILE_CL_ENTRY **offspring_path, char *dir_string, int dir_string_len) { USER_FILE_CL_ENTRY fcl; fcl.entry_type=UFL_DIR_ENTRY; fcl.c.dir_name=strdup(dir_string); fcl.c.dir_name[dir_string_len]='\0'; *offspring_node=gtk_ctree_find_by_row_data_custom(ctree,parent_node,&fcl,find_matching_user_file_dir); free(fcl.c.dir_name); if(*offspring_node==NULL) return FALSE; *offspring_path=gtk_ctree_node_get_row_data(ctree,*offspring_node); return TRUE; } /****************************************************************************************/ /* recursively go through a tree from the last_inserted_node and try to attach the leaf */ /****************************************************************************************/ /* cur_string_pos is the number of bytes already used in new_leaf->c.file.filename */ /***********************************************************************************/ static void recursive_insert_new_user_cl_entry_leaf(GtkCTree *ctree, USER_FILE_CL_ENTRY *new_leaf, USER_FILE_CL_ENTRY **last_inserted_path, GtkCTreeNode **last_inserted_node,int cur_string_pos) { char *next_sep; GtkCTreeNode *offspring_node; USER_FILE_CL_ENTRY *offspring_path; int next_len; next_sep=strchr(new_leaf->c.file.filename+cur_string_pos,'\\'); if(next_sep==NULL) { /* we have reached the leaf position */ GtkCTreeNode *leaf_node; char *nw[2]; char bf[64]; nw[UFLC_TREE_COL]=new_leaf->c.file.filename+cur_string_pos; nw[UFLC_SIZE_COL]=bf; #ifndef NO_PRINTF_LOCALE sprintf(bf,"%lu",new_leaf->c.file.file_size); /* NO_PRINTF_LOCAL support added */ #else sprintf(bf,"%lu",new_leaf->c.file.file_size); #endif leaf_node=gtk_ctree_insert_node(ctree,*last_inserted_node,NULL,nw,5,NULL,NULL,NULL,NULL,TRUE,TRUE); /* it is a leaf */ gtk_ctree_node_set_row_data_full(ctree,leaf_node, new_leaf, (void*)free_user_file_cl_entry); return; } next_len=(next_sep-new_leaf->c.file.filename)+1; /* we always include the '\' in the dir path */ /* we have not reached the leaf position */ /* we must find an offspring to (*last_inserted_node) to resume or we must create it */ if(find_offspring_as_named_dir(ctree,*last_inserted_node, *last_inserted_path, &offspring_node, &offspring_path, new_leaf->c.file.filename, next_len)==FALSE) { /* the node does not exists */ char *nw[2]; char *t; nw[0]=strdup(new_leaf->c.file.filename+cur_string_pos); nw[0][next_sep-(new_leaf->c.file.filename+cur_string_pos)+1]='\0'; /* keep the '\' at the end */ nw[1]=""; t=strdup(new_leaf->c.file.filename); t[(next_sep-new_leaf->c.file.filename)+1]='\0'; *last_inserted_path=new_user_file_cl_entry_as_dir(t); *last_inserted_node=gtk_ctree_insert_node(ctree,*last_inserted_node,NULL,nw,5,NULL,NULL,NULL,NULL,FALSE,TRUE); gtk_ctree_node_set_row_data_full(ctree,*last_inserted_node, *last_inserted_path, (void*)free_user_file_cl_entry); free(t); free(nw[0]); } else { /* a node with this name already exists */ *last_inserted_path=offspring_path; *last_inserted_node=offspring_node; } recursive_insert_new_user_cl_entry_leaf(ctree,new_leaf,last_inserted_path,last_inserted_node,next_len); } /*********************************************************/ /* attach a leaf from a root or from the last known node */ /*********************************************************/ static void insert_new_user_file_cl_entry_leaf(GtkCTree *ctree, GtkCTreeNode *root_node, USER_FILE_CL_ENTRY *root_node_path, USER_FILE_CL_ENTRY *new_leaf, USER_FILE_CL_ENTRY **last_inserted_path, GtkCTreeNode **last_inserted_node) { if((*last_inserted_path)->entry_type==UFL_DIR_ENTRY) { /* add from a directory entry */ int l; l=strlen((*last_inserted_path)->c.dir_name); #if 0 if(!strncmp((*last_inserted_path)->c.dir_name,new_leaf->c.file.filename,l)) #else if( (!strncmp((*last_inserted_path)->c.dir_name,new_leaf->c.file.filename,l)) && (new_leaf->c.file.filename[l]=='\\')) #endif { /* we are adding from the last inserted path */ recursive_insert_new_user_cl_entry_leaf(ctree, new_leaf,last_inserted_path, last_inserted_node,l+1); return; } (*last_inserted_path)=root_node_path; (*last_inserted_node)=root_node; } recursive_insert_new_user_cl_entry_leaf(ctree, new_leaf,last_inserted_path, last_inserted_node,0); } /******************************/ /* end the FLST clist refresh */ /******************************/ void user_share_full_list_fnc(const GString *in) { char *lst; guint64 ttl_size; char *nick; char *cur_lst_ptr; char *t; GtkWidget *w; GtkWidget *apbar; gfloat last_ap_pos=0; unsigned long list_byte_size; GtkCTree *ctree; GtkCTreeNode *root_node; /* user root node */ USER_FILE_CL_ENTRY *root_node_path; /* USER_FILE_CL_ENTRY of the user root node */ char *nw[2]; USER_FILE_CL_ENTRY *last_inserted_path; /* USER_FILE_CL_ENTRY of the last inserted directory (it can be either UFL_NICK_ROOT_ENTRY or UFL_DIR_ENTRY) */ GtkCTreeNode *last_inserted_node; /* ctree not of the last inserted directory */ w=get_widget_by_widget_name("user_file_list_clist"); if(w==NULL) return; /* s format: ] "xxxxx"nick| */ t=strchr(in->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; nick=t; t=strchr(nick,'|'); if(t==NULL) return; *t='\0'; lst=load_ls_file(nick,&ttl_size); if(lst==NULL) return; cur_lst_ptr=lst; /* insert the list in the ctree */ gtk_clist_freeze(GTK_CLIST(w)); discard_sub_ctree_of_user(GTK_CTREE(w), nick); apbar=get_widget_by_widget_name("appbar1"); gnome_appbar_set_progress(GNOME_APPBAR(apbar),0); while (gtk_events_pending()) gtk_main_iteration(); list_byte_size=strlen(cur_lst_ptr); ctree=GTK_CTREE(w); /* create the user root entry */ nw[UFLC_TREE_COL]=nick; nw[UFLC_SIZE_COL]=""; root_node=gtk_ctree_insert_node(ctree,NULL,NULL,nw,5,NULL,NULL,NULL,NULL,FALSE,TRUE); /* it is not a leaf */ gtk_ctree_node_set_row_data_full(ctree,root_node, root_node_path=last_inserted_path=new_user_file_cl_entry_as_nick_root(nick), (void*)free_user_file_cl_entry); last_inserted_node=root_node; while(cur_lst_ptr[0]!='\0') { USER_FILE_CL_ENTRY *new_leaf; char *fname, *fsize; /* line format: filename|size\n */ fname=cur_lst_ptr; cur_lst_ptr=strchr(cur_lst_ptr,'|'); if(cur_lst_ptr==NULL) break; *cur_lst_ptr++='\0'; fsize=cur_lst_ptr; cur_lst_ptr=strchr(cur_lst_ptr,'\n'); if(cur_lst_ptr==NULL) break; *cur_lst_ptr++='\0'; new_leaf=new_user_file_cl_entry_as_file(fname,strtoul(fsize,NULL,10)); insert_new_user_file_cl_entry_leaf(ctree, root_node, root_node_path, new_leaf, &last_inserted_path, &last_inserted_node); if( ((((gfloat)(cur_lst_ptr-lst))/list_byte_size)-last_ap_pos) > 0.01 ) { last_ap_pos=(((gfloat)(cur_lst_ptr-lst))/list_byte_size); gnome_appbar_set_progress(GNOME_APPBAR(apbar),last_ap_pos); while (gtk_events_pending()) gtk_main_iteration(); } } #if 0 printf("a: %d m: %d t: %d\n",nb_add,nb_matching,nb_tst); #endif gnome_appbar_set_progress(GNOME_APPBAR(apbar),1.0); while (gtk_events_pending()) gtk_main_iteration(); gtk_ctree_sort_recursive (GTK_CTREE(w), NULL); gtk_clist_thaw(GTK_CLIST(w)); free(lst); /* make the tab label blink if required */ if(gtk_notebook_get_current_page(GTK_NOTEBOOK(get_widget_by_widget_name("main_notebook")))!=USER_FILE_LIST_TAB) blink_on("user_file_list_page"); } /* this function is called when the user has validated its password */ /* string is a g_malloc'd string which should be freed, or NULL if the user cancelled. */ static void password_entered(gchar *string, gpointer data) { if(string==NULL) { /* user has cancelled */ send_data_to_dctc("/FORCEQUIT\n"); } else { GString *cmd; cmd=g_string_new("/PASSWD "); g_string_sprintfa(cmd,"%s\n",string); send_data_to_dctc(cmd->str); g_string_free(cmd,TRUE); g_free(string); } } /************************************************/ /* open password dialog to enter a new password */ /************************************************/ void enter_passwd_fnc(const GString *in) { /* see gnome_request_dialog for information */ gnome_app_request_password(GNOME_APP(main_window),_("Your nickname is password protected on this hub\nPlease enter your password."), password_entered,NULL); } /*************************************/ /* decode and display a progress bar */ /*************************************/ void prog_bar_fnc(const GString *in) { char *t; gchar **splt; /* s format: ] "xxxxx"barname|progress|string|[string|...] */ t=strchr(in->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; splt=g_strsplit(t+1,"|",0); if(splt!=NULL) { if((splt[0]!=NULL)&&(splt[1]!=NULL)&&(splt[2]!=NULL)) { /* at least 3 fields */ float v; int pb_len; char *pb=NULL; GtkWidget *nw[3]; /* a progress bar is 2 widgets: the window containing the progressbar, the progressbar itself, the label containing the text */ v=atof(splt[1]); if(v!=100.0) { /* it is not a bar destruction */ if(get_tos_entry(PGBAR_TOSKEY,splt[0],strlen(splt[0]),0,&pb,&pb_len)) { /* the bar still exists */ if(pb!=NULL) { /* and seems to be valid */ nw[0]=((GtkWidget **)pb)[0]; nw[1]=((GtkWidget **)pb)[1]; nw[2]=((GtkWidget **)pb)[2]; goto set_field; } } else { /* the bar does not exist */ { nw[0]=gtk_window_new(GTK_WINDOW_DIALOG); gtk_container_border_width (GTK_CONTAINER (nw[0]), 5); { GtkWidget *vbox; vbox=gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(nw[0]),vbox); gtk_widget_show(vbox); { nw[2]=gtk_label_new(NULL); gtk_box_pack_start(GTK_BOX(vbox),nw[2],TRUE,TRUE,0); gtk_widget_show(nw[2]); } { nw[1]=gtk_progress_bar_new(); gtk_progress_bar_set_bar_style(GTK_PROGRESS_BAR(nw[1]),GTK_PROGRESS_CONTINUOUS); gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(nw[1]),GTK_PROGRESS_LEFT_TO_RIGHT); gtk_box_pack_start(GTK_BOX(vbox),nw[1],TRUE,TRUE,0); gtk_widget_show(nw[1]); } } gtk_widget_show(nw[0]); add_tos_entry(PGBAR_TOSKEY,1000000000,splt[0],strlen(splt[0]),(void*)&nw,sizeof(nw)); } set_field: { GString *grp; int i; /* concat all strings */ grp=g_string_new(splt[2]); i=3; while(splt[i]!=NULL) { grp=g_string_append_c(grp,'\n'); grp=g_string_append(grp,splt[i]); i++; } gtk_progress_set_percentage(GTK_PROGRESS(nw[1]), v/100.0); /* the value should be between 0 and 1 and we have it between 0 and 100 */ gtk_label_set_text(GTK_LABEL(nw[2]),grp->str); g_string_free(grp,TRUE); } } if(pb!=NULL) free(pb); } else { /* it is a bar destruction */ if(get_tos_entry(PGBAR_TOSKEY,splt[0],strlen(splt[0]),0,&pb,&pb_len)) { if(pb!=NULL) { gtk_widget_destroy(((GtkWidget **)pb)[0]); } if(pb!=NULL) free(pb); delete_this_tos_entry(PGBAR_TOSKEY,splt[0],strlen(splt[0]),0); } } } g_strfreev(splt); } } /* ===================================================================================== */ /* ===================================================================================== */ /* ===================================================================================== */ /* ===================================================================================== */ static GPtrArray *ualst_temp_array=NULL; /* it is an array of gchar ** (each has been obtain using g_strsplit on one line of UALSC) */ /**************************************************/ /* start the beginning of the UADDR clist refresh */ /**************************************************/ void ualst_begin_fnc(const GString *in) { free_temp_array(&ualst_temp_array); ualst_temp_array=g_ptr_array_new(); } /***********************************/ /* temporary store one UADDR entry */ /***********************************/ void ualst_content_fnc(const GString *in) { char *t; gchar **fields; /* s format: ] "xxxxx"nick|hostip:port */ t=strchr(in->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; fields=g_strsplit(t,"|",0); g_ptr_array_add(ualst_temp_array,fields); } /*******************************/ /* end the UADDR clist refresh */ /*******************************/ void ualst_end_fnc(const GString *in) { GtkWidget *w; GtkCList *clst; int i; if(ualst_temp_array==NULL) return; w=get_widget_by_widget_name("uaddr_clist"); if(w==NULL) return; clst=GTK_CLIST(w); gtk_clist_freeze(clst); /* now, we will scans the clist to remove all sources entries which no more exists and add newly added sources */ /* at the same time, we remove UADDR entries which no more exist */ for(i=clst->rows-1;i>=0;i--) { char *nck,*ipport; gtk_clist_get_text(clst,i,0,&nck); gtk_clist_get_text(clst,i,1,&ipport); if((nck!=NULL)&&(ipport!=NULL)) { int j; gchar **k; int fnd=0; /* first, we try to find a the clist entry matching exactly the UADDR entry */ for(j=0;jlen;j++) { k=g_ptr_array_index(ualst_temp_array,j); if(k!=NULL) { if((!strcmp(nck,k[0]))&&(!strcmp(ipport,k[1]))) { g_strfreev(k); g_ptr_array_index(ualst_temp_array,j)=NULL; fnd=1; break; } } } if((!fnd)&&(strlen(nck)==0)) { /* then, we try to find a the clist entry matching the same ipport as the UADDR entry and having an empty nck */ for(j=0;jlen;j++) { k=g_ptr_array_index(ualst_temp_array,j); if(k!=NULL) { if(!strcmp(ipport,k[1])) { /* update the nickname of this entry */ gtk_clist_set_text(clst,i,0,k[0]); g_strfreev(k); g_ptr_array_index(ualst_temp_array,j)=NULL; fnd=1; break; } } } } if(!fnd) { /* still not found -> remove */ gtk_clist_remove(clst,i); } } } /* the only thing to do know is to add newly create UADDR with their sources */ for(i=0;ilen;i++) { gchar **k; k=g_ptr_array_index(ualst_temp_array,i); if(k) { /* at least 2 fields, like the clist */ gtk_clist_append(clst,k); g_strfreev(k); g_ptr_array_index(ualst_temp_array,i)=NULL; } } gtk_clist_sort (clst); gtk_clist_thaw(clst); /* and free unnecessary data of the ualst_temp_array */ /* this loop should be unuseful because the temp_array should already by empty */ for(i=0;ilen;i++) { gchar **k; k=g_ptr_array_index(ualst_temp_array,i); if(k) g_strfreev(k); } g_ptr_array_free(ualst_temp_array,TRUE); ualst_temp_array=NULL; return; } /**********************************/ /* Add an entry to the UADDR list */ /**********************************/ void ualst_entry_add(const GString *in) { char *t; gchar **fields; GtkWidget *w; GtkCList *clst; w=get_widget_by_widget_name("uaddr_clist"); if(w==NULL) return; clst=GTK_CLIST(w); /* s format: ] "xxxxx"nick|hostip:port */ t=strchr(in->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; fields=g_strsplit(t,"|",0); /* too easy to add a new entry */ gtk_clist_freeze(clst); gtk_clist_append(clst,fields); gtk_clist_sort (clst); gtk_clist_thaw(clst); g_strfreev(fields); } /*************************************/ /* remove an entry to the UADDR list */ /*************************************/ void ualst_entry_remove(const GString *in) { char *t; gchar **fields; GtkWidget *w; GtkCList *clst; int i; w=get_widget_by_widget_name("uaddr_clist"); if(w==NULL) return; clst=GTK_CLIST(w); /* s format: ] "xxxxx"nick|hostip:port */ t=strchr(in->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; fields=g_strsplit(t,"|",0); gtk_clist_freeze(clst); for(i=0;irows;i++) { char *nck,*ipport; gtk_clist_get_text(clst,i,0,&nck); gtk_clist_get_text(clst,i,1,&ipport); if((nck!=NULL)&&(ipport!=NULL)) { if( (!strcmp(nck,fields[0])) && (!strcmp(ipport,fields[1])) ) { gtk_clist_remove(clst,i); break; } } } /* it is not necessary to resort the list, removing something don't break the sort */ gtk_clist_thaw(clst); g_strfreev(fields); } /* ===================================================================================== */ /* ===================================================================================== */ /* ===================================================================================== */ /* ===================================================================================== */ static GPtrArray *glst_temp_array=NULL; /* it is an array of gchar ** (each has been obtain using g_strsplit on one line of GLSTC) */ /************************************************/ /* start the beginning of the GDL ctree refresh */ /************************************************/ void glst_begin_fnc(const GString *in) { free_temp_array(&glst_temp_array); glst_temp_array=g_ptr_array_new(); } #if 0 static const char *ftypestr2num(char *m1) { int i; static struct { const char *pattern; int pattern_length; const char *str; } str[]={ {"[any]",sizeof("[any]")-1,"1"}, {"[audio]",sizeof("[audio]")-1,"2"}, {"[compressed]",sizeof("[compressed]")-1,"3"}, {"[document]",sizeof("[document]")-1,"4"}, {"[exe]",sizeof("[exe]")-1,"5"}, {"[picture]",sizeof("[picture]")-1,"6"}, {"[video]",sizeof("[video]")-1,"7"}, {"[folder]",sizeof("[folder]")-1,"8"}, {NULL,0,NULL}}; i=0; while(str[i].pattern!=NULL) { if(!strncmp(m1,str[i].pattern,str[i].pattern_length)) return str[i].str; i++; } return ""; } #endif #define FIXED_GLSTC_HEADER (3+4+2+1) /* number of fixed strings in the GLSTC header (the GDL ID, the local filename, the local filesize, */ /* (FIXED ?) the byte offset, the received byte, the start time and the speed, the rename dir, the rename file, */ /* the script to start at end */ /*******************************************************************************************************************/ /* for each source/range entry of this GDL, we check if it appear in the given glst_temp_array (data) */ /* on success, we update it and mark the string of data as used (1st byte:'\001'). On error the entry is destroyed */ /*******************************************************************************************************************/ void second_level_glst_end_fnc(GtkCTree *ctree, GtkCTreeNode *cnode, gpointer data) { gchar **strv=((gchar**)data)+FIXED_GLSTC_HEADER; /* skip the header */ int i; GDL_CT_ENTRY *gce; if(GTK_CTREE_ROW(cnode)->level!=2) return; gce=gtk_ctree_node_get_row_data(ctree,cnode); if(gce==NULL) return; switch(gce->ct_type) { case GDL_SEARCH_PATTERN: { GString *temp_str; /* only the autoscan search pattern has an icon */ /* this ctree entry is a GDL autoscan */ temp_str=g_string_new(""); g_string_sprintf(temp_str,"%lu$%u?%s", gce->c.search_pattern.autoscan_id, gce->c.search_pattern.autoscan_type, gce->c.search_pattern.search_pattern); i=0; while(strv[i]!=NULL) { if(strlen(strv[i])==0) /* we have found the empty string between sources and range in the GDLSTC message */ { i++; /* now, i is the index of the first range string */ while(strv[i]!=NULL) { if(strlen(strv[i])==0) /* we have found the empty string between range and autoscan */ { i++; while(strv[i]!=NULL) { if(strlen(strv[i])==0) /* we have found the empty string at the end of the autoscan */ break; if(strv[i][0]!='\001') /* string unused ? */ { /* now, we have to check if we found the wanted string */ if(!strcmp(strv[i],temp_str->str)) { strv[i][0]='\001'; /* mark the string as used */ g_string_free(temp_str,TRUE); /* we have found it, it is over */ return; } } i++; } break; } i++; } break; } i++; } g_string_free(temp_str,TRUE); } break; case GDL_STORED_SEGMENT: { /* build the temporary comparaison string */ gchar *temp_str; /* create a string "filename$range" */ temp_str=g_strconcat(gce->c.stored_segment.stored_filename,"$",gce->c.stored_segment.stored_interval,NULL); i=0; while(strv[i]!=NULL) { if(strlen(strv[i])==0) /* we have found the empty string between sources and range in the GDLSTC message */ { i++; /* now, i is the index of the first range string */ while(strv[i]!=NULL) { if(strlen(strv[i])==0) /* we have found the empty string between range and autoscan */ break; if(strv[i][0]!='\001') /* string unused ? */ { /* now, we have to check if we found the wanted string */ if(!strcmp(strv[i],temp_str)) { strv[i][0]='\001'; /* mark the string as used */ g_free(temp_str); /* we have found it, it is over */ return; } } i++; } break; } i++; } g_free(temp_str); /* we have found it, it is over */ } break; case GDL_RENAME_AT_END: if(strlen(strv[-2])) /* renaming information */ { int changed=0; /* update filename when needed */ if(strcmp(gce->c.rename_at_end.final_filename,strv[-2])) { free(gce->c.rename_at_end.final_filename); gce->c.rename_at_end.final_filename=strdup(strv[-2]); changed=1; } /* update directory when needed */ if(strlen(strv[-3])) { if(strcmp(gce->c.rename_at_end.final_directory,strv[-3])) { free(gce->c.rename_at_end.final_directory); gce->c.rename_at_end.final_directory=strdup(strv[-3]); changed=1; } } else { if(gce->c.rename_at_end.final_directory) { free(gce->c.rename_at_end.final_directory); gce->c.rename_at_end.final_directory=strdup(""); changed=1; } } if(changed) { gchar *temp_str; if(strlen(gce->c.rename_at_end.final_directory)) { temp_str=g_strconcat(gce->c.rename_at_end.final_directory,"/",gce->c.rename_at_end.final_filename,NULL); } else { temp_str=g_strconcat(gce->c.rename_at_end.final_filename,NULL); } /* renaming information differs */ gtk_ctree_node_set_text(ctree,cnode,1,temp_str); g_free(temp_str); } strv[-3][0]='\0'; strv[-2][0]='\0'; return; } break; case GDL_SCRIPT_AT_END: { int changed=0; if(strlen(strv[-1])) { if(strcmp(gce->c.script_at_end.script_to_start,strv[-1])) { free(gce->c.script_at_end.script_to_start); gce->c.script_at_end.script_to_start=strdup(strv[-1]); changed=1; } } else { if(gce->c.script_at_end.script_to_start) { free(gce->c.script_at_end.script_to_start); gce->c.script_at_end.script_to_start=strdup(""); changed=1; } } if(changed) { /* script information differs */ gtk_ctree_node_set_text(ctree,cnode,1,gce->c.script_at_end.script_to_start); } strv[-1][0]='\0'; return; } break; case GDL_ACTIVE_SEGMENT: { int temp_str_len; char *status_temp; gchar *temp_str; /* create a string "nickname$filename$" */ temp_str=g_strconcat(gce->c.active_segment.nickname,"$",gce->c.active_segment.remote_filename,"$",NULL); temp_str_len=strlen(temp_str); i=0; while(strv[i]!=NULL) { if(strlen(strv[i])==0) /* we have found the empty string between sources and range in the GDLSTC message */ break; if(strv[i][0]!='\001') /* string unused ? */ { /* now, we have to check if we found the wanted string */ if(!strncmp(strv[i],temp_str,temp_str_len)) { /* we have found the string, check if we must update the row */ status_temp=strchr(strv[i]+temp_str_len,'$'); if(status_temp!=NULL) { unsigned long cur_size; *status_temp++='\0'; /* strv[i]+temp_str_len is the remote file size */ /* status_temp is the xfer status */ if((cur_size=strtoul(strv[i]+temp_str_len,NULL,10))!=gce->c.active_segment.remote_file_size) { char buf_size[64]; #ifndef NO_PRINTF_LOCALE sprintf(buf_size,"%lu",cur_size); /* NO_PRINTF_LOCAL support added */ #else sprintf(buf_size,"%lu",cur_size); #endif gtk_ctree_node_set_text(ctree,cnode,2,buf_size); gce->c.active_segment.remote_file_size=cur_size; } if(strcmp(gce->c.active_segment.status,status_temp)) { gtk_ctree_node_set_text(ctree,cnode,3, ((status_temp[0]=='W')?_("Waiting"): ((status_temp[0]=='T')?_("Trying"):status_temp))); free(gce->c.active_segment.status); gce->c.active_segment.status=strdup(status_temp); } strv[i][0]='\001'; /* mark the string as used */ g_free(temp_str); /* we have found it, it is over */ return; } } } i++; } g_free(temp_str); /* we have found it, it is over */ } break; default: printf("Unsupported entry type: %d\n",gce->ct_type); break; } /* the entry does not exist anymore */ gtk_ctree_remove_node(ctree,cnode); } static const char *ftype2str(int file_type) { #define NB_TYPE_ENT 8 static const char *ftype_str[]={ "any", "audio", "compressed", "document", "exe", "picture", "video", "folder", NULL}; file_type--; if((file_type<0)||(file_type>=NB_TYPE_ENT)) return ""; if(ftype_str[file_type]==NULL) return ""; return ftype_str[file_type]; } /*******************************************************************************************/ /* for each unused string of the given glst_temp_array (data), we create all ctree entries */ /*******************************************************************************************/ static void second_level_add_newly_created_entries(GtkCTree *ctree, GtkCTreeNode *cnode, gpointer data) { gchar **strv=((gchar**)data)+FIXED_GLSTC_HEADER; /* skip the header */ int i; char *ent_array[4]; /* 4 columns in the list */ GDL_CT_ENTRY *gce; if(strlen(strv[-2])) { /* there is renaming information */ GtkCTreeNode *new_node; gchar *temp_str; if(strlen(strv[-3])) temp_str=g_strconcat(strv[-3],"/",strv[-2],NULL); else temp_str=g_strconcat(strv[-2],NULL); ent_array[0]=""; ent_array[1]=temp_str; ent_array[2]=""; ent_array[3]=_("At end, rename"); new_node=gtk_ctree_insert_node(ctree,cnode,NULL, ent_array, 5,NULL,NULL,NULL,NULL,TRUE,TRUE); gce=new_gdl_ct_entry_as_rename_at_end(strv[-3],strv[-2]); gtk_ctree_node_set_row_data_full(ctree,new_node,gce,(void*)free_gdl_ct_entry); g_free(temp_str); } if(strlen(strv[-1])) { /* there is script at end information */ GtkCTreeNode *new_node; ent_array[0]=""; ent_array[1]=strv[-1]; ent_array[2]=""; ent_array[3]=_("At end, start script"); new_node=gtk_ctree_insert_node(ctree,cnode,NULL, ent_array, 5,NULL,NULL,NULL,NULL,TRUE,TRUE); gce=new_gdl_ct_entry_as_script_at_end(strv[-1]); gtk_ctree_node_set_row_data_full(ctree,new_node,gce,(void*)free_gdl_ct_entry); } i=0; /* scan source parts of the string */ while((strv[i]!=NULL)&&(strlen(strv[i]))) { if(strv[i][0]!='\001') /* string unused ? */ { gchar **f4; GtkCTreeNode *new_node; f4=g_strsplit(strv[i],"$",3); if((f4[0]!=NULL)&&(f4[1]!=NULL)&&(f4[2]!=NULL)&&(f4[3]!=NULL)) { char buf_size[64]; unsigned long cur_size; cur_size=strtoul(f4[2],NULL,10); #ifndef NO_PRINTF_LOCALE sprintf(buf_size,"%lu",cur_size); /* NO_PRINTF_LOCAL support added */ #else sprintf(buf_size,"%lu",cur_size); #endif ent_array[0]=f4[0]; ent_array[1]=f4[1]; ent_array[2]=buf_size; if(f4[3][0]=='W') ent_array[3]=_("Waiting"); else if(f4[3][0]=='T') ent_array[3]=_("Trying"); else ent_array[3]=f4[3]; new_node=gtk_ctree_insert_node(ctree,cnode,NULL, ent_array, 5,NULL,NULL,NULL,NULL,TRUE,TRUE); gce=new_gdl_ct_entry_as_active_segment(f4[0],f4[1],cur_size,f4[3]); gtk_ctree_node_set_row_data_full(ctree,new_node,gce,(void*)free_gdl_ct_entry); if(user_here(ent_array[0])!=-1) gtk_ctree_node_set_background (ctree,new_node,&green); /* put operator xfer in red */ if(str_array_is_inside(op_array,ent_array[0])) { gtk_ctree_node_set_foreground (ctree,new_node,&light_red); } } g_strfreev(f4); } i++; } if(strv[i]!=NULL) { /* we have found the empty string between sources and range in the GDLSTC message */ i++; /* now, i is the index of the first range string */ while((strv[i]!=NULL)&&(strlen(strv[i]))) { if(strv[i][0]!='\001') /* string unused ? */ { gchar **f2; f2=g_strsplit(strv[i],"$",1); if((f2[0]!=NULL)&&(f2[1]!=NULL)) { GtkCTreeNode *new_node; char out_range[512]; unsigned long lower, upper; sscanf(f2[1],"[%lu;%lu]",&lower,&upper); #ifndef NO_PRINTF_LOCALE sprintf(out_range,"[%lu : %lu]",lower,upper); /* NO_PRINTF_LOCAL support added */ #else sprintf(out_range,"[%lu : %lu]",lower,upper); #endif ent_array[0]=""; ent_array[1]=f2[0]; ent_array[2]=out_range; ent_array[3]=""; new_node=gtk_ctree_insert_node(ctree,cnode,NULL, ent_array, 5,NULL,NULL,NULL,NULL,TRUE,TRUE); gce=new_gdl_ct_entry_as_stored_segment(f2[0],f2[1]); gtk_ctree_node_set_row_data_full(ctree,new_node,gce,(void*)free_gdl_ct_entry); } g_strfreev(f2); } i++; } if(strv[i]!=NULL) { /* we have found the empty string between range and autoscan */ i++; /* now, i is the index of the first autoscan string */ while((strv[i]!=NULL)&&(strlen(strv[i]))) { if(strv[i][0]!='\001') /* string unused ? */ { gchar **f2; f2=g_strsplit(strv[i],"$",1); if((f2[0]!=NULL)&&(f2[1]!=NULL)) { static GdkPixmap *as_pixmap=NULL; static GdkBitmap *as_mask=NULL; GtkCTreeNode *new_node; GString *long_desc; int ftype; char *t; long_desc=g_string_new(f2[1]); ftype=atoi(long_desc->str); t=strchr(long_desc->str,'?'); if(t!=NULL) { long_desc=g_string_erase(long_desc,0,1+t-long_desc->str); } /* all the values are available only here */ gce=new_gdl_ct_entry_as_search_pattern(strtoul(f2[0],NULL,10),ftype,long_desc->str); long_desc=g_string_prepend(long_desc,"] "); long_desc=g_string_prepend(long_desc,ftype2str(ftype)); long_desc=g_string_prepend_c(long_desc,'['); ent_array[0]=f2[0]; ent_array[1]=long_desc->str; ent_array[2]=""; ent_array[3]=""; if(as_pixmap==NULL) { as_pixmap=gdk_pixmap_create_from_xpm_d(main_window->window,&as_mask,NULL,search_xpm); } new_node=gtk_ctree_insert_node(ctree,cnode,NULL, ent_array, 5,NULL,NULL,NULL,NULL,TRUE,TRUE); gtk_ctree_node_set_pixtext(ctree,new_node,0,f2[0],0,as_pixmap,as_mask); gtk_ctree_node_set_row_data_full(ctree,new_node,gce,(void*)free_gdl_ct_entry); g_string_free(long_desc,TRUE); } g_strfreev(f2); } i++; } } } } /**********************************************************************************/ /* for each GDL of the ctree, we do this: */ /* 1) check if it still exists. If not, delete it */ /* 2) if it exists, we scan its sources and ranges to remove no more existing one */ /* 3) if it exists, we add newly inserted ranges and sources */ /**********************************************************************************/ static void first_level_glst_end_fnc(GtkCTree *ctree, GtkCTreeNode *cnode, gpointer data) { gchar gdl_id_txt[20]; int i; GDL_CT_ENTRY *gce_root; gce_root=gtk_ctree_node_get_row_data(ctree,cnode); if((gce_root==NULL)||(gce_root->ct_type!=GDL_ROOT)) return; sprintf(gdl_id_txt,"%lu",gce_root->c.root.gdl_id); /* now, search for this id in the glst_temp_array */ for(i=0;ilen;i++) { gchar **ptr; ptr=g_ptr_array_index(glst_temp_array,i); if(ptr!=NULL) { if(!strcmp(gdl_id_txt,ptr[0])) /* compare this temp entry to the gdl_id we search. On success, we start level2 scan */ { GString *spd_str; unsigned long missing_bytes; time_t duration; double spd; unsigned long cur_size; gce_root->c.root.gdl_size=strtoul(ptr[2],NULL,10); /* ttl_size */ gce_root->c.root.byte_offset=strtoul(ptr[3],NULL,10); /* yet_here */ gce_root->c.root.received_bytes=strtoul(ptr[4],NULL,10); gce_root->c.root.start_time=strtoul(ptr[5],NULL,10); gce_root->c.root.last_10sec_speed=strtoul(ptr[6],NULL,10); /* last10sec_here */ missing_bytes=gce_root->c.root.gdl_size-gce_root->c.root.received_bytes; spd_str=g_string_new(""); #ifndef NO_PRINTF_LOCALE g_string_sprintf(spd_str,"%15lu (%.2f%%) ",gce_root->c.root.received_bytes,100.0*(double)gce_root->c.root.received_bytes/(double)gce_root->c.root.gdl_size); /* NO_PRINTF_LOCAL support added */ #else g_string_sprintf(spd_str,"%15lu (%.2f%%) ",gce_root->c.root.received_bytes,100.0*(double)gce_root->c.root.received_bytes/(double)gce_root->c.root.gdl_size); #endif cur_size=gce_root->c.root.received_bytes-gce_root->c.root.byte_offset; /* number of bytes downloaded */ duration=time(NULL)-gce_root->c.root.start_time; spd=(double)(gce_root->c.root.last_10sec_speed)/10.0; /* compute the speed of the last 10 seconds */ if(spd<1024.0) { g_string_sprintfa(spd_str,"[%.2fB/s]",spd); } else if(spd<(1024.0*1024.0)) { g_string_sprintfa(spd_str,"[%.2fKB/s]",spd/1024.0); } /* Estimated Time to Arrival computation: now (in second) + missing_bytes/spd */ if(spd>=10.0) /* speed above 10bytes/s */ { unsigned long tt=(unsigned long)(((double)missing_bytes/spd)); if(tt<60) { g_string_sprintfa(spd_str," %ld\"",tt); } else if(tt<3600) { g_string_sprintfa(spd_str," %ld'%02ld\"",tt/60,tt%60); } else { g_string_sprintfa(spd_str," %ld:%02ld'%02ld\"",tt/3600,(tt%3600)/60,(tt%3600)%60); } spd_str=g_string_append(spd_str,_(" left")); } gtk_ctree_node_set_text(ctree,cnode,3,spd_str->str); g_string_free(spd_str,TRUE); gtk_ctree_post_recursive_to_depth(ctree,cnode,2,second_level_glst_end_fnc,ptr); second_level_add_newly_created_entries(ctree,cnode,ptr); g_strfreev(ptr); /* and free memory */ g_ptr_array_index(glst_temp_array,i)=NULL; return; } } } /* the ctree entry no more exists, delete it */ gtk_ctree_remove_node(ctree,cnode); } /*****************************/ /* end the GDL ctree refresh */ /*****************************/ void glst_end_fnc(const GString *in) { GtkWidget *w; int i; int gdl_displaying; if(glst_temp_array==NULL) return; w=get_widget_by_widget_name("gdl_ctree"); if(w==NULL) return; gtk_clist_freeze(GTK_CLIST(w)); /* now, we will scans the ctree to remove all sources entries which no more exists and add newly added sources */ /* at the same time, we remove GDL entries which no more exist */ gtk_ctree_post_recursive_to_depth(GTK_CTREE(w),NULL,1,first_level_glst_end_fnc,NULL); /* the only thing to do know is to add newly create GDL with their sources */ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(get_widget_by_widget_name("expand_gdl_radiobutton")))==TRUE) gdl_displaying=TRUE; else gdl_displaying=FALSE; for(i=0;ilen;i++) { gchar **k; k=g_ptr_array_index(glst_temp_array,i); if(k) { /* at least 5 fields */ GtkCTreeNode *new_gdl; GDL_CT_ENTRY *gce; char *ent_array[4]; /* 4 columns in the list */ char buf_size[64]; unsigned long size_gdl=strtoul(k[2],NULL,10); /* remove an entry with the same gdl_id */ #ifndef NO_PRINTF_LOCALE sprintf(buf_size,"%lu",size_gdl); /* NO_PRINTF_LOCAL support added */ #else sprintf(buf_size,"%lu",size_gdl); #endif /* add a new entry in the root list */ gce=new_gdl_ct_entry_as_root( strtoul(k[0],NULL,10), k[1], size_gdl, 0,0,0,0); ent_array[0]=k[0]; ent_array[1]=k[1]; ent_array[2]=buf_size; ent_array[3]=""; new_gdl=gtk_ctree_insert_node(GTK_CTREE(w),NULL,NULL, ent_array,5,NULL,NULL,NULL,NULL,FALSE,gdl_displaying); gtk_ctree_node_set_row_data_full(GTK_CTREE(w),new_gdl,gce,(void*)free_gdl_ct_entry); gtk_ctree_node_set_background (GTK_CTREE(w),new_gdl,&light_orange); /* and put its info inside it */ second_level_add_newly_created_entries(GTK_CTREE(w),new_gdl,k); g_strfreev(k); g_ptr_array_index(glst_temp_array,i)=NULL; } } gtk_ctree_sort_recursive (GTK_CTREE(w), NULL); gtk_clist_thaw(GTK_CLIST(w)); /* and free unnecessary data of the glst_temp_array */ /* this loop should be unuseful because the temp_array should already by empty */ for(i=0;ilen;i++) { gchar **k; k=g_ptr_array_index(glst_temp_array,i); if(k) g_strfreev(k); } g_ptr_array_free(glst_temp_array,TRUE); glst_temp_array=NULL; return; } /***********************************************************************************/ /* search inside the root of the given ctree and delete a node having the given id */ /***********************************************************************************/ void found_and_delete_gdl_ctree_entry(GtkCTree *ctree, GtkCTreeNode *cnode, gpointer data) { gchar *txt; /* the first column of a ctree is always a pixtext */ if(gtk_ctree_node_get_pixtext(ctree,cnode,0,&txt,NULL,NULL,NULL)) { if((txt!=NULL)&&(!strcmp(txt,data))) { gtk_ctree_remove_node(ctree,cnode); } } } /*********************************/ /* temporary store one GDL entry */ /*********************************/ void glst_content_fnc(const GString *in) { char *t; gchar **fields; /* s format: ] "xxxxx"gdlID|localfname|fsize|offset|downloaded|start_time|speed|runningxfer|donexfer|autoscan */ t=strchr(in->str,'"'); if(t==NULL) return; t=strchr(t+1,'"'); if(t==NULL) return; t++; fields=g_strsplit(t,"|",0); g_ptr_array_add(glst_temp_array,fields); } static struct { const char *msg_type; void (*fnc)(const GString *); } msg_fnc[]={ {"ERR ]",err_fnc}, /* done, not checked */ {"DEBUG]",dummy_fnc}, {"INFO ]",dummy_fnc}, {"USER ]",user__fnc}, /* done, checked */ {"OP ]",op_fnc}, {"ADMIN]",op_fnc}, {"USER+]",user__fnc}, /* done, checked */ {"USER-]",user_minus_fnc}, /* done, checked */ {"CHAT ]",chat_fnc}, /* done, checked */ {"UINFO]",uinfo_fnc}, /* done, checked (partial) */ {"HUBNM]",hubnm_fnc}, /* done, checked */ {"SREST]",srest_fnc}, /* done, checked */ {"$USER]",dummy_fnc}, {"$UL+ ]",update_lists}, /* done, not checked */ {"$UL- ]",update_lists}, /* same function on error and success */ {"$UL# ]",update_lists}, /* done, not checked */ {"$DL+ ]",update_lists}, /* done, not checked */ {"$DL- ]",remove_dl_xfer_on_success_fnc}, /* done, not checked */ {"$DL# ]",update_lists}, /* done, not checked */ {"$LS+ ]",update_lists}, /* in progress */ {"$LS- ]",update_lists}, {"$LS# ]",update_lists}, {"$UL= ]",update_lists}, {"$DL= ]",update_lists}, {"$LS= ]",update_lists}, {"ASTRT]",update_lists}, {"ASTOP]",update_lists}, {"$DL~ ]",update_lists}, {"$LS~ ]",update_lists}, {"RFRSH]",update_lists}, {"XFERR]",add_xferr_fnc}, {"XFERQ]",add_xferq_fnc}, {"CMDKB]",add_cmdkb_fnc}, {"BXFER]",begin_xfer_list_fnc}, {"EXFER]",end_xfer_list_fnc}, {"$ULST]",update_ul_list}, {"HUB- ]",dummy_fnc}, {"PRIV ]",pchat_fnc}, {"HUBGO]",dummy_fnc}, {"HUB+ ]",dummy_fnc}, {"VAR ]",var_fnc}, {"PASWD]",enter_passwd_fnc}, {"PRGBR]",prog_bar_fnc}, {"GLSTB]",glst_begin_fnc}, {"GLSTC]",glst_content_fnc}, {"GLSTE]",glst_end_fnc}, {"UALSB]",ualst_begin_fnc}, {"UALSC]",ualst_content_fnc}, {"UALSE]",ualst_end_fnc}, {"UALS+]",ualst_entry_add}, {"UALS-]",ualst_entry_remove}, {"LUSER]",luser_fnc}, {"LSCCH]",user_share_full_list_fnc}, {NULL,NULL} }; /**********************************************************************************/ /* this function is called when something comes from DCTC client */ /* data is always NULL, source == current_dctc_fd and condition == GTK_INPUT_READ */ /**********************************************************************************/ void process_data_from_dctc(gpointer data, gint source, GdkInputCondition condition) { GString *input; int i; input=get_dctc_line(1); while(input!=NULL) { #if 0 printf("%s\n",input->str); #endif i=0; while(msg_fnc[i].msg_type!=NULL) { if(!strncmp(input->str,msg_fnc[i].msg_type,6)) { (msg_fnc[i].fnc)(input); break; } i++; } g_string_free(input,TRUE); input=get_dctc_line(0); } return; } /************************************************************************************/ /* same function as previous one except it tries to send queued data to DCTC client */ /************************************************************************************/ /* data is always NULL, source == current_dctc_fd and condition == GTK_INPUT_WRITE */ /***********************************************************************************/ void process_data_to_dctc(gpointer data, gint source, GdkInputCondition condition) { if(current_dctc!=NULL) { /* the previous test should never fail */ /* as long as there is something queued and it is possible to send data */ /* on the socket, we send */ while(current_dctc->write_q->len!=0) { char *str; int l; int ret; str=g_ptr_array_index(current_dctc->write_q,0); l=strlen(str); ret=send(current_dctc->dctc_fd,str,l,MSG_DONTWAIT); if(ret==l) { /* successfully sent => go to next one */ g_ptr_array_remove_index(current_dctc->write_q,0); free(str); } else { /* oh oh, an error occurs */ if(errno!=EAGAIN) { /* and it is a fatal one */ close_current_dctc(); /* we can no longer do anything because the structure has been destroyed */ gnome_app_error(GNOME_APP(main_window),_("Error while sending data to DCTC.\nConnection with DCTC terminated.")); return; } break; } } if(current_dctc->write_q->len==0) { gdk_input_remove(current_dctc->tag_write); current_dctc->tag_write=-1; } } else { fprintf(stderr,"process_data_to_dctc: invalid handler.\n"); } } /****************************************/ /* send data to the current DCTC client */ /* the function handles all errors */ /****************************************/ void send_data_to_dctc(char *str) { char *tm; if(current_dctc==NULL) return; /* if the wait_q is empty, we try to send the string without queueing */ /* else the string is queued and gdk_input handler is enabled */ if(current_dctc->write_q->len==0) { int l; int ret; l=strlen(str); #if 0 ret=send(current_dctc->dctc_fd,str,l,0); #else ret=send(current_dctc->dctc_fd,str,l,MSG_DONTWAIT); #endif if(ret==l) return; /* everything ok, we end here */ /* oh oh, an error occurs */ if(errno!=EAGAIN) { close_current_dctc(); gnome_app_error(GNOME_APP(main_window),_("Error while sending data to DCTC.\nConnection with DCTC terminated.")); } } /* if a queue still exists or the atomic send fails, the string is queued */ tm=strdup(str); if(tm==NULL) { close_current_dctc(); gnome_app_error(GNOME_APP(main_window),_("Out of memory.\nConnection with DCTC terminated.")); return; } g_ptr_array_add(current_dctc->write_q,tm); if(current_dctc->tag_write==-1) { current_dctc->tag_write=gdk_input_add(current_dctc->dctc_fd,GDK_INPUT_WRITE,process_data_to_dctc,NULL); } } /*************************************/ /* kill the given entry of the ctree */ /*********************************************/ /* entry is a GtkCTreeNode, ct is a GtkCTree */ /*********************************************/ void kill_this_gdl_entry(gpointer entry, gpointer ct) { GtkCTree *ctree; GDL_CT_ENTRY *gce; if((ct==NULL)||(entry==NULL)) { printf("kill_this_gdl_entry: NULL\n"); return; } ctree=GTK_CTREE(ct); gce=gtk_ctree_node_get_row_data(ctree,GTK_CTREE_NODE(entry)); if(gce==NULL) return; switch(gce->ct_type) { case GDL_ROOT: /* GDL ID level */ { GString *str; str=g_string_new("/GDLEND "); g_string_sprintfa(str,"%lu\n",gce->c.root.gdl_id); send_data_to_dctc(str->str); g_string_free(str,TRUE); } break; case GDL_SEARCH_PATTERN: { GDL_CT_ENTRY *gce_parent; gce_parent=gtk_ctree_node_get_row_data(ctree, GTK_CTREE_ROW(entry)->parent); if((gce_parent!=NULL)&&(gce_parent->ct_type==GDL_ROOT)) { GString *str; str=g_string_new(""); g_string_sprintf(str,"/GDLAS- %lu|%lu\n",gce_parent->c.root.gdl_id,gce->c.search_pattern.autoscan_id); send_data_to_dctc(str->str); g_string_free(str,TRUE); } } break; case GDL_ACTIVE_SEGMENT: { GDL_CT_ENTRY *gce_parent; gce_parent=gtk_ctree_node_get_row_data(ctree, GTK_CTREE_ROW(entry)->parent); if((gce_parent!=NULL)&&(gce_parent->ct_type==GDL_ROOT)) { GString *str; str=g_string_new(""); g_string_sprintf(str,"/GDLDEL %lu|%s|%s\n",gce_parent->c.root.gdl_id, gce->c.active_segment.nickname, gce->c.active_segment.remote_filename); send_data_to_dctc(str->str); g_string_free(str,TRUE); } } break; case GDL_STORED_SEGMENT: /* nothing can be done here*/ break; case GDL_RENAME_AT_END: { GDL_CT_ENTRY *gce_parent; gce_parent=gtk_ctree_node_get_row_data(ctree, GTK_CTREE_ROW(entry)->parent); if((gce_parent!=NULL)&&(gce_parent->ct_type==GDL_ROOT)) { GString *str; str=g_string_new(""); g_string_sprintf(str,"/GDLNORENAME %lu\n",gce_parent->c.root.gdl_id); send_data_to_dctc(str->str); g_string_free(str,TRUE); } } break; case GDL_SCRIPT_AT_END: { GDL_CT_ENTRY *gce_parent; gce_parent=gtk_ctree_node_get_row_data(ctree, GTK_CTREE_ROW(entry)->parent); if((gce_parent!=NULL)&&(gce_parent->ct_type==GDL_ROOT)) { GString *str; str=g_string_new(""); g_string_sprintf(str,"/GDLNOSCRIPT %lu\n",gce_parent->c.root.gdl_id); send_data_to_dctc(str->str); g_string_free(str,TRUE); } } break; default: break; } } /*****************************/ /* kill selected GDL entries */ /*****************************/ void kill_selected_gdl_entry(void) { GtkWidget *w; GtkCTree *ctree; w=get_widget_by_widget_name("gdl_ctree"); if(w==NULL) return; ctree=GTK_CTREE(w); g_list_foreach(GTK_CLIST(ctree)->selection,kill_this_gdl_entry,ctree); update_lists_force_gdl(NULL); } /***************************************/ /* detach the given entry of the ctree */ /*********************************************/ /* entry is a GtkCTreeNode, ct is a GtkCTree */ /*********************************************/ void detach_this_gdl_entry(gpointer entry, gpointer ct) { GDL_CT_ENTRY *gce; if((ct==NULL)||(entry==NULL)) { printf("detach_this_gdl_entry: NULL\n"); return; } gce=gtk_ctree_node_get_row_data(GTK_CTREE(ct),GTK_CTREE_NODE(entry)); if((gce!=NULL)&&(gce->ct_type==GDL_ROOT)) { GString *str; str=g_string_new("/GDLDETACH "); g_string_sprintfa(str,"%lu\n",gce->c.root.gdl_id); send_data_to_dctc(str->str); g_string_free(str,TRUE); } } /*******************************/ /* detach selected GDL entries */ /*******************************/ void detach_selected_gdl_entry(void) { GtkWidget *w; GtkCTree *ctree; w=get_widget_by_widget_name("gdl_ctree"); if(w==NULL) return; ctree=GTK_CTREE(w); g_list_foreach(GTK_CLIST(ctree)->selection,detach_this_gdl_entry,ctree); update_lists_force_gdl(NULL); } static int as_created=0; /*************************************************************************/ /* create autoscan configuration window for the given entry of the ctree */ /*************************************************************************/ /* entry is a GtkCTreeNode, ct is a GtkCTree */ /*********************************************/ static void create_autoscan_window_for_this_gdl_entry(gpointer entry, gpointer ct) { GDL_CT_ENTRY *gce; if(as_created==1) return; if((ct==NULL)||(entry==NULL)) { return; } gce=gtk_ctree_node_get_row_data(GTK_CTREE(ct),GTK_CTREE_NODE(entry)); if((gce!=NULL)&&(gce->ct_type==GDL_ROOT)) { GtkWidget *w; w=get_widget_by_widget_name("as_gid_label"); if(w!=NULL) { char bf[64]; sprintf(bf,"%lu",gce->c.root.gdl_id); gtk_label_set(GTK_LABEL(w),bf); } w=get_widget_by_widget_name("as_fname_label"); if(w!=NULL) { gtk_label_set(GTK_LABEL(w),gce->c.root.local_filename); } /* switch to the find config tab */ w=get_widget_by_widget_name("main_notebook"); gtk_notebook_set_page(GTK_NOTEBOOK(w),FIND_CONFIG_TAB); w=get_widget_by_widget_name("gdl_as_pattern_entry"); if(w!=NULL) { gtk_editable_set_position(GTK_EDITABLE(w),0); gtk_editable_delete_text(GTK_EDITABLE(w),0,-1); gtk_widget_grab_focus(w); } } } /*****************************************************************/ /* create autoscan configuration window for selected GDL entries */ /*****************************************************************/ void create_autoscan_window_for_selected_gdl_entry(void) { GtkWidget *w; GtkCTree *ctree; w=get_widget_by_widget_name("gdl_ctree"); if(w==NULL) return; ctree=GTK_CTREE(w); as_created=0; g_list_foreach(GTK_CLIST(ctree)->selection,create_autoscan_window_for_this_gdl_entry,ctree); update_lists_force_gdl(NULL); } /**************************************************************/ /* create end program window for the given entry of the ctree */ /**************************************************************/ /* entry is a GtkCTreeNode, ct is a GtkCTree */ /*********************************************/ static void create_script_window_for_this_gdl_entry(gpointer entry, gpointer ct) { GDL_CT_ENTRY *gce; if(as_created==1) return; if((ct==NULL)||(entry==NULL)) { return; } gce=gtk_ctree_node_get_row_data(GTK_CTREE(ct),GTK_CTREE_NODE(entry)); if((gce!=NULL)&&(gce->ct_type==GDL_ROOT)) { GtkWidget *w; w=get_widget_by_widget_name("gdl_script_gid_label"); if(w!=NULL) { char bf[64]; sprintf(bf,"%lu",gce->c.root.gdl_id); gtk_label_set(GTK_LABEL(w),bf); } w=get_widget_by_widget_name("gdl_script_fname_label"); if(w!=NULL) { gtk_label_set(GTK_LABEL(w),gce->c.root.local_filename); } /* switch to the find config tab */ w=get_widget_by_widget_name("main_notebook"); gtk_notebook_set_page(GTK_NOTEBOOK(w),FIND_CONFIG_TAB); w=get_widget_by_widget_name("gdl_endname_filename_entry"); if(w!=NULL) { gtk_editable_set_position(GTK_EDITABLE(w),0); gtk_editable_delete_text(GTK_EDITABLE(w),0,-1); gtk_widget_grab_focus(w); } } } /*************************************************/ /* create rename window for selected GDL entries */ /*************************************************/ void create_script_window_for_selected_gdl_entry(void) { GtkWidget *w; GtkCTree *ctree; w=get_widget_by_widget_name("gdl_ctree"); if(w==NULL) return; ctree=GTK_CTREE(w); as_created=0; g_list_foreach(GTK_CLIST(ctree)->selection,create_script_window_for_this_gdl_entry,ctree); update_lists_force_gdl(NULL); } /*********************************************************/ /* create rename window for the given entry of the ctree */ /*********************************************************/ /* entry is a GtkCTreeNode, ct is a GtkCTree */ /*********************************************/ static void create_rename_window_for_this_gdl_entry(gpointer entry, gpointer ct) { GDL_CT_ENTRY *gce; if(as_created==1) return; if((ct==NULL)||(entry==NULL)) { return; } gce=gtk_ctree_node_get_row_data(GTK_CTREE(ct),GTK_CTREE_NODE(entry)); if((gce!=NULL)&&(gce->ct_type==GDL_ROOT)) { GtkWidget *w; w=get_widget_by_widget_name("gdl_rename_gid_label"); if(w!=NULL) { char bf[64]; sprintf(bf,"%lu",gce->c.root.gdl_id); gtk_label_set(GTK_LABEL(w),bf); } w=get_widget_by_widget_name("gdl_rename_fname_label"); if(w!=NULL) { gtk_label_set(GTK_LABEL(w),gce->c.root.local_filename); } /* switch to the find config tab */ w=get_widget_by_widget_name("main_notebook"); gtk_notebook_set_page(GTK_NOTEBOOK(w),FIND_CONFIG_TAB); w=get_widget_by_widget_name("gdl_rename_file_entry"); if(w!=NULL) { gtk_editable_set_position(GTK_EDITABLE(w),0); gtk_editable_delete_text(GTK_EDITABLE(w),0,-1); gtk_widget_grab_focus(w); } } } /*************************************************/ /* create rename window for selected GDL entries */ /*************************************************/ void create_rename_window_for_selected_gdl_entry(void) { GtkWidget *w; GtkCTree *ctree; w=get_widget_by_widget_name("gdl_ctree"); if(w==NULL) return; ctree=GTK_CTREE(w); as_created=0; g_list_foreach(GTK_CLIST(ctree)->selection,create_rename_window_for_this_gdl_entry,ctree); update_lists_force_gdl(NULL); } /**********************************************************************/ /* kill upload or download task using their ID (and /KILL or /KILLKB) */ /**********************************************************************/ void kill_selected_entry(char *cmd,char *clist_name) { GtkWidget *w; GtkCList *clist; GtkCListRow *clist_row; int row; char buf[512]; w=get_widget_by_widget_name(clist_name); if(w==NULL) return; clist=GTK_CLIST(w); for(row=0;rowrows;row++) { clist_row=g_list_nth(clist->row_list,row)->data; if(clist_row->state==GTK_STATE_SELECTED) { char *t; gtk_clist_get_text(clist,row,0,&t); sprintf(buf,"%s %s\n",cmd,t); send_data_to_dctc(buf); } } update_lists(NULL); } /*********************************************************************************************/ /* foreach selected line, send the given command followed by the content of the given column */ /*********************************************************************************************/ void foreach_selected_entry_send_cmd(char *cmd,char *clist_name, int column_num) { GtkWidget *w; GtkCList *clist; GtkCListRow *clist_row; int row; char buf[512]; w=get_widget_by_widget_name(clist_name); if(w==NULL) return; clist=GTK_CLIST(w); for(row=0;rowrows;row++) { clist_row=g_list_nth(clist->row_list,row)->data; if(clist_row->state==GTK_STATE_SELECTED) { char *t; gtk_clist_get_text(clist,row,column_num,&t); sprintf(buf,"%s %s\n",cmd,t); send_data_to_dctc(buf); } } } /*********************************************************************************************/ /* foreach selected line, send the given command followed by the content of the given column */ /*********************************************************************************************/ /* ctree version */ /*****************/ void foreach_selected_user_entry_of_gdl_ctree_send_cmd(char *cmd,char *ctree_name) { GtkWidget *w; GtkCList *clist; GtkCListRow *clist_row; int row; char buf[512]; w=get_widget_by_widget_name(ctree_name); if(w==NULL) return; clist=GTK_CLIST(w); for(row=0;rowrows;row++) { clist_row=g_list_nth(clist->row_list,row)->data; if(clist_row->state==GTK_STATE_SELECTED) { GDL_CT_ENTRY *gce; gce=gtk_clist_get_row_data(clist,row); if((gce!=NULL)&&(gce->ct_type==GDL_ACTIVE_SEGMENT)) { sprintf(buf,"%s %s\n",cmd,gce->c.active_segment.nickname); send_data_to_dctc(buf); } } } } /***********************************************************************************/ /* when the multihub search is enabled, this function is called after 10 seconds */ /* if more than 15 results are available, nothing occurs, else a /MSRCH is started */ /***********************************************************************************/ gint start_msearch(gpointer data) { GtkWidget *w; w=get_widget_by_widget_name("find_result"); if(w!=NULL) { if(GTK_CLIST(w)->rows<15) { GString *str; int i; str=g_string_new(""); for(i=0;i<2;i++) { if(last_search[i]!=NULL) { str=g_string_assign(str,last_search[i]->str); str=g_string_insert_c(str,1,'M'); /* transform the /SRCH into /MSRCH */ send_data_to_dctc(str->str); } } g_string_free(str,TRUE); } } last_search_tag=-1; return FALSE; /* don't timeout again */ } /*************************************************************************************/ /* search in the given clist a row having the given column containing a given string */ /*************************************************************************************/ /* output: -1: not found else row number in the clist */ /******************************************************/ int row_num(GtkCList *clst,int col_num, char *col_content) { int i; char *t; for(i=0;irows;i++) { gtk_clist_get_text(clst,i,col_num,&t); if(t!=NULL) { if(!strcmp(t,col_content)) return i; } } return -1; } static struct { const char *widget_name; const char *option_name; const char *autoflag_widget_name; } opt_list[]={ {"user_flag_ignore_pmsg_togglebutton","IGNORE_PMSG","autoflag_user_flag_ignore_pmsg_togglebutton"}, {"user_flag_ignore_pubmsg_togglebutton","IGNORE_PUBMSG","autoflag_user_flag_ignore_pubmsg_togglebutton"}, {"user_flag_ignore_srch_togglebutton","IGNORE_SRCH","autoflag_user_flag_ignore_srch_togglebutton"}, {"user_flag_ignore_sr_togglebutton","IGNORE_SREP","autoflag_user_flag_ignore_sr_togglebutton"}, {"user_flag_no_xfer_togglebutton","IGNORE_XFER","autoflag_user_flag_no_xfer_togglebutton"}, {"user_flag_ignore_dl_limit_togglebutton","IGNORE_SLOT_LIMIT","autoflag_user_flag_ignore_dl_limit_togglebutton"}, {NULL,NULL}}; /**********************************************/ /* automatically flag the given user nickname */ /**********************************************/ void auto_flag_user(char *nick) { int fl_row; GtkWidget *fl_w; GtkWidget *w; fl_w=get_widget_by_widget_name("flagged_user_clist"); if(fl_w==NULL) return; fl_row=row_num(GTK_CLIST(fl_w),0,nick); if(fl_row!=-1) { /* the user is already flagged */ gtk_clist_select_row(GTK_CLIST(fl_w),fl_row,0); } else { int i; w=get_widget_by_widget_name("flagged_user_label"); if(w) { gtk_label_set(GTK_LABEL(w),nick); i=0; while(opt_list[i].widget_name!=NULL) { w=get_widget_by_widget_name(opt_list[i].widget_name); if(w!=NULL) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(get_widget_by_widget_name(opt_list[i].autoflag_widget_name)))); } i++; } } /* automatically flag the user ? */ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(get_widget_by_widget_name("pchat_flag_auto_add_checkbutton")))==TRUE) { gtk_button_clicked(GTK_BUTTON(get_widget_by_widget_name("add_modify_flag_user_button"))); } } /* switch to flagged user tab ? */ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(get_widget_by_widget_name("pchat_flag_switch_to_flag_tab_checkbutton")))==TRUE) { w=get_widget_by_widget_name("main_notebook"); gtk_notebook_set_page(GTK_NOTEBOOK(w),FLAGGED_USER_TAB); } } /*************************************************/ /* flag the user of the given entry of the ctree */ /*************************************************/ /* entry is a GtkCTreeNode, ct is a GtkCTree */ /*********************************************/ void flag_user_of_this_gdl_entry(gpointer entry, gpointer ct) { GDL_CT_ENTRY *gce; if((ct==NULL)||(entry==NULL)) { printf("flag_user_of_this_gdl_entry: NULL\n"); return; } gce=gtk_ctree_node_get_row_data(GTK_CTREE(ct),GTK_CTREE_NODE(entry)); if((gce!=NULL)&&(gce->ct_type==GDL_ACTIVE_SEGMENT)) { auto_flag_user(gce->c.active_segment.nickname); } } /*******************************************************/ /* view user file list of the given entry of the ctree */ /*******************************************************/ /* entry is a GtkCTreeNode, ct is a GtkCTree */ /*********************************************/ void view_user_file_list_of_this_gdl_entry(gpointer entry, gpointer ct) { GDL_CT_ENTRY *gce; if((ct==NULL)||(entry==NULL)) { printf("flag_user_of_this_gdl_entry: NULL\n"); return; } gce=gtk_ctree_node_get_row_data(GTK_CTREE(ct),GTK_CTREE_NODE(entry)); if((gce!=NULL)&&(gce->ct_type==GDL_ACTIVE_SEGMENT)) { char buf[512]; sprintf(buf,"/LS %s\n",gce->c.active_segment.nickname); send_data_to_dctc(buf); } } /*********************************************************/ /* executed a command for each selected GDL source entry */ /*********************************************************/ void cmd_selected_gdl_user(void (*fnc)(gpointer entry, gpointer ct)) { GtkWidget *w; GtkCTree *ctree; w=get_widget_by_widget_name("gdl_ctree"); if(w==NULL) return; ctree=GTK_CTREE(w); g_list_foreach(GTK_CLIST(ctree)->selection,fnc,ctree); }