/***************************************************************************** * main.c * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * Copyright (C) 2000-2002 Chris Pinkham * Released under the terms of the GPL. * *NO WARRANTY* * * cpinkham@corp.infi.net, cpinkham@bc2va.org * http://www4.infi.net/~cpinkham/gyach/ *****************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifdef USE_PTHREAD_CREATE #include #endif #include "gyach.h" #ifndef OS_WINDOWS # include # include #endif #include #include "aliases.h" #include "callbacks.h" #include "commands.h" #include "friends.h" #include "gyach_int.h" #include "ignore.h" #include "images.h" #include "interface.h" #include "main.h" #include "support.h" #include "users.h" #include "util.h" #include "yahoochat.h" /* ------------------------------------------------------------------------ */ #ifndef USE_GTK2 typedef enum { Medium, Bold } FontWeight; typedef enum { Italic, Roman } FontSlant; static GdkFont *get_font(const char *family, const short size, const FontWeight weight, const FontSlant slant) { GdkFont *font = NULL; char XLFD[1000]; char my_font_name[129]; char *ptr; char *from; char *to; #ifndef OS_WINDOWS XFontStruct *fontOK = (XFontStruct *) NULL; #endif DBG( 21, "get_font( '%s', %d, %d, %d )\n", family, size, weight, slant ); if ( font ) { gdk_font_unref( font ); font = NULL; } my_strncpy( my_font_name, font_name, sizeof(my_font_name)); strcpy(XLFD, "-*"); /* foundry */ if (family && *family) { char *p = NULL, *lowerFace = NULL; strcat(XLFD, "-"); p = lowerFace = strdup(family); while (p && *p) { int c = tolower(*p); *p = c; ++p; } strcat(XLFD, lowerFace); free(lowerFace); } else { strcat(XLFD, "-times"); /* default family, I should really get this from the current theme */ } switch (weight) { case Bold: strcat(XLFD, "-bold"); /* weight */ if (( ptr = strstr( my_font_name, "medium" ))) { strcpy( ptr, "bold" ); to = ptr + 4; from = ptr + 6; while( *from ) { *(to++) = *(from++); } *to = '\0'; } break; case Medium: default: strcat(XLFD, "-medium"); /* weight */ if (( ptr = strstr( my_font_name, "bold" ))) { from = strstr( font_name, "bold" ) + 4; strcpy( ptr, "medium" ); to = ptr + 6; while( *from ) { *(to++) = *(from++); } *to = '\0'; } break; } switch (slant) { case Italic: strcat(XLFD, "-i"); /* slant : italic */ break; case Roman: default: strcat(XLFD, "-r"); /* slant : roman */ break; } strcat(XLFD, "-normal"); /* set width */ strcat(XLFD, "-*"); /* additional style (nil) */ /* dunno why, but he appears to have had these next 2 fields reversed, it */ /* works better this way. */ /* if (size > -1) { char sizeS[10]; sprintf(sizeS, "-%d", 10 * size); strcat(XLFD, sizeS); } else { strcat(XLFD, "-*"); } */ { char sizeS[10]; sprintf(sizeS, "-%d", font_size); strcat(XLFD, sizeS); } strcat(XLFD, "-*"); /* pixel size (don't care) */ strcat(XLFD, "-*"); /* resolution X */ strcat(XLFD, "-*"); /* resolution Y */ strcat(XLFD, "-*"); /* proportional spacing */ strcat(XLFD, "-*"); /* Average width */ strcat(XLFD, "-*"); /* Charset registry */ strcat(XLFD, "-*"); /* Charset encoding */ /* printf( "XLFD: %s\n", XLFD ); printf( " my: %s\n", my_font_name ); fflush( stdout ); */ if ( ! show_fonts ) { strcpy( XLFD, my_font_name ); } /* Test load the font. If it fails, fontOK is null, and get on with * life after giving the user an error. * If it is successful, immediately unload the font, since we're using * GTK+ here, mmmk? */ #ifndef OS_WINDOWS fontOK = XLoadQueryFont(GDK_DISPLAY(), XLFD); if (fontOK == (XFontStruct *) NULL || (!fontOK)) { /* Font was no good - you can't load this font. */ font = NULL; } else { /* Remember to free this since XLoadQueryFont returns allocated memory */ XFreeFont(GDK_DISPLAY(), fontOK); font = gdk_font_load(XLFD); } #endif if ( ! font ) { strcpy( XLFD, "-*-times-medium-r-normal-*-14-*-*-*-*-*-*-*" ); font = gdk_font_load( XLFD ); } return font; } GdkFont *getFont(int bold, int italic, int underline, const char *family, const char *sizeS) { static GdkFont *font = NULL; FontWeight weight; FontSlant slant; short size = 0; DBG( 21, "getFont( %d, %d, %d, '%s', '%s' )\n", bold, italic, underline, family, sizeS ); if (sizeS && *sizeS) { size = atoi(sizeS); } weight = bold ? Bold : Medium; slant = italic ? Italic : Roman; if (NULL != font) { gdk_font_unref(font); font = NULL; } if (NULL == (font = get_font(family, size, weight, slant))) { /* If the getting the actual font fails, first try a few sizes smaller and then try a blank family */ short trySize = size - 1, endTrySize = (size - 4); if (family && *family) { while ((trySize > 0) && (NULL == (font = get_font(family, trySize, weight, slant))) && (trySize > endTrySize)) { --trySize; } } if (NULL == font) { trySize = size; while ((trySize > 0) && (NULL == (font = get_font(NULL, trySize, weight, slant))) && (trySize > endTrySize)) { --trySize; } } } if (NULL == font) { gdk_font_ref(font); } return (font); } #endif /* #ifndef USE_GTK2 */ int real_show_colors = 1; #ifdef USE_GTK2 void tv_append_text_with_color( GtkTextView *text_view, char *text, int len, int r, int g, int b, char *font ) { char buf[1024]; char tmp[32]; GtkTextTagTable *tag_table; GtkTextBuffer *text_buffer; GdkColor chat_color; GtkTextIter iter; GtkTextMark *end_mark; text_buffer = gtk_text_view_get_buffer( text_view ); chat_color.red = r * ( 65535 / 255 ); chat_color.green = g * ( 65535 / 255 ); chat_color.blue = b * ( 65535 / 255 ); sprintf( tmp, "fg_%05d%05d%05d", chat_color.red, chat_color.green, chat_color.blue ); tag_table = gtk_text_buffer_get_tag_table( text_buffer ); if ( ! gtk_text_tag_table_lookup( tag_table, tmp )) { gtk_text_buffer_create_tag( text_buffer, tmp, "foreground-gdk", &chat_color, NULL); } if ( ! gtk_text_tag_table_lookup( tag_table, font )) { gtk_text_buffer_create_tag( text_buffer, font, "font", font, NULL); } gtk_text_buffer_get_end_iter( text_buffer, &iter ); strncpy( buf, text, len ); buf[len] = '\0'; gtk_text_buffer_insert_with_tags_by_name( text_buffer, &iter, buf, len, tmp, font, NULL ); end_mark = gtk_text_buffer_get_mark( text_buffer, "end_mark" ); gtk_text_view_scroll_to_mark( text_view, end_mark, 0, FALSE, 0, 0 ); gtk_text_buffer_get_iter_at_mark( text_buffer, &iter, end_mark ); gtk_text_buffer_place_cursor( text_buffer, &iter ); } #endif static int bold = FALSE, italic = FALSE, underline = FALSE, url = FALSE; void append_to_textbox(GtkWidget *window, GtkWidget *textbox, char *text) { int i = 0; #ifndef USE_GTK2 GdkColor colorspace; GdkColor *color = &colorspace; GdkFont *font = NULL; #endif char face[1000] = "", size[1000] = ""; int tmp_color; char *tmp_ptr; char *tmp_ptr2; char buf[1024]; int scroll = FALSE; unsigned int r, g, b; unsigned int or, og, ob; char *sound = NULL; struct stat sbuf; int tmp_int; char sm_file[128]; #ifdef USE_PTHREAD_CREATE pthread_t prof_thread; #endif #ifdef USE_GTK2 char user_font[129]; #endif DBG( 21, "append_to_textbox( %p, %p, '%s' )\n", window, textbox, text ); *face = *size = '\0'; my_strncpy( face, font_family, sizeof(face)); #ifdef USE_GTK2 my_strncpy( face, font_family, sizeof(face)); bold = use_bold; italic = use_italics; sprintf( size, "%d", font_size ); #else font = getFont(bold, italic, underline, face, size); #endif if ( force_lowercase ) lower_str( text ); strip_junk( text ); convert_tags( text ); if (( show_emoticons ) && ( ! textbox )) { convert_smileys( text ); } if (( recv_sound ) && ( filename_is_sane( recv_sound ))) { sound = recv_sound; recv_sound = NULL; snprintf( buf, sizeof(buf), "%s/sounds/%s.wav", GYACH_CFG_DIR, sound ); free( sound ); sound = strdup( buf ); if ( ! stat( buf, &sbuf )) { #ifdef USE_PTHREAD_CREATE pthread_create( &prof_thread, NULL, play_sound, (void *)sound ); #else play_sound( (void *)sound ); #endif } else { snprintf( buf, sizeof(buf), PACKAGE_DATA_DIR "/sounds/%s.wav", sound ); if ( ! stat( buf, &sbuf )) { #ifdef USE_PTHREAD_CREATE pthread_create( &prof_thread, NULL, play_sound, (void *)sound ); #else play_sound( (void *)sound ); #endif } } } if (( ! textbox ) && ( ct_scroll_at_bottom())) { scroll = TRUE; } /* Reset all attributes - currently just color */ r = g = b = 0; or = og = ob = 0; /* freeze before printing to speed up display, especially on blended */ /* colors or for people who switch colors every letter */ if ( ! textbox ) ct_freeze(); i = 0; while (text[i] && i < strlen(text)) { if (!strncmp(&text[i], YAHOO_FONT_TAG_START, strlen(YAHOO_FONT_TAG_START))) { int closeFound = FALSE; i += strlen(YAHOO_FONT_TAG_START); while (!closeFound) { #ifdef PARSE_USER_FONTS if (( show_fonts ) && ( !strncmp(&text[i], YAHOO_FONT_FACE_START, strlen(YAHOO_FONT_FACE_START)))) { int k = 0; i += strlen(YAHOO_FONT_FACE_START); while (text && i < strlen(text) && text[i] != '"') { face[k] = text[i]; ++i; ++k; face[k] = '\0'; } while (text && i < strlen(text) && NULL != strchr("\" \t", text[i])) { ++i; } } #endif if (!strncmp(&text[i], YAHOO_FONT_SIZE_START, strlen(YAHOO_FONT_SIZE_START))) { int k = 0; i += strlen(YAHOO_FONT_SIZE_START); while (text && i < strlen(text) && text[i] != '"') { size[k] = text[i]; ++i; ++k; size[k] = '\0'; } while (text && i < strlen(text) && NULL != strchr("\" \t", text[i])) { ++i; } if ( ! size[0] ) { strcpy( size, "12" ); } } if (text && '>' == text[i]) { ++i; closeFound = TRUE; continue; } i++; } #ifndef USE_GTK2 if ( show_fonts ) /* should we use their font? */ { font = getFont(bold, italic, underline, face, size); } #endif continue; #ifdef TRY_WITHOUT_THIS } else if ( text[i] == '<' ) { /* shouldn't get in here except when user puts a literal < */ i++; #endif } else if (( text[i] == 033 ) && ( text[i+1] == '|' )) { /* we found one of our converted smileys */ i += 2; /* skip over the escape and | */ tmp_ptr = &text[i]; tmp_ptr2 = find_whitespace( tmp_ptr ); strncpy( sm_file, tmp_ptr, tmp_ptr2 - tmp_ptr ); sm_file[tmp_ptr2 - tmp_ptr] = '\0'; tmp_int = atoi( &text[i] ); i += tmp_ptr2 - tmp_ptr; if ( ! ct_can_do_pixmaps()) { continue; } snprintf( buf, sizeof(buf), "%s/smileys/%s", GYACH_CFG_DIR, sm_file ); if ( ! stat( buf, &sbuf )) { ct_append_pixmap( buf ); } else { snprintf( buf, sizeof(buf), PACKAGE_DATA_DIR "/smileys/%s", sm_file ); if ( ! stat( buf, &sbuf )) { ct_append_pixmap( buf ); } } } else if (( text[i] == 033 ) && ( text[i+1] == '[' )) { i += 2; /* skip over the escape and [ */ if ( text[i+1] == ';' ) { /* we have a bold/not bold */ if ( text[i] == '0' ) { bold = FALSE; } else { bold = TRUE; } #ifndef USE_GTK2 font = getFont(bold, italic, underline, face, size); #endif i += 2; } if ( text[i] == 'x' ) { /* turn something OFF */ i++; switch ( text[i] ) { case '1': bold = FALSE ; #ifndef USE_GTK2 font = getFont(bold, italic, underline, face, size); #endif break; case '2': italic = FALSE; #ifndef USE_GTK2 font = getFont(bold, italic, underline, face, size); #endif break; case '4': underline = FALSE; #ifndef USE_GTK2 font = getFont(bold, italic, underline, face, size); #endif break; case 'l': url = FALSE ; r = or; g = og; b = ob; #ifndef USE_GTK2 font = getFont(bold, italic, underline, face, size); #endif break; } i += 2; continue; } else if ( text[i] == '#' ) { /* we found a blended color */ char tmp_int[3]; if ( show_blended_colors ) { or = r; og = g; ob = b; tmp_int[2] = '\0'; tmp_int[0] = text[ i + 1 ]; tmp_int[1] = text[ i + 2 ]; sscanf( tmp_int, "%x", &r ); tmp_int[0] = text[ i + 3 ]; tmp_int[1] = text[ i + 4 ]; sscanf( tmp_int, "%x", &g ); tmp_int[0] = text[ i + 5 ]; tmp_int[1] = text[ i + 6 ]; sscanf( tmp_int, "%x", &b ); } i += 8; continue; } else { tmp_color = atoi( &text[i] ); switch ( tmp_color ) { case 0: if (( text[i] == 'l' ) && ( text[i+1] == 'm' )) { /* always show urls in blue if ( real_show_colors ) { */ url = TRUE ; or = r; og = g; ob = b; r = 0; g = 0; b = 0xff; /* } */ i += 2; continue; } else if ( text[i+1] == 'm' ) { italic = FALSE; bold = FALSE; underline = FALSE; url = FALSE; #ifndef USE_GTK2 font = getFont(bold, italic, underline, face, size); #endif /* black */ or = r; og = g; ob = b; r = 0; g = 0; b = 0; i += 2; continue; } break; case 1: bold = TRUE ; #ifndef USE_GTK2 if ( show_fonts ) font = getFont(bold, italic, underline, face, size); #endif i += 2; continue; break; case 2: italic = TRUE; #ifndef USE_GTK2 if ( show_fonts ) font = getFont(bold, italic, underline, face, size); #endif i += 2; continue; break; case 4: underline = TRUE; #ifndef USE_GTK2 if ( show_fonts ) font = getFont(bold, italic, underline, face, size); #endif i += 2; continue; break; case 30: /* black */ if ( real_show_colors ) { or = r; og = g; ob = b; r = 0; g = 0; b = 0; } i += 3; break; case 31: /* blue */ if ( real_show_colors ) { or = r; og = g; ob = b; r = 0; g = 0; b = 0xff; } i += 3; break; case 32: /* cyan */ if ( real_show_colors ) { or = r; og = g; ob = b; r = 0; g = 0xb2; b = 0xb2; } i += 3; break; case 33: /* gray */ if ( real_show_colors ) { or = r; og = g; ob = b; r = 0x80; g = 0x80; b = 0x80; } i += 3; break; case 34: /* green */ if ( real_show_colors ) { or = r; og = g; ob = b; r = 0; g = 0xc2 ; b = 0; } i += 3; break; case 35: /* pink */ if ( real_show_colors ) { or = r; og = g; ob = b; r = 0xff; g = 0xaf; b = 0xaf; } i += 3; break; case 36: /* purple */ if ( real_show_colors ) { or = r; og = g; ob = b; r = 0xb2; g = 0; b = 0xb2; } i += 3; break; case 37: /* yellow */ if ( real_show_colors ) { or = r; og = g; ob = b; r = 0xff; g = 0xff ; b = 0; } i += 3; break; case 38: /* red */ if ( real_show_colors ) { or = r; og = g; ob = b; r = 0xff ; g = 0; b = 0; } i += 3; break; case 39: /* olive */ if ( real_show_colors ) { or = r; og = g; ob = b; r = 0x54; g = 0x6b ; b = 0x50; } i += 3; break; } } continue; } else if ( text[i] == 033 ) { i++; } if (i >= strlen(text)) { break; } if ( text[i] == 033 ) { continue; } /* if ( text[i] == '<' ) { continue; } */ if ( ! text[i] ) { continue; } /* print out as much as we can */ tmp_ptr = strchr( &text[i], 033 ); tmp_ptr2 = strstr( &text[i], "red = r * ( 65535 / 255 ); color->green = g * ( 65535 / 255 ); color->blue = b * ( 65535 / 255 ); gdk_colormap_alloc_color( gtk_widget_get_colormap(GTK_WIDGET(textbox)), color, FALSE, TRUE); gtk_text_insert(GTK_TEXT(textbox), font, color, NULL, (gchar *) & text[i], tmp_color ); #endif } else { ct_set_color( r, g, b ); #ifdef USE_GTK2 if ( show_fonts ) { my_strncpy( user_font, face, sizeof(user_font)); my_strncat( user_font, " ", sizeof(user_font)); if ( bold ) my_strncat( user_font, "Bold ", sizeof(user_font)); if ( italic ) my_strncat( user_font, "Italic ", sizeof(user_font)); my_strncat( user_font, size, sizeof(user_font)); ct_set_font( user_font ); } else { ct_set_font( font_name ); } #else ct_set_font( font ); #endif tmp_ptr = strstr( text, ":\n" ); if ( tmp_ptr > ( text + tmp_color )) { tmp_ptr = NULL; } /* attempt to display /exec-ed stuff in fixed width font */ if (( tmp_ptr != NULL ) && ( tmp_ptr != ( text + strlen( text ) - 2 ))) { ct_append_fixed( &text[i], tmp_color ); } else { tmp_ptr = strstr( text, "-->\n" ); if (( tmp_ptr != NULL ) && ( tmp_ptr != ( text + strlen( text ) - 4 ))) { ct_append_fixed( &text[i], tmp_color ); } else { #ifdef USE_GTK2 if ( url ) { ct_set_underline( 1 ); } #endif ct_append( &text[i], tmp_color ); } } } if ( capture_fp ) { fwrite( &text[i], 1, tmp_color, capture_fp ); } i += tmp_color; } if ( ! textbox ) ct_thaw(); if( scroll ) ct_scroll_to_bottom(); if ( capture_fp ) fflush( capture_fp ); DBG( 22, "RETURN append_to_textbox()\n" ); } void append_to_textbox_color(GtkWidget *win, GtkWidget *tb, char *text) { char tmp[128] = ""; int old_colors = real_show_colors; int old_fonts = show_fonts; int old_lower = force_lowercase; DBG( 21, "append_to_textbox_color( %p, %p, '%s' )\n", win, tb, text ); real_show_colors = 1; show_fonts = 1; force_lowercase = 0; /* reset things to normal */ if ( bold ) strcpy( tmp, YAHOO_STYLE_BOLDOFF ); if ( italic ) strcpy( tmp, YAHOO_STYLE_ITALICOFF ); if ( underline ) strcpy( tmp, YAHOO_STYLE_UNDERLINEOFF ); if ( url ) strcpy( tmp, YAHOO_STYLE_URLOFF ); if ( tmp[0] ) append_to_textbox( win, tb, tmp ); /* now send our text */ append_to_textbox( win, tb, text ); real_show_colors = old_colors; show_fonts = old_fonts; force_lowercase = old_lower; DBG( 22, "RETURN append_to_textbox_color()\n" ); } /* ------------------------------------------------------------------------ */ /* send a chat command * Note: it modifies the string in place * return FALSE if we should quit */ void chat_command( char *cmd ) { char *txt = ""; char *args; char buf[2048] = ""; char tmp[1025] = ""; DBG( 21, "chat_command( '%s' )\n", cmd ); cmd = skip_whitespace( cmd ); auto_away_time = time(NULL) + ( auto_away * 60 ); switch(cmd[0]) { case '\0': return; break; case ':': if ( cmd[1] == '!' ) { /* emote a ! or !! */ if ( cmd[2] == '!' ) { snprintf( buf, sizeof(buf), "/execlocal_e %s", cmd+3 ); } else { snprintf( buf, sizeof(buf), "/exec_e %s", cmd+2 ); } try_command( buf ); return; } else { if ( check_smiley( cmd )) { /* it's a smiley */ txt = cmd; subst_escs( txt ); convert_smileys( txt ); } else { /* it's not */ txt = cmd + 1; subst_escs( txt ); snprintf( buf, sizeof(buf), "/emote %s", txt); try_command( buf ); return; } } break; case '!': if ( cmd[1] == '!' ) { snprintf( buf, sizeof(buf), "/execlocal %s", cmd+2); } else { snprintf( buf, sizeof(buf), "/exec %s", cmd+1); } try_command( buf ); return; break; case '/': if ( try_command( cmd )) return; args = find_whitespace( cmd + 1); if ( *args ) { *args = '\0'; args++; args = skip_whitespace( args ); } if ( check_alias( cmd + 1, args )) return; snprintf( buf, sizeof(buf), "*** Gyach: unknown command '%s'\n", cmd ); append_to_textbox( chat_window, NULL, buf ); return; break; default: if (( cmd[0] == '\\' ) && (( cmd[1] == '/' ) || ( cmd[1] == ':' ) || ( cmd[1] == '!' ))) { txt = cmd +1; } else { txt = cmd; } subst_escs( txt ); break; } if ( use_color ) { if ( ! strcmp( use_color, "black" )) { my_strncat( buf, YAHOO_COLOR_BLACK, sizeof(buf)); } else if ( ! strcmp( use_color, "blue" )) { my_strncat( buf, YAHOO_COLOR_BLUE, sizeof(buf)); } else if ( ! strcmp( use_color, "cyan" )) { my_strncat( buf, YAHOO_COLOR_CYAN, sizeof(buf)); } else if ( ! strcmp( use_color, "gray" )) { my_strncat( buf, YAHOO_COLOR_GRAY, sizeof(buf)); } else if ( ! strcmp( use_color, "green" )) { my_strncat( buf, YAHOO_COLOR_GREEN, sizeof(buf)); } else if ( ! strcmp( use_color, "pink" )) { my_strncat( buf, YAHOO_COLOR_PINK, sizeof(buf)); } else if ( ! strcmp( use_color, "purple" )) { my_strncat( buf, YAHOO_COLOR_PURPLE, sizeof(buf)); } else if ( ! strcmp( use_color, "yellow" )) { my_strncat( buf, "\033[#ffff00m", sizeof(buf)); } else if ( ! strcmp( use_color, "orange" )) { my_strncat( buf, "\033[#ffc800m", sizeof(buf)); } else if ( ! strcmp( use_color, "red" )) { my_strncat( buf, YAHOO_COLOR_RED, sizeof(buf)); } else if ( ! strcmp( use_color, "custom" )) { #ifdef TRANS_BG if (( trans_bg ) && ( custom_color_red > 0xa0 ) && ( custom_color_green > 0xa0 ) && ( custom_color_blue > 0xa0 )) { my_strncat( buf, YAHOO_COLOR_BLACK, sizeof(buf)); } else { #endif sprintf( buf, "\033[#%02x%02x%02xm", custom_color_red, custom_color_green, custom_color_blue ); #ifdef TRANS_BG } #endif } } snprintf( tmp, sizeof(tmp), "%s %s%s\" %s%d\">", YAHOO_FONT_TAG_START, YAHOO_FONT_FACE_START, font_family, YAHOO_FONT_SIZE_START, font_size ); my_strncat( buf, tmp, sizeof(buf)); if ( use_bold ) my_strncat( buf, YAHOO_STYLE_BOLDON, sizeof(buf)); if ( use_italics ) my_strncat( buf, YAHOO_STYLE_ITALICON, sizeof(buf)); if ( use_underline ) my_strncat( buf, YAHOO_STYLE_UNDERLINEON, sizeof(buf)); if ( filter_command ) { my_strncat( buf, filter_text( txt ), sizeof(buf)); } else { my_strncat( buf, txt, sizeof(buf)); } if ( *buf ) { if( send_avatar ) { my_strncat( buf, AVATAR_START, sizeof(buf)); my_strncat( buf, send_avatar, sizeof(buf)); my_strncat( buf, AVATAR_SEND_END, sizeof(buf)); #ifndef OS_WINDOWS if ( show_avatars ) { display_avatar( ymsg_sess->user, send_avatar ); } #endif } gyach_comment( ymsg_sess, buf ); } } char ymsg_fields[300][2048]; int split( char *str, char *connector ) { char *last; char *orig; char *ptr; char tmp_str[ 2048 ]; int result = 0; int i = 0; my_strncpy( tmp_str, str, sizeof(tmp_str)); str = tmp_str; last = orig = str; while (( ptr = strstr( str, connector ))) { *ptr = '\0'; strcpy( ymsg_fields[result], last ); str = last = ptr + strlen( connector ); result++; } if ( last != orig ) { strcpy( ymsg_fields[result], last ); } else { result--; } strcpy( ymsg_fields[result], "__END__" ); strcpy( ymsg_fields[result+1], "__END__" ); i = 0; while( strcmp( ymsg_fields[i], "__END__" )) { if (( ymsg_sess->debug_packets ) && ( strcmp( ymsg_fields[i], "117" ))) { fprintf( stderr, "%-3s = '%s'\n", ymsg_fields[i], ymsg_fields[i+1] ); fflush( stderr ); } i += 2; } return( result + 1 ); } char *ymsg9_field_p( char *key ) { int i = 0; static char result[2048]; char *ptr; result[0] = '\0'; while( strcmp( ymsg_fields[i], "__END__" )) { if ( ! strcmp( ymsg_fields[i], key )) { if ( ymsg_fields[i+1][0] == 'C' ) { i += 2; continue; } if ( !strcmp( key, "59" )) { ptr = strstr( ymsg_fields[i+1], "; expires" ); if ( ptr ) *ptr = '\0'; } if ( result[0] ) { my_strncat( result, "| ", sizeof(result)); } my_strncat( result, ymsg_fields[i+1], sizeof(result)); } i += 2; } return( result ); } char *ymsg9_field( char *key ) { int i = 0; static char result[2048]; char *ptr; result[0] = '\0'; while( strcmp( ymsg_fields[i], "__END__" )) { if ( ! strcmp( ymsg_fields[i], key )) { if ( !strcmp( key, "59" )) { ptr = strstr( ymsg_fields[i+1], "; expires" ); if ( ptr ) *ptr = '\0'; } if ( result[0] ) { my_strncat( result, ",", sizeof(result)); } my_strncat( result, ymsg_fields[i+1], sizeof(result)); } i += 2; } return( result ); } void show_yahoo_packet() { static char buf[1024]; /* these are static so they aren't on the stack */ static char tmp[2048]; static char tmp2[2048]; static char tmp3[2048]; char *lf; char *ptr; char *src; char *end; int lf_count = 0; int last; time_t time_now; int hours; int minutes; int seconds; struct tm *tm_now; GList *pm_lptr; PM_SESSION *pm_sess; int display; int accept_pm; int count; time_t exp_time; #ifdef USE_GTK2 GtkTextBuffer *text_buffer; GtkTextIter end_iter; #endif if ( ymsg_sess->pkt.size ) { split( ymsg_sess->pkt.data, "\xC0\x80" ); } else { strcpy( ymsg_fields[0], "__END__" ); strcpy( ymsg_fields[1], "__END__" ); } switch( ymsg_sess->pkt.type ) { case YMSG9_REJECTBUDDY: break; case YMSG9_GET_KEY: connect_time = time(NULL); strcpy( tmp, ymsg9_field( "94" )); ymsg9_login( ymsg_sess, tmp ); gtk_statusbar_pop( GTK_STATUSBAR(chat_status), st_cid ); gtk_statusbar_push( GTK_STATUSBAR(chat_status), st_cid, "Logging in to chat server..." ); strcpy(buf ,"Chat started, type /help for help\n"); append_to_textbox( chat_window, NULL, buf ); /* reset cookies */ ymsg_sess->cookie[0] = '\0'; break; case YMSG9_COOKIE: /* set online if we got the right cookie packet */ if ( strcmp( ymsg9_field( "3" ), "" )) { gtk_statusbar_pop( GTK_STATUSBAR(chat_status), st_cid ); gtk_statusbar_push( GTK_STATUSBAR(chat_status), st_cid, "Setting status to Online..." ); ymsg9_online( ymsg_sess ); } /* store any cookie(s) */ if ( strcmp( ymsg9_field( "59" ), "" )) { if ( ymsg_sess->cookie[0] ) { my_strncat( ymsg_sess->cookie, ";", YMSG9_COOKIE_SIZE); my_strncat( ymsg_sess->cookie, ymsg9_field_p( "59" ), YMSG9_COOKIE_SIZE); } else { my_strncat( ymsg_sess->cookie, ymsg9_field_p( "59" ), YMSG9_COOKIE_SIZE); } ptr = ymsg_sess->cookie; ptr = strchr( ptr, ' ' ); /* a tab */ while( ptr ) { *ptr = '='; ptr = strchr( ptr, '|' ); if ( ptr ) { *ptr = ';'; ptr = strchr( ptr, ' ' ); /* a tab */ } } } /* set our buddy list */ if ( strcmp( ymsg9_field( "87" ), "" )) { populate_friend_list( ymsg9_field( "87" )); } /* merge yahoo ignore list into local list */ if ( strcmp( ymsg9_field( "88" ), "" )) { strcpy( tmp, ymsg9_field( "88" )); ptr = tmp; while( ptr ) { end = strchr( ptr, ',' ); if ( end ) *end = '\0'; if ( ! ignore_check( ptr )) ignore_toggle( ptr ); if ( end ) { ptr = end + 1; } else { ptr = NULL; } } } break; case YMSG9_ONLINE: ymsg9_join( ymsg_sess ); gtk_statusbar_pop( GTK_STATUSBAR(chat_status), st_cid ); snprintf( buf, sizeof(buf), "Current Room: %s", ymsg_sess->room ); gtk_statusbar_push( GTK_STATUSBAR(chat_status), st_cid, buf ); break; case YMSG9_MAIL: /* don't print if Yahoo is telling us our mailbox is empty */ if ( atoi( ymsg9_field( "9" )) == 0 ) { return; } snprintf( buf, sizeof(buf), "*** You have %s%s%s email(s). " "http://mail.yahoo.com ***\n", YAHOO_COLOR_RED, ymsg9_field( "9" ), YAHOO_COLOR_BLACK ); append_to_textbox( chat_window, NULL, buf ); break; case YMSG9_AWAY: case YMSG9_BACK: /* user status change */ strcpy( tmp, ymsg9_field( "7" )); strcpy( tmp2, ymsg9_field( "10" )); strcpy( tmp3, ymsg9_field( "19" )); if ( ! strcmp( ymsg9_field( "7" ), "" )) { /* this is just a confirmation that we came back */ return; } if (( ignore_check( tmp )) || ( mute_check( tmp ))) { return; } /* * for now don't display for room users since we get this * in a comment packet from at least both curphoo and gyach */ if ( find_user_row( tmp ) >= 0 ) { return; } if ( ymsg_sess->pkt.type == YMSG9_BACK ) { strcpy( tmp2, "0" ); } if (( atoi( tmp2 ) == 99 ) || ( atoi( tmp2 ) == 999 )) { /* custom away message in tmp3 */ } else { /* stock away message */ strcpy( tmp3, away_msgs[atoi(tmp2)] ); } if ( find_friend( tmp )) { snprintf( buf, sizeof(buf), "%s%s%s%s%s ", YAHOO_STYLE_BOLDON, YAHOO_COLOR_GREEN, tmp, YAHOO_COLOR_PURPLE, YAHOO_STYLE_BOLDOFF ); } else { snprintf( buf, sizeof(buf), "%s%s%s%s%s ", YAHOO_STYLE_BOLDON, YAHOO_COLOR_RED, tmp, YAHOO_COLOR_PURPLE, YAHOO_STYLE_BOLDOFF ); } if ( atoi( tmp2 )) { /* away */ chatter_list_status( tmp, pixmap_status_away, "AW" ); my_strncat( buf, "is away ( ", sizeof(buf)); my_strncat( buf, tmp3, sizeof(buf)); my_strncat( buf, " )\n", sizeof(buf)); } else { /* back */ chatter_list_status( tmp, pixmap_status_here, "" ); my_strncat( buf, "is back\n", sizeof(buf)); } append_to_textbox( chat_window, NULL, buf ); break; case YMSG9_COMMENT: /* user comment/emote/thought */ strcpy( tmp, ymsg9_field( "109" )); strcpy( tmp2, ymsg9_field( "117" )); /* set auto-away if needed */ /* should put this in the event loop somehow */ if (( ! my_status ) && ( auto_away ) && ( time(NULL) > auto_away_time )) { cmd_away( "11" ); } /* ignore comments from users not in the chatter list */ /* if ( find_user_row( tmp ) < 0 ) { return; } */ if ( ignore_check( tmp )) { return; } if ( mute_check( tmp )) { return; } ptr = get_last_comment( tmp ); if (( first_post_is_url ) && ( ! find_friend( tmp )) && (( strstr( tmp2, "http://" )) || ( strstr( tmp2, "ftp://" )) || ( strstr( tmp2, " www." ))) && (( ! strstr( tmp2, "Gyach" )) && ( ! strstr( tmp2, "jfcinnovations" )) && ( ! strstr( tmp2, "waduck.com" ))) && (( ptr == NULL ) || ( !strcmp( ptr, "Entered Room" )))) { if ( ! ignore_check( tmp )) { ignore_toggle( tmp ); } snprintf( buf, sizeof(buf), "Gyach - auto-ignored %s%s%s, first " "post was a URL: '%s'\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK, tmp2 ); append_to_textbox( chat_window, NULL, buf ); return; } if ((( ptr = auto_ignore_check( tmp2 )) != NULL ) && ( ! find_friend( tmp ))) { if ( ! ignore_check( tmp )) { ignore_toggle( tmp ); } else { return; } snprintf( buf, sizeof(buf), "Gyach - auto-ignored %s%s%s, regex '%s'\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK, ptr ); append_to_textbox( chat_window, NULL, buf ); if ( ! disp_auto_ignored ) { return; } } /* keep track of last thing the user said */ count = set_last_comment( tmp, tmp2 ); if (( ignore_on_mults ) && ( count > ignore_on_mults ) && ( ! find_friend( tmp )) && ( ! ignore_check( tmp ))) { ignore_toggle( tmp ); snprintf( buf, sizeof(buf), "Gyach - auto-ignored %s%s%s, same post " "%d times: \"%s\"\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK, count, tmp2 ); append_to_textbox( chat_window, NULL, buf ); } else if (( mute_on_mults ) && ( count > mute_on_mults ) && ( ! find_friend( tmp )) && ( ! mute_check( tmp ))) { mute_toggle( tmp ); snprintf( buf, sizeof(buf), "Gyach - auto-muted %s%s%s, same post " "%d times: \"%s\"\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK, count, tmp2 ); append_to_textbox( chat_window, NULL, buf ); } if (( suppress_mult ) && ( count > 1 )) { return; } /* need to make fetch_avatar windows-safe */ #ifndef OS_WINDOWS if ( show_avatars ) { /* check for an avatar and update if needed */ if (( ptr = strstr( tmp2, AVATAR_START )) != NULL ) { /* avatar exists so try to display if unset */ ptr += strlen( AVATAR_START ); end = strstr( ptr, AVATAR_END ); if ( ! end ) { end = strchr( ptr, '>' ); } if ( end ) { *end = '\0'; if ( filename_is_sane( ptr )) display_avatar( tmp, ptr ); } } } #endif strcpy( tmp2, ymsg9_field( "117" )); /* check for lots of linefeeds */ if ( limit_lfs ) { lf = strchr( tmp2, '\n' ); while( lf ) { lf_count++; lf = strchr( lf + 1, '\n' ); } if ( lf_count > limit_lfs ) { lf = strchr( tmp2, '\n' ); while( lf ) { *lf = '|'; lf = strchr( lf + 1, '\n' ); } } } if ( chat_timestamp ) { time_now = time( NULL ); tm_now = localtime( &time_now ); snprintf( buf, sizeof(buf), "%s[%d/%d/%d %02d:%02d] ", YAHOO_COLOR_BLACK, tm_now->tm_mon + 1, tm_now->tm_mday, tm_now->tm_year + 1900, tm_now->tm_hour, tm_now->tm_min ); append_to_textbox_color( chat_window, NULL, buf ); } if ( strcasecmp( tmp, ymsg_sess->user )) { snprintf( buf, sizeof(buf), "%s%s%s%s%s", YAHOO_STYLE_BOLDON, ( highlight_friends && find_friend(tmp)) ? YAHOO_COLOR_GREEN : YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK, YAHOO_STYLE_BOLDOFF ); } else { /* this never really happens, we don't recv our comments */ snprintf( buf, sizeof(buf), "%s%s%s%s%s", YAHOO_STYLE_BOLDON, YAHOO_COLOR_BLUE, tmp, YAHOO_COLOR_BLACK, YAHOO_STYLE_BOLDOFF ); } if ( ! strcmp( ymsg9_field( "124"), "1" )) my_strncat( buf, ": ", sizeof(buf)); else my_strncat( buf, " ", sizeof(buf)); append_to_textbox_color( chat_window, NULL, buf ); if ( ! strcmp( ymsg9_field( "124"), "1" )) { snprintf( buf, sizeof(buf), "%s%s%s\n", YAHOO_COLOR_BLACK, tmp2, ATTR_RESET ); real_show_colors = show_colors; append_to_textbox( chat_window, NULL, buf ); real_show_colors = 1; } else { snprintf( buf, sizeof(buf), "%s%s%s\n", YAHOO_COLOR_PURPLE, tmp2, ATTR_RESET ); /* check for status change */ if ( ! strncasecmp( tmp2, "is away ", 8 )) { chatter_list_status( tmp, pixmap_status_away, "AW" ); } else if ( ! strncasecmp( tmp2, "is back", 7 )) { chatter_list_status( tmp, pixmap_status_here, "" ); } append_to_textbox( chat_window, NULL, buf ); } break; case YMSG9_JOIN: /* fixme, need to verify what exactly constitutes a join pkt */ strcpy( tmp, ymsg9_field( "126" )); /* dunno what */ strcpy( tmp2, ymsg9_field( "104" )); /* room name */ if (( strcmp( tmp, "" )) || ( ! strcmp( tmp2, "" ))) { /* I just joined the room, so get userlist */ if ( strcmp( ymsg9_field( "104" ), "" )) { gtk_statusbar_pop( GTK_STATUSBAR(chat_status), st_cid ); snprintf( buf, sizeof(buf), "Current Room: %s", ymsg9_field( "104" )); gtk_statusbar_push( GTK_STATUSBAR(chat_status), st_cid, buf ); my_strncpy( ymsg_sess->room, ymsg9_field( "104" ), YMSG9_ROOM_SIZE); snprintf( buf, sizeof(buf), "You are now in %s%s%s\n", YAHOO_COLOR_BLUE, ymsg9_field( "104" ), ATTR_RESET ); if ( strcmp( ymsg9_field( "105" ), "" )) { my_strncat( buf, YAHOO_COLOR_CYAN, sizeof(buf)); my_strncat( buf, ymsg9_field( "105" ), sizeof(buf)); my_strncat( buf, ATTR_RESET, sizeof(buf)); my_strncat( buf, "\n", sizeof(buf)); } } strcpy( tmp, ymsg9_field( "109" )); src = tmp; ptr = tmp2; while( *src ) { *ptr = *(src++); if ( *ptr == ',' ) { ptr++; *ptr = ' '; } ptr++; } *ptr = '\0'; if ( strcmp( ymsg9_field( "104" ), "" )) { my_strncat( buf, "You see here: ", sizeof(buf)); } else { if ( tmp[0] == '\0' ) { return; } my_strncpy( buf, "And also: ", sizeof(buf)); } my_strncat( buf, tmp2, sizeof(buf)); my_strncat( buf, "\n", sizeof(buf)); append_to_textbox( chat_window, NULL, buf ); if ( strcmp( ymsg9_field( "104" ), "" )) { chatter_list_populate( ymsg9_field( "109" ), 1 ); } else { chatter_list_populate( ymsg9_field( "109" ), 0 ); } /* little debugging code for showing capabilities */ /* strcpy( tmp, ymsg9_field( "113" )); strcpy( tmp2, ymsg9_field( "109" )); ptr = tmp; src = tmp2; while( src ) { end = strchr( src, ',' ); if ( end ) { *end = '\0'; end++; } end = strchr( ptr, ',' ); if ( end ) { *end = '\0'; end++; } fprintf( stderr, "%-20.20s = %x\n", src, atoi( ptr )); fflush( stderr ); if ( ! end ) { src = NULL; } else { src = src + strlen( src ) + 1; ptr = ptr + strlen( ptr ) + 1; } } */ } else if (( ! strcmp( ymsg9_field( "108" ), "1" )) && ( strcasecmp( ymsg9_field( "109" ), ymsg_sess->user ))) { /* someone else joined the room while I'm in there */ strcpy( tmp, ymsg9_field( "109" )); chatter_list_add( tmp ); /* keep track of user enters for auto-ignore/mute */ count = set_last_comment( tmp, "Entered Room" ); if (( ignore_on_mults ) && ( count > ignore_on_mults ) && ( ! ignore_check( tmp ))) { ignore_toggle( tmp ); snprintf( buf, sizeof(buf), "Gyach - auto-ignored %s%s%s, entered/left " "room %d times without commenting\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK, count ); append_to_textbox( chat_window, NULL, buf ); } else if (( mute_on_mults ) && ( count > mute_on_mults ) && ( ! mute_check( tmp ))) { mute_toggle( tmp ); snprintf( buf, sizeof(buf), "Gyach - auto-muted %s%s%s, entered/left " "room %d times without commenting\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK, count ); append_to_textbox( chat_window, NULL, buf ); } /* don't do this for now because we don't check leave msgs if (( suppress_mult ) && ( count > 1 )) { return; } */ if (( ! ignore_check( tmp )) && ( ! mute_check( tmp )) && ( show_enters )) { snprintf( buf, sizeof(buf), "%s%s %senters%s the room\n", YAHOO_COLOR_BLUE, tmp, YAHOO_COLOR_GREEN, YAHOO_COLOR_BLACK ); append_to_textbox( chat_window, NULL, buf ); } } break; case YMSG9_EXIT: if ( strcasecmp( ymsg_sess->user, ymsg9_field( "109"))) { /* someone else left */ strcpy( tmp, ymsg9_field( "109" )); chatter_list_remove( tmp ); if (( ! ignore_check( tmp )) && ( ! mute_check( tmp )) && ( show_enters )) { snprintf( buf, sizeof(buf), "%s%s %sleaves%s the room\n", YAHOO_COLOR_BLUE, tmp, YAHOO_COLOR_GREEN, YAHOO_COLOR_BLACK ); append_to_textbox( chat_window, NULL, buf ); } } else { /* packet that shows up when I leave */ } break; case YMSG9_PM: case YMSG9_PM_RECV: strcpy( tmp, ymsg9_field( "4" )); strcpy( tmp2, ymsg9_field( "14" )); /* don't think we should get any of these, but just in cas */ if ( ! strcmp( ymsg9_field( "49" ), "TYPING" )) { return; } /* if 10 is set that is the user's status so ignore for now */ if ( strcmp( ymsg9_field( "10" ), "" )) { return; } if ( ignore_check( tmp )) { return; } if ( mute_check( tmp )) { return; } /* check the fields determining who to accept PMs from */ accept_pm = 0; if (( pm_from_all ) || (( pm_from_users ) && ( find_user_row( tmp ) >= 0 )) || (( pm_from_friends ) && ( find_friend( tmp )))) { accept_pm = 1; } ptr = get_last_comment( tmp ); if (( first_post_is_pm ) && ( ! find_friend( tmp )) && (( ptr == NULL ) || ( !strcmp( ptr, "Entered Room" )))) { if ( ! ignore_check( tmp )) { ignore_toggle( tmp ); } snprintf( buf, sizeof(buf), "Gyach - auto-ignored %s%s%s, first " "post was PM: '%s'\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK, tmp2 ); append_to_textbox( chat_window, NULL, buf ); snprintf( buf, sizeof(buf), "/tell %s Automated Response: sorry this " "user does not accept PMs from other users not " "on their friend list or in their current room.", tmp ); chat_command( buf ); return; } if (( url_from_nonroom_user ) && (( strstr( tmp2, "http://" )) || ( strstr( tmp2, "ftp://" )) || ( strstr( tmp2, " www." ))) && ( ! find_friend( tmp )) && ( find_user_row( tmp )) < 0 ) { if ( ! ignore_check( tmp )) { ignore_toggle( tmp ); } snprintf( buf, sizeof(buf), "Gyach - auto-ignored %s%s%s, URL in " "PM from user not in room: '%s'\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK, tmp2 ); append_to_textbox( chat_window, NULL, buf ); snprintf( buf, sizeof(buf), "/tell %s Automated Response: sorry this " "user does not accept URLs from other users not " "on their friend list or in their current room.", tmp ); chat_command( buf ); return; } if ( ! accept_pm ) { if ( find_friend( tmp )) { snprintf( buf, sizeof(buf), "Ignored PM from Friend (%s%s%s)\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK ); append_to_textbox( chat_window, NULL, buf ); } /* possibly enable this code sometime. else if ( find_user_row( tmp ) >= 0 ) { snprintf( buf, sizeof(buf), "Ignored PM from User in Room (%s%s%s)\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK ); append_to_textbox( chat_window, NULL, buf ); } */ return; } if (( ptr = auto_ignore_check( tmp2 )) != NULL ) { if ( ! ignore_check( tmp )) { ignore_toggle( tmp ); } else { return; } snprintf( buf, sizeof(buf), "Gyach - auto-ignored %s%s%s, regex '%s'\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK, ptr ); append_to_textbox( chat_window, NULL, buf ); if ( ! disp_auto_ignored ) { return; } } if (( ! pm_in_sep_windows ) || ( ignore_check( tmp ))) { if ( chat_timestamp ) { time_now = time( NULL ); tm_now = localtime( &time_now ); snprintf( buf, sizeof(buf), "%s[%d/%d/%d %02d:%02d] ", YAHOO_COLOR_BLACK, tm_now->tm_mon + 1, tm_now->tm_mday, tm_now->tm_year + 1900, tm_now->tm_hour, tm_now->tm_min ); append_to_textbox_color( chat_window, NULL, buf ); } snprintf( buf, sizeof(buf), "%s%s%s%s%s %s%s%s\n", YAHOO_COLOR_RED, YAHOO_STYLE_BOLDON, tmp, YAHOO_COLOR_BLACK, YAHOO_STYLE_BOLDOFF, YAHOO_COLOR_BLUE, YAHOO_STYLE_BOLDON, ymsg_sess->user, YAHOO_COLOR_BLACK, YAHOO_STYLE_BOLDOFF, YAHOO_STYLE_BOLDON, tmp2, YAHOO_STYLE_BOLDOFF ); append_to_textbox_color( chat_window, NULL, buf ); } else { /* here we would send to a private pm session */ /* duplicate to both for now for testing */ if (( pm_lptr = find_pm_session( tmp )) != NULL ) { pm_sess = pm_lptr->data; } else { /* open a new window if one doesn't exist already */ pm_sess = (PM_SESSION *)malloc( sizeof( PM_SESSION )); pm_sess->pm_window = create_pm_session(); pm_sess->pm_text = lookup_widget( pm_sess->pm_window, "pms_text" ); pm_sess->pm_user = strdup( tmp ); pm_sess->typing = 0; #ifdef USE_GTK2 gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(pm_sess->pm_text), GTK_WRAP_WORD ); text_buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(pm_sess->pm_text)); gtk_text_buffer_get_end_iter( text_buffer, &end_iter ); gtk_text_buffer_create_mark( text_buffer, "end_mark", &end_iter, 0 ); #endif snprintf( buf, sizeof(buf), "* %s - Gyach", tmp ); gtk_window_set_title( GTK_WINDOW(pm_sess->pm_window), buf ); pm_list = g_list_append( pm_list, pm_sess ); /* setup the callback for url highlighting */ gtk_signal_connect_after (GTK_OBJECT (pm_sess->pm_text), "motion_notify_event", GTK_SIGNAL_FUNC(chat_motion_notify), NULL); GTK_WIDGET_UNSET_FLAGS( GTK_WIDGET(pm_sess->pm_text), GTK_CAN_FOCUS); gtk_widget_set_events( GTK_WIDGET(pm_sess->pm_text), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK ); } gtk_widget_show( pm_sess->pm_window ); if ( auto_raise_pm ) { gdk_window_raise( pm_sess->pm_window->window ); } if ( chat_timestamp_pm ) { time_now = time( NULL ); tm_now = localtime( &time_now ); snprintf( buf, sizeof(buf), "%s[%d/%d/%d %02d:%02d] ", YAHOO_COLOR_BLACK, tm_now->tm_mon + 1, tm_now->tm_mday, tm_now->tm_year + 1900, tm_now->tm_hour, tm_now->tm_min ); append_to_textbox_color( pm_sess->pm_window, pm_sess->pm_text, buf ); } snprintf( buf, sizeof(buf), "%s%s%s%s%s: ", YAHOO_COLOR_RED, YAHOO_STYLE_BOLDON, tmp, YAHOO_COLOR_BLACK, YAHOO_STYLE_BOLDOFF ); append_to_textbox_color( pm_sess->pm_window, pm_sess->pm_text, buf ); real_show_colors = show_colors; snprintf( buf, sizeof(buf), "%s\n", tmp2 ); append_to_textbox_color( pm_sess->pm_window, pm_sess->pm_text, buf ); real_show_colors = 1; snprintf( buf, sizeof(buf), "* %s - Gyach", tmp ); gtk_window_set_title( GTK_WINDOW(pm_sess->pm_window), buf ); } /* auto-reply if necessary */ if (( my_status ) && ( auto_reply_when_away ) && ( ! ignore_check( tmp )) && ( auto_reply_msg )) { ymsg9_pm( ymsg_sess, tmp, auto_reply_msg ); } break; case YMSG9_NOTIFY: strcpy( tmp, ymsg9_field( "4" )); /* message that tell us the user is typing to us or stopped */ /* typing is stored in '49' field */ if ( ! strcmp( ymsg9_field( "49" ), "TYPING" )) { /* this code broken right now, we don't seem to receive */ /* the typing start messages */ if (( pm_lptr = find_pm_session( tmp )) != NULL ) { pm_sess = pm_lptr->data; if ( GTK_WINDOW(pm_sess->pm_window)->title[0] == '*' ) { strcpy( buf, "* " ); } else { buf[0] = '\0'; } my_strncat( buf, tmp, sizeof(buf)); if ( ! strcmp( ymsg9_field( "13" ), "1" )) { my_strncat( buf, " [TYPING]", sizeof(buf)); } my_strncat( buf, " - Gyach", sizeof(buf)); gtk_window_set_title( GTK_WINDOW(pm_sess->pm_window), buf ); } return; } break; case YMSG9_BUDDY_ON: if ( ! strcmp( ymsg9_field( "7" ), "" )) { return; } if ( strcmp( ymsg9_field( "8" ), "" )) { /* initial buddy list of people online */ strcpy( buf, ymsg9_field( "7")); ptr = buf; last = 0; while( ptr ) { end = strchr( ptr, ',' ); if ( end ) { *end = '\0'; } else { last = 1; } add_online_friend( ptr ); if ( last ) { ptr = NULL; } else { ptr = end + 1; } } show_friends(); return; } strcpy( tmp, ymsg9_field( "7" )); if ( ! strcasecmp( tmp, ymsg_sess->user )) { return; } snprintf( buf, sizeof(buf), "%sBuddy:%s %s%s%s has logged ON.\n", YAHOO_COLOR_BLUE, YAHOO_COLOR_BLACK, YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK ); display = 1; if ( find_online_friend( tmp )) { display = 0; } else { add_online_friend( tmp ); } if ( display ) { append_to_textbox_color( chat_window, NULL, buf ); if (( pm_lptr = find_pm_session( tmp )) != NULL ) { pm_sess = pm_lptr->data; append_to_textbox_color( pm_sess->pm_window, pm_sess->pm_text, buf ); } } break; case YMSG9_BUDDY_OFF: if ( ! ymsg_sess->pkt.size ) { ymsg_sess->pkt.type = YMSG9_LOGOUT; show_yahoo_packet(); } if ( ! strcmp( ymsg9_field( "7" ), "" )) { return; } strcpy( tmp, ymsg9_field( "7")); if ( ! strcasecmp( tmp, ymsg_sess->user )) { return; } snprintf( buf, sizeof(buf), "%sBuddy:%s %s%s%s has logged OFF.\n", YAHOO_COLOR_BLUE, YAHOO_COLOR_BLACK, YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK ); display = 1; if ( find_online_friend( tmp )) { remove_online_friend( tmp ); } else { display = 0; } if ( display ) { append_to_textbox_color( chat_window, NULL, buf ); if (( pm_lptr = find_pm_session( tmp )) != NULL ) { pm_sess = pm_lptr->data; append_to_textbox_color( pm_sess->pm_window, pm_sess->pm_text, buf ); } } break; case YMSG9_INVITE: strcpy( tmp, ymsg9_field( "119" )); strcpy( tmp2, ymsg9_field( "104" )); if ( ! strcmp( tmp, "" )) { snprintf( buf, sizeof(buf), "%sUser has been invited to %s%s\n", YAHOO_COLOR_PURPLE, ymsg_sess->room, YAHOO_COLOR_BLACK ); append_to_textbox_color( chat_window, NULL, buf ); return; } /* keep track of user enters for auto-ignore/mute */ snprintf( tmp3, sizeof(tmp3), "Invite: %s", tmp2 ); count = set_last_comment( tmp, tmp3 ); if (( ignore_on_mults ) && ( count > ignore_on_mults ) && ( ! ignore_check( tmp ))) { ignore_toggle( tmp ); snprintf( buf, sizeof(buf), "Gyach - auto-ignored %s%s%s, invited you to " "'%s' room %d times in a row.\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK, tmp2, count ); append_to_textbox( chat_window, NULL, buf ); } else if (( mute_on_mults ) && ( count > mute_on_mults ) && ( ! mute_check( tmp ))) { mute_toggle( tmp ); snprintf( buf, sizeof(buf), "Gyach - auto-muted %s%s%s, invited you to " "'%s' room %d times in a row.\n", YAHOO_COLOR_RED, tmp, YAHOO_COLOR_BLACK, tmp2, count ); append_to_textbox( chat_window, NULL, buf ); } if (( suppress_mult ) && ( count > 1 )) { return; } snprintf( buf, sizeof(buf), "%sYou have been invited to (%s%s%s%s%s) by %s%s%s%s%s\n", YAHOO_COLOR_PURPLE, YAHOO_COLOR_RED, YAHOO_STYLE_BOLDON, tmp2, YAHOO_STYLE_BOLDOFF, YAHOO_COLOR_PURPLE, YAHOO_COLOR_BLUE, YAHOO_STYLE_BOLDON, tmp, YAHOO_STYLE_BOLDOFF, YAHOO_COLOR_BLACK ); if ((( ! ignore_check( tmp )) && ( ! mute_check( tmp ))) || ( disp_auto_ignored )) { append_to_textbox_color( chat_window, NULL, buf ); } break; case YMSG9_FILETRANSFER: strcpy( tmp, ymsg9_field( "4" )); if ( ! strcmp( tmp, "FILE_TRANSFER_SYSTEM" )) { /* we sent a file */ strcpy( tmp2, ymsg9_field( "14" )); snprintf( buf, sizeof(buf), "%sFILE:%s %s\n", YAHOO_COLOR_GREEN, YAHOO_COLOR_BLACK, tmp2 ); append_to_textbox_color( chat_window, NULL, buf ); } else { /* we received a file */ strcpy( tmp2, ymsg9_field( "20" )); strcpy( tmp3, ymsg9_field( "14" )); exp_time = atoi( ymsg9_field( "38" )); snprintf( buf, sizeof(buf), "%sFILE:%s %s%s has sent you a file with " "the message: '%s'.\n" " %s\n" " It is available until: %s", YAHOO_COLOR_GREEN, YAHOO_COLOR_BLUE, tmp, YAHOO_COLOR_BLACK, tmp3, tmp2, ctime( &exp_time )); append_to_textbox_color( chat_window, NULL, buf ); } break; case YMSG9_LOGOUT: close( ymsg_sess->sock ); ymsg_sess->sock = -1; logged_in = 0; set_menu_connected( 0 ); gtk_clist_clear(GTK_CLIST(chat_users)); if ( ymsg_sess->io_callback_tag != 0) { gdk_input_remove( ymsg_sess->io_callback_tag ); ymsg_sess->io_callback_tag = 0; } if ( ymsg_sess->ping_callback_tag != 0) { gdk_input_remove( ymsg_sess->ping_callback_tag ); ymsg_sess->ping_callback_tag = 0; } time_now = time(NULL); hours = (int)(( time_now - connect_time ) / 3600); minutes = (int)(( time_now - connect_time ) % 3600 ) / 60; seconds = (int)(( time_now - connect_time ) % 60 ); connect_time = 0; /* show user that we aren't logged in anymore */ snprintf( buf, sizeof(buf), "%s%s%s%s%s Online for %d:%02d:%02d.\n\n", YAHOO_COLOR_BLUE, YAHOO_STYLE_BOLDON, "Disconnected from Chat!", YAHOO_STYLE_BOLDOFF, YAHOO_COLOR_BLACK, hours, minutes, seconds ); append_to_textbox_color( chat_window, NULL, buf ); gtk_statusbar_pop( GTK_STATUSBAR(chat_status), st_cid ); gtk_statusbar_push( GTK_STATUSBAR(chat_status), st_cid, "Not currently connected to chat..." ); if (( auto_reconnect ) && ( minutes > 0 )) { login_to_yahoo_chat(); } break; } } int main( int argc, char **argv ) { char gtkrc_filename[1024]; struct stat gtkrc_stat; #ifdef OS_WINDOWS struct timeval tv; fd_set set; int ret; #endif DBG( 1, "Gyach v%s\n", VERSION ); DBG( 1, "%s\n", GYACH_URL ); DBG( 1, "Debug Level set to: %d\n", DBG_LEVEL ); memset( ymsg_sess ,0 ,sizeof(YMSG9_SESSION)); ymsg_sess->sock = -1; ymsg_sess->suppress_dup_packets = 1; gtk_set_locale(); gtk_init( &argc, &argv ); snprintf( gtkrc_filename, sizeof(gtkrc_filename), "%s/gtkrc", GYACH_CFG_DIR ); if ( ! stat( gtkrc_filename, >krc_stat )) { gtk_rc_parse( gtkrc_filename ); } gyach_init(); chat_window = build_chat_window(); gtk_widget_show( chat_window ); login_window = build_login_window(); if ( ! auto_login ) { gtk_widget_show( login_window ); } else { login_to_yahoo_chat(); } gdk_threads_enter(); #ifdef OS_WINDOWS /* since we can't use an io callback with win32, we have to do a */ /* main loop ourselves and check the socket with a select(). */ while( ! ymsg_sess->quit ) { while( gtk_events_pending()) { gtk_main_iteration(); } /* now check for input on our socket */ FD_ZERO( &set ); if ( ymsg_sess->sock != -1 ) FD_SET( ymsg_sess->sock, &set ); tv.tv_sec = 0; tv.tv_usec = 50000; ret = select( ymsg_sess->sock + 1, &set, NULL, NULL, &tv ); if ( ret ) { if ( ymsg9_recv_data( ymsg_sess )) { show_yahoo_packet(); } } } #else gtk_main(); #endif return( 0 ); }