[C++] 飞信源代码(c++) →→→→→进入此内容的聊天室

来自 , 2021-02-18, 写在 C++, 查看 146 次.
URL http://www.code666.cn/view/04df4d43
  1. /***************************************************************************
  2.  *   Copyright (C) 2010 by lwp                                             *
  3.  *   levin108@gmail.com                                                    *
  4.  *                                                                         *
  5.  *   This program is free software; you can redistribute it and/or modify  *
  6.  *   it under the terms of the GNU General Public License as published by  *
  7.  *   the Free Software Foundation; either version 2 of the License, or     *
  8.  *   (at your option) any later version.                                   *
  9.  *                                                                         *
  10.  *   This program is distributed in the hope that it will be useful,       *
  11.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  12.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  13.  *   GNU General Public License for more details.                          *
  14.  *                                                                         *
  15.  *   You should have received a copy of the GNU General Public License     *
  16.  *   along with this program; if not, write to the                         *
  17.  *   Free Software Foundation, Inc.,                                       *
  18.  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  19.  ***************************************************************************/
  20.  
  21. #include "fx_include.h"
  22. #ifdef USE_GSTREAMER
  23. #include <gst/gst.h>
  24. #endif
  25. #include <glib/gi18n.h>
  26. #include <sys/select.h>
  27. #include <locale.h>
  28. #include <glib.h>
  29.  
  30. fd_set  fd_read;
  31. gint presence_count = 0;
  32. gint window_pos_x;
  33. gint window_pos_y;
  34. gint window_pos_x_old = 0;
  35. gint window_pos_y_old = 0;
  36. gint start_popup_presence = 0;
  37. extern struct unacked_list *unackedlist;
  38. GStaticMutex mutex = G_STATIC_MUTEX_INIT;
  39. GdkScreen *current_screen;
  40.  
  41. static void fx_main_process_pggetgroupinfo(FxMain *fxmain , const gchar *sipmsg);
  42. static void fx_main_process_pgpresencechanged(FxMain *fxmain , const gchar *sipmsg);
  43. static gboolean key_press_func(GtkWidget *widget , GdkEventKey *event
  44.                                , gpointer data);
  45.  
  46. FxMain *fx_main_new() {
  47.     FxMain *fxmain = (FxMain *)malloc(sizeof(FxMain));
  48.  
  49.     memset(fxmain , 0 , sizeof(FxMain));
  50.     fxmain->clist = fx_list_new(NULL);
  51.     fxmain->mlist = fx_list_new(NULL);
  52.     fxmain->slist = fx_list_new(NULL);
  53.     fxmain->tlist = fx_list_new(NULL);
  54.     fxmain->shlist = fx_list_new(NULL);
  55.     fxmain->pglist = fx_list_new(NULL);
  56.     return fxmain;
  57. }
  58.  
  59. #if 0
  60. static void fx_main_position_func(GtkWidget *UNUSED(widget) , GdkEventConfigure *event ,
  61.                                   gpointer UNUSED(user_data)) {
  62.     window_pos_x = event->x;
  63.     window_pos_y = event->y;
  64. }
  65. #endif
  66.  
  67. void fx_main_initialize(FxMain *fxmain) {
  68.     int window_width , window_height;
  69.     Config    *config;
  70.  
  71.     fxmain->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  72.     gtk_widget_set_name(fxmain->window , "mainwindow");
  73.     gtk_window_set_title(GTK_WINDOW(fxmain->window) , "OpenFetion");
  74.  
  75.  
  76.     current_screen = gdk_screen_get_default();
  77.     config = fetion_config_new();
  78.     fetion_config_load_size(config);
  79.     if(config->window_width == 0) {
  80.         window_width = gdk_screen_get_width(current_screen);
  81.         window_height = gdk_screen_get_height(current_screen);
  82.         window_pos_x = window_width - WINDOW_WIDTH - 200;
  83.         window_pos_y = (window_height - WINDOW_HEIGHT) / 2;
  84.     } else {
  85.         window_pos_x = config->window_pos_x;
  86.         window_pos_y = config->window_pos_y;
  87.     }
  88.     fetion_config_free(config);
  89.  
  90.     gtk_window_move(GTK_WINDOW(fxmain->window) , window_pos_x , window_pos_y);
  91.     gtk_container_set_border_width(GTK_CONTAINER(fxmain->window) , 0);
  92.     g_signal_connect(G_OBJECT(fxmain->window)
  93.                      , "delete-event"
  94.                      , G_CALLBACK(fx_main_delete)
  95.                      , fxmain);
  96.     g_signal_connect(G_OBJECT(fxmain->window)
  97.                      , "key-press-event"
  98.                      , G_CALLBACK(key_press_func)
  99.                      , fxmain);
  100.     g_signal_connect(G_OBJECT(fxmain->window)
  101.                      , "destroy"
  102.                      , G_CALLBACK(fx_main_destroy)
  103.                      , fxmain);
  104.     g_signal_connect(G_OBJECT(fxmain->window)
  105.                      , "window-state-event"
  106.                      , G_CALLBACK(fx_main_window_state_func)
  107.                      , fxmain);
  108. #if 0
  109.     g_signal_connect(G_OBJECT(fxmain->window)
  110.                      , "configure-event"
  111.                      , G_CALLBACK(fx_main_position_func)
  112.                      , NULL);
  113. #endif
  114.  
  115.     gtk_window_set_default_size(
  116.         GTK_WINDOW(fxmain->window),
  117.         WINDOW_WIDTH , WINDOW_HEIGHT);
  118.     GdkPixbuf *icon = gdk_pixbuf_new_from_file_at_size(
  119.                           SKIN_DIR"fetion.svg" , 48 , 48 , NULL);
  120.     gtk_window_set_icon(GTK_WINDOW(fxmain->window) , icon);
  121.     fxmain->trayIcon = gtk_status_icon_new_from_file(
  122.                            SKIN_DIR"offline.svg");
  123.     gtk_status_icon_set_tooltip(fxmain->trayIcon, "OpenFetion");
  124. #ifdef USE_LIBNOTIFY
  125.     fxmain->notify = notify_notification_new_with_status_icon("welcome"
  126.                      , "" , NULL , fxmain->trayIcon);
  127.     notify_notification_set_timeout(fxmain->notify , 2500);
  128. #endif
  129.  
  130.     fxmain->iconConnectId = g_signal_connect(
  131.                                 GTK_STATUS_ICON(fxmain->trayIcon),
  132.                                 "activate",
  133.                                 GTK_SIGNAL_FUNC(fx_main_tray_activate_func),
  134.                                 fxmain);
  135.     g_signal_connect(GTK_STATUS_ICON(fxmain->trayIcon),
  136.                      "popup-menu",
  137.                      GTK_SIGNAL_FUNC(fx_main_tray_popmenu_func),
  138.                      fxmain);
  139.  
  140.     fxmain->mainbox = gtk_vbox_new(FALSE , 4);
  141.     gtk_container_add(GTK_CONTAINER(fxmain->window) , fxmain->mainbox);
  142.  
  143.     fxmain->loginPanel = fx_login_new();
  144.     fx_login_initialize(fxmain);
  145.     gtk_widget_show_all(fxmain->window);
  146.  
  147.     gdk_threads_enter();
  148.     gtk_main();
  149.     gdk_threads_leave();
  150. }
  151.  
  152. void fx_main_free(FxMain *fxmain) {
  153.     if(fxmain->user != NULL)
  154.         fetion_user_free(fxmain->user);
  155.     free(fxmain);
  156. }
  157.  
  158. void fx_main_set_user(FxMain *fxmain , User *user) {
  159.     fxmain->user = user;
  160. }
  161.  
  162. void fx_main_history_init(FxMain *fxmain) {
  163.     fxmain->history = fetion_history_new(fxmain->user);
  164. }
  165.  
  166. void update() {
  167.     g_usleep(1);
  168.     while(gtk_events_pending()) {
  169.         gtk_main_iteration();
  170.     }
  171. }
  172. TimeOutArgs *timeout_args_new(FxMain *fxmain , FetionSip *sip , const gchar *sipuri) {
  173.     TimeOutArgs *args = (TimeOutArgs *)malloc(sizeof(TimeOutArgs));
  174.     memset(args , 0 , sizeof(TimeOutArgs));
  175.     args->fxmain = fxmain;
  176.     args->sip = sip;
  177.     args->terminated = FALSE;
  178.     strcpy(args->sipuri , sipuri);
  179.     return args;
  180. }
  181. GtkWidget *fx_main_create_menu(const gchar *name
  182.                                , const gchar *iconpath
  183.                                , GtkWidget *parent
  184.                                , void (*func)(GtkWidget *item , gpointer data)
  185.                                , gpointer data
  186.                               ) {
  187.     GtkWidget *item = gtk_image_menu_item_new_with_label(name);
  188.     GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_size(iconpath , 16 , 16 , NULL);
  189.     GtkWidget *img = gtk_image_new_from_pixbuf(pb);
  190.     g_object_unref(pb);
  191.     gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item) , img);
  192.     gtk_menu_shell_append(GTK_MENU_SHELL(parent) , item);
  193.     if(func != NULL)
  194.         g_signal_connect(item , "activate" , G_CALLBACK(func) , data);
  195.     return item;
  196. }
  197.  
  198. GtkWidget *fx_main_create_menu1(const gchar *name
  199.                                 , const gchar *stockid
  200.                                 , GtkWidget *parent
  201.                                 , void (*func)(GtkWidget *item , gpointer data)
  202.                                 , gpointer data
  203.                                ) {
  204.     GtkWidget *item = gtk_image_menu_item_new_with_label(name);
  205. #if 0
  206.     GtkWidget *img = gtk_image_new_from_stock(stockid , GTK_ICON_SIZE_MENU);
  207.     gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item) , img);
  208. #endif
  209.     gtk_menu_shell_append(GTK_MENU_SHELL(parent) , item);
  210.     if(func != NULL)
  211.         g_signal_connect(item , "activate" , G_CALLBACK(func) , data);
  212.     return item;
  213. }
  214.  
  215. void fx_main_process_notification(FxMain *fxmain , const gchar *sipmsg) {
  216.     gint   event;
  217.     gint   notification_type;
  218.     gchar  *xml;
  219.  
  220.     fetion_sip_parse_notification(sipmsg , &notification_type , &event , &xml);
  221.     g_usleep(1);
  222.     switch(notification_type) {
  223.     case NOTIFICATION_TYPE_PRESENCE:
  224.         switch(event) {
  225.         case NOTIFICATION_EVENT_PRESENCECHANGED :
  226.             fx_main_process_presence(fxmain , xml);
  227.             break;
  228.         default:
  229.             break;
  230.         }
  231.     case NOTIFICATION_TYPE_CONVERSATION :
  232.         if(event == NOTIFICATION_EVENT_USERLEFT) {
  233.             fx_main_process_user_left(fxmain , sipmsg);
  234.             break;
  235.         }
  236.         break;
  237.     case NOTIFICATION_TYPE_REGISTRATION :
  238.         if(event == NOTIFICATION_EVENT_DEREGISTRATION) {
  239.             fx_main_process_deregistration(fxmain);
  240.             break;
  241.         }
  242.         break;
  243.     case NOTIFICATION_TYPE_SYNCUSERINFO :
  244.         if(event == NOTIFICATION_EVENT_SYNCUSERINFO) {
  245.             fx_main_process_syncuserinfo(fxmain , xml);
  246.             break;
  247.         }
  248.         break;
  249.     case NOTIFICATION_TYPE_CONTACT :
  250.         if(event == NOTIFICATION_EVENT_ADDBUDDYAPPLICATION) {
  251.             fx_main_process_addbuddyapplication(fxmain , sipmsg);
  252.             break;
  253.         }
  254.         break;
  255.     case NOTIFICATION_TYPE_PGGROUP :
  256.         if(event == NOTIFICATION_EVENT_PGGETGROUPINFO) {
  257.             fx_main_process_pggetgroupinfo(fxmain , sipmsg);
  258.             break;
  259.         }
  260.         if(event == NOTIFICATION_EVENT_PRESENCECHANGED) {
  261.             fx_main_process_pgpresencechanged(fxmain , sipmsg);
  262.             break;
  263.         }
  264.         break;
  265.     default:
  266.         break;
  267.     }
  268.     g_free(xml);
  269.  
  270. }
  271.  
  272. static void *update_data(void *data) {
  273.     FxMain *fxmain = (FxMain *)data;
  274.     User   *user = fxmain->user;
  275.  
  276.     fetion_user_save(user);
  277.     fetion_contact_save(user);
  278.     fx_tree_update_portrait(data);
  279.  
  280.     return NULL;
  281. }
  282.  
  283. static void popup_online_notify(FxMain *fxmain, Contact *contact) {
  284. #ifdef USE_LIBNOTIFY
  285.     gchar         notifySummary[256];
  286.     gchar         notifyText[1024];
  287.     gchar         iconPath[256];
  288.     GdkPixbuf    *pixbuf;
  289.     Config       *config;
  290.  
  291.     config = fxmain->user->config;
  292.  
  293.     if(start_popup_presence &&
  294.             presence_count > fxmain->user->contactCount &&
  295.             config->onlineNotify == ONLINE_NOTIFY_ENABLE) {
  296.  
  297.         sprintf(iconPath , "%s/%s.jpg",
  298.                 config->iconPath , contact->sId);
  299.         sprintf(notifySummary,
  300.                 _("%s , now ONLINE") , contact->nickname);
  301.         sprintf(notifyText ,
  302.                 _("Phone Number: %s\n"
  303.                   "Fetion Number: %s\n"
  304.                   "Signature: %s")
  305.                 , contact->mobileno == NULL ||
  306.                 strlen(contact->mobileno) == 0 ?
  307.                 "未知" : contact->mobileno
  308.                 , contact->sId
  309.                 , contact->impression );
  310.         pixbuf = gdk_pixbuf_new_from_file_at_size(
  311.                      iconPath,
  312.                      NOTIFY_IMAGE_SIZE,
  313.                      NOTIFY_IMAGE_SIZE , NULL);
  314.         if(!pixbuf)
  315.             pixbuf = gdk_pixbuf_new_from_file_at_size(
  316.                          SKIN_DIR"fetion.svg",
  317.                          NOTIFY_IMAGE_SIZE,
  318.                          NOTIFY_IMAGE_SIZE , NULL);
  319.  
  320.         notify_notification_update(fxmain->notify , notifySummary
  321.                                    , notifyText , NULL);
  322.         notify_notification_set_icon_from_pixbuf(fxmain->notify , pixbuf);
  323.         notify_notification_show(fxmain->notify , NULL);
  324.         g_object_unref(pixbuf);
  325.     }
  326. #endif
  327. }
  328.  
  329. void fx_main_process_presence(FxMain *fxmain , const gchar *xml) {
  330.     gchar        *crc = NULL;
  331.     gchar        *name;
  332.     gint          oldstate , count;
  333.     Contact      *contactlist;
  334.     Contact      *contact;
  335.     User         *user = fxmain->user;
  336.     GtkWidget    *treeView = fxmain->mainPanel->treeView;
  337.     GtkTreeModel *model;
  338.     FxChat       *fxchat;
  339.     GtkTreeIter   iter;
  340.     GtkTreeIter   parentIter;
  341.  
  342.     contactlist = fetion_user_parse_presence_body(xml , user);
  343.     contact = contactlist;
  344.  
  345.     model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeView));
  346.     foreach_contactlist(contactlist , contact) {
  347.  
  348.         if(fx_tree_get_buddy_iter_by_userid(model , contact->userId , &iter) == -1)
  349.             continue;
  350.  
  351.         presence_count ++;
  352.  
  353.         /* all presence information has been pushed
  354.          * then start update local data and buddy portrait */
  355.         if(presence_count == user->contactCount)
  356.             g_thread_create(update_data, fxmain, FALSE, NULL);
  357.  
  358.         gtk_tree_model_get(model , &iter
  359.                            , B_CRC_COL    , &crc
  360.                            , B_STATE_COL  , &oldstate
  361.                            , -1);
  362.         gdk_threads_enter();
  363.         fxchat = fx_list_find_chat_by_sipuri(fxmain->clist , contact->sipuri);
  364.         if(oldstate > 0 && contact->state <= 0 && contact->serviceStatus == STATUS_NORMAL) {
  365.             gtk_tree_model_iter_parent(model , &parentIter , &iter);
  366.             gtk_tree_model_get(model , &parentIter
  367.                                , G_ONLINE_COUNT_COL     , &count
  368.                                , -1);
  369.             count --;
  370.             gtk_tree_store_set(GTK_TREE_STORE(model) , &parentIter
  371.                                , G_ONLINE_COUNT_COL     , count
  372.                                , -1);
  373.             fx_tree_move_to_the_last(model , &iter);
  374.         }
  375.         if(oldstate <= 0 && contact->state > 0 && contact->serviceStatus == STATUS_NORMAL) {
  376.             gtk_tree_model_iter_parent(model , &parentIter , &iter);
  377.             gtk_tree_model_get(model , &parentIter
  378.                                , G_ONLINE_COUNT_COL     , &count
  379.                                , -1);
  380.             count ++;
  381.             gtk_tree_store_set(GTK_TREE_STORE(model) , &parentIter
  382.                                , G_ONLINE_COUNT_COL     , count
  383.                                , -1);
  384.             fx_tree_move_to_the_last(model , &iter);
  385.             fx_tree_move_to_the_first(model , &iter);
  386.  
  387.             popup_online_notify(fxmain, contact);
  388.  
  389.         }
  390.         if(fxchat)
  391.             fxchat->state = contact->state;
  392.  
  393.         name = (contact->nickname == NULL || strlen(contact->localname) == 0) ?
  394.                contact->nickname : contact->localname;
  395.         gtk_tree_store_set(GTK_TREE_STORE(model) , &iter
  396.                            , B_NAME_COL            , g_markup_escape_text(name, -1)
  397.                            , B_SIPURI_COL                        , contact->sipuri
  398.                            , B_IMPRESSION_COL            , g_markup_escape_text(contact->impression, -1)
  399.                            , B_PHONENUM_COL              , contact->mobileno
  400.                            , B_USERID_COL                        , contact->userId
  401.                            , B_STATE_COL                         , contact->state
  402.                            , B_IDENTITY_COL              , contact->identity
  403.                            , B_DEVICE_COL                        , contact->devicetype
  404.                            , B_RELATIONSTATUS_COL  , contact->relationStatus
  405.                            , B_SERVICESTATUS_COL         , contact->serviceStatus
  406.                            , B_CARRIERSTATUS_COL   , contact->carrierStatus
  407.                            , B_CARRIER_COL               , contact->carrier
  408.                            , B_CRC_COL                   , contact->portraitCrc
  409.                            , B_IMAGE_CHANGED_COL         , crc == NULL ? IMAGE_CHANGED :
  410.                            (strcmp(crc , contact->portraitCrc) == 0 ? IMAGE_NOT_CHANGED : IMAGE_CHANGED)
  411.                            , -1);
  412.         g_free(crc);
  413.         gdk_threads_leave();
  414.     }
  415. }
  416.  
  417. static void process_system_message(const char *sipmsg) {
  418.  
  419.     gint     showonce;
  420.     gint     type;
  421.     gchar    *msg;
  422.     gchar    *url;
  423.     FxSysmsg *sysmsg;
  424.  
  425.     fetion_sip_parse_sysmsg(sipmsg , &type , &showonce
  426.                             , &msg , &url);
  427.  
  428.     if(type == 0) {
  429.         sysmsg = fx_sysmsg_new();
  430.         fx_sysmsg_initialize(sysmsg);
  431.         fx_sysmsg_bind(sysmsg , msg , url);
  432.         gtk_dialog_run(GTK_DIALOG(sysmsg->dialog));
  433.  
  434.         gtk_widget_destroy(sysmsg->dialog);
  435.         g_free(sysmsg);
  436.  
  437.     }
  438. }
  439.  
  440. static void process_group_message(FxMain *fxmain , Message *message) {
  441.     FxPGGroup     *fxpgcur;
  442.     FxPGGroup     *fxpg;
  443.     PGGroupMember *memcur;
  444.     FxList        *pglist;
  445.     FxList        *cur;
  446.     User          *user;
  447.     Config        *config;
  448.     GdkPixbuf     *pixbuf;
  449.     gchar         path[1024];
  450.     gchar         *sid;
  451.  
  452.     user = fxmain->user;
  453.     config = user->config;
  454.  
  455.     pglist = fxmain->pglist;
  456.  
  457.     foreach_list(pglist , cur) {
  458.         fxpgcur = (FxPGGroup *)(cur->data);
  459.         if(strcmp(fxpgcur->pggroup->pguri,
  460.                   message->pguri) == 0) {
  461.             fxpg = fxpgcur;
  462.             break;
  463.         }
  464.     }
  465.  
  466.     gdk_threads_enter();
  467.     if(fxpg == NULL || fxpg->hasFocus == CHAT_DIALOG_NOT_FOCUSED ) {
  468.         if(fxpg == NULL) {
  469.             if(config->autoPopup == AUTO_POPUP_ENABLE) {
  470.                 fxpg = pg_create_window(fxmain , message->pguri);
  471.                 foreach_pg_member(fxpg->pggroup->member , memcur) {
  472.                     if(strcmp(memcur->sipuri , message->sipuri) == 0)
  473.                         pg_add_message(fxpg , message->message
  474.                                        , &(message->sendtime) , memcur);
  475.                 }
  476.  
  477.             } else {
  478.                 cur = fx_list_new(message);
  479.                 fx_list_append(fxmain->mlist , cur);
  480.             }
  481.         } else {
  482.             foreach_pg_member(fxpg->pggroup->member , memcur) {
  483.                 if(strcmp(memcur->sipuri , message->sipuri) == 0)
  484.                     pg_add_message(fxpg , message->message , &(message->sendtime) , memcur);
  485.             }
  486.         }
  487.         sid = fetion_sip_get_pgid_by_sipuri(message->pguri);
  488.         snprintf(path , sizeof(path) - 1 , "%s/PG%s.jpg" , config->iconPath , sid);
  489.         g_free(sid);
  490.         pixbuf = gdk_pixbuf_new_from_file(path , NULL);
  491.         if(pixbuf == NULL)
  492.             pixbuf = gdk_pixbuf_new_from_file(SKIN_DIR"online.svg" , NULL);
  493.         gtk_status_icon_set_from_pixbuf(GTK_STATUS_ICON(fxmain->trayIcon) , pixbuf);
  494.         g_object_unref(pixbuf);
  495.         gtk_status_icon_set_blinking(GTK_STATUS_ICON(fxmain->trayIcon) , TRUE);
  496.         g_signal_handler_disconnect(fxmain->trayIcon , fxmain->iconConnectId);
  497.         fxmain->iconConnectId = g_signal_connect(G_OBJECT(fxmain->trayIcon)
  498.                                 , "activate"
  499.                                 , GTK_SIGNAL_FUNC(fx_main_message_func)
  500.                                 , fxmain);
  501.     } else {
  502.         foreach_pg_member(fxpg->pggroup->member , memcur) {
  503.             if(strcmp(memcur->sipuri , message->sipuri) == 0)
  504.                 pg_add_message(fxpg , message->message , &(message->sendtime) , memcur);
  505.         }
  506.     }
  507.     gdk_threads_leave();
  508.     if(config->isMute == MUTE_DISABLE)
  509.         fx_sound_play_file(RESOURCE_DIR"newmessage.wav");
  510. }
  511.  
  512. static void popup_msg_notify(FxMain *fxmain, Contact *senderContact, Message *msg) {
  513. #ifdef USE_LIBNOTIFY
  514.     Config    *config = fxmain->user->config;
  515.     GdkPixbuf *notifyIcon;
  516.     gchar     *senderSid;
  517.     gchar      iconPath[256];
  518.     gchar      notifySum[256];
  519.  
  520.     if(config->msgAlert == MSG_ALERT_ENABLE) {
  521.         if(senderContact) {
  522.             sprintf(iconPath, "%s/%s.jpg",
  523.                     config->iconPath, senderContact->sId);
  524.             senderSid = fetion_sip_get_sid_by_sipuri(msg->sipuri);
  525.             sprintf(notifySum, _("%s(%s) said:"),
  526.                     senderContact->nickname , senderContact->sId);
  527.             g_free(senderSid);
  528.  
  529.             notifyIcon = gdk_pixbuf_new_from_file_at_size(
  530.                              iconPath , 48 , 48 , NULL);
  531.             notify_notification_update(fxmain->notify,
  532.                                        notifySum, msg->message , NULL);
  533.  
  534.             if(!notifyIcon)
  535.                 notifyIcon = gdk_pixbuf_new_from_file_at_size(
  536.                                  SKIN_DIR"fetion.svg", 48, 48, NULL);
  537.  
  538.             notify_notification_set_icon_from_pixbuf(
  539.                 fxmain->notify , notifyIcon);
  540.             notify_notification_show(fxmain->notify , NULL);
  541.             g_object_unref(notifyIcon);
  542.         }
  543.     }
  544. #endif
  545. }
  546.  
  547. void fx_main_process_message(FxMain *fxmain , FetionSip *sip , const gchar *sipmsg) {
  548.     Message   *msg;
  549.     FxList    *clist;
  550.     FxList    *mitem;
  551.     FxChat    *fxchat;
  552.     User      *user;
  553.     Config    *config;
  554.     gchar      path[256];
  555.     gchar     *sid;
  556.     GdkPixbuf *pb;
  557.     Contact *senderContact;
  558.  
  559.     clist = fxmain->clist;
  560.     user = fxmain->user;
  561.     config = user->config;
  562.  
  563.     fetion_sip_parse_message(sip , sipmsg , &msg);
  564.  
  565.     /* group message */
  566.     if(msg->pguri) {
  567.         process_group_message(fxmain , msg);
  568.         return;
  569.     }
  570.  
  571.     fxchat = fx_list_find_chat_by_sipuri(clist , msg->sipuri);
  572.     sid = fetion_sip_get_sid_by_sipuri(msg->sipuri);
  573.  
  574.     senderContact = fetion_contact_list_find_by_sipuri(
  575.                         user->contactList , msg->sipuri);
  576.  
  577.     /* system message */
  578.     if(strlen(sid) < 5 || strcmp(sid , "10000") == 0) {
  579.         g_free(sid);
  580.         if(config->closeSysMsg == CLOSE_SYSMSG_ENABLE)
  581.             return;
  582.         gdk_threads_enter();
  583.         process_system_message(sipmsg);
  584.         gdk_threads_leave();
  585.         fetion_message_free(msg);
  586.         return;
  587.     }
  588.  
  589.     if(senderContact)
  590.         fx_main_add_history(fxmain, senderContact->nickname,
  591.                             senderContact->userId, msg->message, 0);
  592.  
  593.  
  594.     gdk_threads_enter();
  595.  
  596.     if(!fxchat || fxchat->hasFocus == CHAT_DIALOG_NOT_FOCUSED) {
  597.         /* chat window does not exist */
  598.         if(!fxchat) {
  599.  
  600.             /* auto popup enabled */
  601.             if(config->autoPopup == AUTO_POPUP_ENABLE) {
  602.                 fxchat = fx_main_create_chat_window(fxmain , msg->sipuri);
  603.                 if(!fxchat) {
  604.                     fetion_message_free(msg);
  605.                     gdk_threads_leave();
  606.                     return;
  607.                 }
  608.                 fx_chat_add_message(fxchat , msg->message,
  609.                                     &(msg->sendtime) , 0 , msg->sysback);
  610.                 fetion_message_free(msg);
  611.                 gdk_threads_leave();
  612.                 return;
  613.             } else {
  614.                 /* chat window doesn`t exist and auto-pupup wasn`t enabled
  615.                  * just push message into message queue,wait for user action */
  616.                 mitem = fx_list_new(msg);
  617.                 fx_list_append(fxmain->mlist , mitem );
  618.                 popup_msg_notify(fxmain, senderContact, msg);
  619.             }
  620.             /* chat window exist,but not focused */
  621.         } else {
  622.             fx_chat_add_message(fxchat , msg->message,
  623.                                 &(msg->sendtime) , 0 , msg->sysback);
  624.             fxchat->unreadMsgCount ++;
  625.             fx_chat_update_window(fxchat);
  626.         }
  627.  
  628.         sprintf(path , "%s/%s.jpg" , config->iconPath , sid);
  629.         g_free(sid);
  630.         pb = gdk_pixbuf_new_from_file(path , NULL);
  631.         if(!pb)
  632.             pb = gdk_pixbuf_new_from_file(SKIN_DIR"online.svg" , NULL);
  633.         gtk_status_icon_set_from_pixbuf(GTK_STATUS_ICON(fxmain->trayIcon) , pb);
  634.         g_object_unref(pb);
  635.  
  636.         gtk_status_icon_set_blinking(GTK_STATUS_ICON(fxmain->trayIcon) , TRUE);
  637.         g_signal_handler_disconnect(fxmain->trayIcon , fxmain->iconConnectId);
  638.  
  639.         fxmain->iconConnectId = g_signal_connect(G_OBJECT(fxmain->trayIcon)
  640.                                 , "activate"
  641.                                 , GTK_SIGNAL_FUNC(fx_main_message_func)
  642.                                 , fxmain);
  643.  
  644.         /* no message was pushed into the message queue,just free it */
  645.         if(fxchat && fxchat->hasFocus == CHAT_DIALOG_NOT_FOCUSED)
  646.             fetion_message_free(msg);
  647.     } else {
  648.         fx_chat_add_message(fxchat , msg->message,
  649.                             &(msg->sendtime) , 0, msg->sysback);
  650.  
  651.         /* message was showed in the chat dialog directly,just free it */
  652.         fetion_message_free(msg);
  653.     }
  654.     gdk_threads_leave();
  655.     if(config->isMute == MUTE_DISABLE)
  656.         fx_sound_play_file(RESOURCE_DIR"newmessage.wav");
  657. }
  658. void fx_main_process_user_left(FxMain *fxmain , const gchar *msg) {
  659.     gchar         *sipuri;
  660.     FxList       *clist;
  661.     FxChat       *fxchat;
  662.     Conversation *conv;
  663.  
  664.     clist = fxmain->clist;
  665.  
  666.     fetion_sip_parse_userleft(msg , &sipuri);
  667.     /* remove sip struct from stack      */
  668.     fx_list_remove_sip_by_sipuri(fxmain->slist , sipuri);
  669.  
  670.     /* if fxchat exist , set current sip struct to NULL ,
  671.      * and exit thread, orelse just exit current thread  */
  672.     fxchat = fx_list_find_chat_by_sipuri(clist , sipuri);
  673.     if(!fxchat) {
  674.         debug_info("User %s left conversation" , sipuri);
  675.         debug_info("Thread exit");
  676.         g_free(sipuri);
  677.         g_thread_exit(0);
  678.     }
  679.     conv = fxchat->conv;
  680.     conv->currentSip = NULL;
  681.  
  682.     debug_info("User %s left conversation" , sipuri);
  683.     debug_info("Thread exit");
  684.     g_free(sipuri);
  685.     g_thread_exit(0);
  686.  
  687. }
  688. FxChat *fx_main_create_chat_window(FxMain *fxmain , const gchar *sipuri) {
  689.     Conversation *conv;
  690.     FxChat       *fxchat;
  691.     FxList       *citem;
  692.     Contact      *contact;
  693.     gchar        *sid;
  694.  
  695.     if((fxchat = fx_list_find_chat_by_sipuri(fxmain->clist , sipuri)) != NULL)
  696.         return fxchat;
  697.     conv = fetion_conversation_new(fxmain->user , sipuri , NULL);
  698.  
  699.     /* this buddy is not in the friend list*/
  700.     if(!conv) {
  701.         sid = fetion_sip_get_sid_by_sipuri(sipuri);
  702.         if(strlen(sid) < 8 || strcmp(sid , "10000") == 0) {
  703.             g_free(sid);
  704.             return NULL;
  705.         }
  706.  
  707.         contact = fetion_contact_get_contact_info_by_no(fxmain->user , sid , FETION_NO);
  708.  
  709.         if(!contact)
  710.             return NULL;
  711.         /* replace the sipuri*/
  712.         memset(contact->sipuri, 0, sizeof(contact->sipuri));
  713.         strcpy(contact->sipuri , sipuri);
  714.         fetion_contact_list_append(fxmain->user->contactList , contact);
  715.         conv = fetion_conversation_new(fxmain->user , sipuri , NULL);
  716.     }
  717.     if(!conv)
  718.         return NULL;
  719.     fxchat = fx_chat_new(fxmain , conv);
  720.     fx_chat_initialize(fxchat);
  721.     citem = fx_list_new(fxchat);
  722.     fx_list_append(fxmain->clist , citem);
  723.  
  724.     return fxchat;
  725. }
  726. void fx_main_process_invitation(FxMain *fxmain , const gchar *sipmsg) {
  727.     gchar       *sipuri;
  728.     FetionSip   *osip;
  729.     FetionSip   *sip;
  730.     FxList      *list;
  731.     TimeOutArgs *timeout;
  732.     gchar        event[16];
  733.     ThreadArgs  *args;
  734.  
  735.     args = (ThreadArgs *)malloc(sizeof(ThreadArgs));
  736.     sip = fxmain->user->sip;
  737.  
  738.     memset(event, 0, sizeof(event));
  739.     if(fetion_sip_get_attr(sipmsg , "N" , event) != -1)
  740.         return;
  741.  
  742.     fetion_sip_parse_invitation(sip,
  743.                                 fxmain->user->config->proxy,
  744.                                 sipmsg , &osip , &sipuri);
  745.  
  746.     list = fx_list_new(osip);
  747.     fx_list_append(fxmain->slist , list);
  748.  
  749.     args->fxmain = fxmain;
  750.     args->sip = osip;
  751.  
  752.     /* create a thread to listen in this channel */
  753.     g_thread_create(fx_main_listen_thread_func,
  754.                     args , FALSE , NULL);
  755.  
  756.     /* start send keep alive message throuth chat chanel
  757.      * and put the timeout information into stack */
  758.     debug_info("Start periodically sending keep alive request");
  759.     timeout = timeout_args_new(fxmain , osip , sipuri);
  760.     list = fx_list_new(timeout);
  761.     fx_list_append(fxmain->tlist , list);
  762. }
  763. #if 0
  764. static void process_share_action_accept(FxMain *fxmain
  765.                                         , FetionSip *sip , const char *sipmsg , const char *sipuri) {
  766.  
  767.     return;
  768. }
  769.  
  770. static void process_share_action_cancel(FxMain *fxmain
  771.                                         , FetionSip *sip , const char *sipmsg , const char *sipuri) {
  772.  
  773.     return;
  774.  
  775. }
  776. #endif
  777. void fx_main_process_incoming(FxMain *fxmain
  778.                               , FetionSip *sip , const gchar *sipmsg) {
  779.     IncomingType       type;
  780.     IncomingActionType action;
  781.     gchar              *sipuri;
  782.     FxChat             *fxchat;
  783.  
  784.     fetion_sip_parse_incoming(sip , sipmsg , &sipuri , &type , &action);
  785.     switch(type) {
  786.     case INCOMING_NUDGE : {
  787.         gdk_threads_enter();
  788.         fxchat = fx_main_create_chat_window(fxmain , sipuri);
  789.         gdk_threads_leave();
  790.  
  791.         fx_chat_nudge_in_thread(fxchat);
  792.  
  793.         gdk_threads_enter();
  794.         fx_chat_add_information(fxchat , _("Receive a window jitter"));
  795.         gdk_threads_leave();
  796.         debug_info("Received a nudge from %s" , sipuri);
  797.         break;
  798.     }
  799.     case INCOMING_SHARE_CONTENT : {
  800.         switch(action) {
  801.         case INCOMING_ACTION_ACCEPT :
  802.             //process_share_action_accept(fxmain , sip , sipmsg , sipuri);
  803.             break;
  804.         case INCOMING_ACTION_CANCEL :
  805.             //process_share_action_cancel(fxmain , sip , sipmsg , sipuri);
  806.             break;
  807.         default:
  808.             break;
  809.         }
  810.         break;
  811.     }
  812.     default:
  813.         break;
  814.     }
  815. }
  816.  
  817. static void fx_main_process_group(FxMain *fxmain , const gchar *xml) {
  818.     User *user = fxmain->user;
  819.     PGGroup *pgcur;
  820.  
  821.     user->pggroup = pg_group_parse_list(xml);
  822.     if(user->pggroup == NULL)
  823.         return;
  824.     pg_group_get_info(user , user->pggroup);
  825.     foreach_pg_group(user->pggroup , pgcur) {
  826.         pg_group_send_invitation(user , pgcur);
  827.         pg_group_get_group_members(user , pgcur);
  828.     }
  829. }
  830.  
  831. void fx_main_process_sipc(FxMain *fxmain , const gchar *sipmsg) {
  832.     int callid;
  833.     int code;
  834.     char *xml = NULL;
  835.     User *user = fxmain->user;
  836.  
  837.     struct unacked_list *ulist;
  838.  
  839.     PGGroup *pggroup = user->pggroup;
  840.     PGGroup *pgcur;
  841.  
  842.     code = fetion_sip_parse_sipc(sipmsg , &callid , &xml);
  843.  
  844.     /* get group info response */
  845.     if(callid == user->pgGroupCallId) {
  846.         gdk_threads_enter();
  847.         fx_main_process_group(fxmain , xml);
  848.         gdk_threads_leave();
  849.         return;
  850.     }
  851.  
  852.     foreach_unacked_list(unackedlist , ulist) {
  853.         if(callid == ulist->message->callid) {
  854.             unacked_list_remove(unackedlist , ulist);
  855.             fetion_message_free(ulist->message);
  856.             free(ulist);
  857.             return;
  858.         }
  859.     }
  860.  
  861.     if(pggroup != NULL) {
  862.         foreach_pg_group(pggroup , pgcur) {
  863. #if 0
  864.             /* get member contact info response */
  865.             foreach_pg_member(pgcur->member , memcur) {
  866.                 if(memcur->getContactInfoCallId == callid) {
  867.                     memcur->contact = pg_group_parse_contact_info(xml);
  868.                     return;
  869.                 }
  870.             }
  871. #endif
  872.             /* group invitation response */
  873.             if(pgcur->inviteCallId == callid && code == 200) {
  874.                 if(pgcur->hasAcked == 0) {
  875.                     pg_group_send_invite_ack(user , sipmsg);
  876.                     pgcur->hasAcked = 1;
  877.                     return;
  878.                 }
  879.  
  880.             }
  881.             /* get group member response */
  882.             if(pgcur->getMembersCallId == callid) {
  883.                 pg_group_parse_member_list(pggroup , sipmsg);
  884.                 pg_group_subscribe(user , pgcur);
  885.                 return;
  886.             }
  887.         }
  888.     }
  889.  
  890.     free(xml);
  891. }
  892.  
  893. void fx_main_process_deregistration(FxMain *fxmain) {
  894.  
  895.     gdk_threads_enter();
  896.     fx_util_popup_warning(fxmain , _("Your fetion login elsewhere. You are forced quit."));
  897.     gdk_threads_leave();
  898.     gtk_main_quit();
  899. }
  900. void fx_main_process_syncuserinfo(FxMain *fxmain , const gchar *xml) {
  901.     Contact      *contact;
  902.     GtkTreeIter   iter;
  903.     GtkTreeIter   cIter;
  904.     gchar         *userid;
  905.     GtkTreeModel *model = gtk_tree_view_get_model(
  906.                               GTK_TREE_VIEW(fxmain->mainPanel->treeView));
  907.  
  908.     contact = fetion_user_parse_syncuserinfo_body(xml , fxmain->user);
  909.  
  910.     if(!contact)
  911.         return;
  912.  
  913.     gtk_tree_model_get_iter_root(model , &iter);
  914.  
  915.     do {
  916.         if(gtk_tree_model_iter_children(model , &cIter , &iter)) {
  917.             do {
  918.                 gtk_tree_model_get(model , &cIter , B_USERID_COL , &userid , -1);
  919.                 if(strcmp(userid , contact->userId) == 0) {
  920.  
  921.                     gdk_threads_enter();
  922.                     gtk_tree_store_set(GTK_TREE_STORE(model) , &cIter
  923.                                        , B_SIPURI_COL                    , contact->sipuri
  924.                                        , B_RELATIONSTATUS_COL    , contact->relationStatus
  925.                                        , -1);
  926.                     gdk_threads_leave();
  927.                     g_free(userid);
  928.                     goto end;
  929.                 }
  930.                 g_free(userid);
  931.             } while(gtk_tree_model_iter_next(model , &cIter));
  932.         }
  933.     } while(gtk_tree_model_iter_next(model , &iter));
  934. end:
  935.     return;
  936. }
  937. void *fx_main_process_addbuddyapplication_thread(void *data) {
  938.     struct Args {
  939.         FxMain *fxmain;
  940.         gchar   sipmsg[2048];
  941.     } *args = (struct Args *)data;
  942.     gchar *userid;
  943.     gchar *sipuri;
  944.     gchar *desc;
  945.     gint   phrase;
  946.     FxApp *fxapp;
  947.  
  948.  
  949.     fetion_sip_parse_addbuddyapplication(args->sipmsg,
  950.                                          &sipuri , &userid , &desc , &phrase);
  951.  
  952.     fxapp = fx_app_new(args->fxmain, sipuri,
  953.                        userid , desc , phrase);
  954.  
  955.     gdk_threads_enter();
  956.     fx_app_initialize(fxapp);
  957.     gtk_dialog_run(GTK_DIALOG(fxapp->dialog));
  958.     gtk_widget_destroy(fxapp->dialog);
  959.     gdk_threads_leave();
  960.  
  961.     return NULL;
  962. }
  963. void fx_main_process_addbuddyapplication(FxMain *fxmain , const char *sipmsg) {
  964.     struct Args {
  965.         FxMain *fxmain;
  966.         char sipmsg[2048];
  967.     } *args = (struct Args *)malloc(sizeof(struct Args));
  968.  
  969.     memset(args , 0 , sizeof(struct args));
  970.     args->fxmain = fxmain;
  971.     strcpy(args->sipmsg , sipmsg);
  972.     g_thread_create(fx_main_process_addbuddyapplication_thread , args , FALSE , NULL);
  973. }
  974. void fx_main_destroy(GtkWidget *UNUSED(widget) , gpointer data) {
  975.     FxMain *fxmain = (FxMain *)data;
  976.     User   *user = fxmain->user;
  977.     if(user) {
  978.         Config *config = user->config;
  979.         fetion_config_save_size(config);
  980.     }
  981.     gtk_main_quit();
  982. }
  983. gboolean fx_main_delete(GtkWidget *widget , GdkEvent *UNUSED(event) , gpointer data) {
  984.     FxMain *fxmain = (FxMain *)data;
  985.     FxClose *fxclose;
  986.     Config *config;
  987.  
  988.     int ret;
  989.  
  990.     int     window_width;
  991.     int     window_height;
  992.     int     window_x;
  993.     int     window_y;
  994.  
  995.     if(fxmain->user) {
  996.         config = fxmain->user->config;
  997.         gtk_window_get_position(GTK_WINDOW(fxmain->window),
  998.                                 &window_x, &window_y);
  999.         config->window_pos_x = window_x;
  1000.         config->window_pos_y = window_y;
  1001.         gtk_window_get_size(GTK_WINDOW(fxmain->window),
  1002.                             &window_width, &window_height);
  1003.         config->window_width = window_width;
  1004.         config->window_height = window_height;
  1005.     }
  1006.  
  1007.     if(fxmain->user) {
  1008.         if(config->closeAlert == CLOSE_ALERT_ENABLE) {
  1009.             fxclose = fx_close_new(fxmain);
  1010.             fx_close_initialize(fxclose);
  1011.             ret = gtk_dialog_run(GTK_DIALOG(fxclose->dialog));
  1012.             if(ret == GTK_RESPONSE_OK) {
  1013.                 if(fx_close_alert(fxclose) == CLOSE_ALERT_DISABLE) {
  1014.                     config->closeMode = fx_close_get_action(fxclose);
  1015.                     config->closeAlert = CLOSE_ALERT_DISABLE;
  1016.                     fetion_config_save(fxmain->user);
  1017.                 }
  1018.                 if(fx_close_get_action(fxclose) == CLOSE_DESTROY_MODE) {
  1019.                     gtk_widget_destroy(fxclose->dialog);
  1020.                     free(fxclose);
  1021.                     gtk_widget_destroy(widget);
  1022.                     return FALSE;
  1023.                 } else {
  1024.                     gtk_widget_destroy(fxclose->dialog);
  1025.                     gtk_widget_hide_on_delete(widget);
  1026.                     return TRUE;
  1027.                 }
  1028.             } else {
  1029.                 gtk_widget_destroy(fxclose->dialog);
  1030.                 return TRUE;
  1031.             }
  1032.         }
  1033.     } else {
  1034.         fx_main_destroy(widget , fxmain);
  1035.         return FALSE;
  1036.     }
  1037.  
  1038.     if(fxmain->user != NULL && fxmain->user->loginStatus != -1) {
  1039.         config = fxmain->user->config;
  1040.         if(config->closeMode == CLOSE_ICON_MODE) {
  1041.             gtk_widget_hide_on_delete(widget);
  1042.             return TRUE;
  1043.         } else {
  1044.             gtk_widget_destroy(widget);
  1045.             return FALSE;
  1046.         }
  1047.     }
  1048.     return FALSE;
  1049. }
  1050. gboolean fx_main_window_state_func(GtkWidget *widget
  1051.                                    , GdkEventWindowState *event , gpointer data) {
  1052.     FxMain *fxmain;
  1053.     Config *config;
  1054.  
  1055.     fxmain = (FxMain *)data;
  1056.     config = fxmain->user == NULL ? NULL : fxmain->user->config;
  1057.  
  1058.     if(config) {
  1059.         if(event->changed_mask == GDK_WINDOW_STATE_ICONIFIED &&
  1060.                 event->new_window_state == GDK_WINDOW_STATE_ICONIFIED) {
  1061.  
  1062.             if(config->canIconify == ICON_CAN) {
  1063.                 gtk_window_get_position(GTK_WINDOW(widget)
  1064.                                         , &window_pos_x_old , &window_pos_y_old);
  1065.                 return TRUE;
  1066.             } else {
  1067.                 return FALSE;
  1068.             }
  1069.         }
  1070.     }
  1071.     return FALSE;
  1072. }
  1073. void fx_main_tray_activate_func(GtkWidget *UNUSED(widget) , gpointer data) {
  1074.     FxMain *fxmain;
  1075.     Config *config = NULL;
  1076.  
  1077.     fxmain = (FxMain *)data;
  1078.  
  1079.     if(fxmain->user && fxmain->user->config)
  1080.         config = fxmain->user->config;
  1081.  
  1082.     if(!config)
  1083.         return;
  1084.  
  1085.     gtk_window_deiconify(GTK_WINDOW(fxmain->window));
  1086.     if(GTK_WIDGET_VISIBLE(fxmain->window)) {
  1087.         if(config->canIconify == ICON_CAN) {
  1088.             gtk_window_iconify(GTK_WINDOW(fxmain->window));
  1089.             gtk_window_get_position(GTK_WINDOW(fxmain->window)
  1090.                                     , &window_pos_x_old , &window_pos_y_old);
  1091.             gtk_widget_hide(fxmain->window);
  1092.         }
  1093.     } else {
  1094.         //gtk_window_deiconify(GTK_WINDOW(fxmain->window));
  1095.         gtk_widget_show(fxmain->window);
  1096.     }
  1097.  
  1098.     if(window_pos_x_old == 0 && window_pos_y_old == 0) {
  1099.         window_pos_x_old = window_pos_x;
  1100.         window_pos_y_old = window_pos_y;
  1101.     }
  1102.     gtk_window_move(GTK_WINDOW(fxmain->window),
  1103.                     window_pos_x_old , window_pos_y_old);
  1104.  
  1105. }
  1106.  
  1107. static void fx_main_mute_clicked(
  1108.     GtkWidget *UNUSED(widget) , gpointer data) {
  1109.     FxMain *fxmain;
  1110.     User   *user;
  1111.     Config *config;
  1112.  
  1113.     fxmain = (FxMain *)data;
  1114.     user = fxmain->user;
  1115.     config = user->config;
  1116.  
  1117.     if(config->isMute == MUTE_ENABLE)
  1118.         config->isMute = MUTE_DISABLE;
  1119.     else
  1120.         config->isMute = MUTE_ENABLE;
  1121.  
  1122.     fetion_config_save(user);
  1123.  
  1124. }
  1125.  
  1126. static void fx_main_direct_sms_clicked(
  1127.     GtkWidget *UNUSED(widget) , gpointer data) {
  1128.     FxMain *fxmain;
  1129.     FxDSMS *fxdsms;
  1130.  
  1131.     fxmain = (FxMain *)data;
  1132.     fxdsms = fx_dsms_new(fxmain);
  1133.  
  1134.     if(fxmain->user->carrierStatus == CARRIER_STATUS_DOWN) {
  1135.         fx_util_popup_warning(fxmain,
  1136.                               SERVICE_DOWN_MESSAGE);
  1137.         return;
  1138.     }
  1139.     fx_dsms_initialize(fxdsms);
  1140. }
  1141.  
  1142. void fx_main_tray_popmenu_func(
  1143.     GtkWidget *UNUSED(widget),
  1144.     guint button , guint activate_time,
  1145.     gpointer data) {
  1146.     FxMain    *fxmain;
  1147.     User      *user;
  1148.     Config    *config;
  1149.     GtkWidget *item;
  1150.     GtkWidget *menu;
  1151.     GtkWidget *statemenu;
  1152.     GtkWidget *submenu;
  1153.     gchar     stateMenu[48];
  1154.     gint      i;
  1155.     typedef struct {
  1156.         FxMain *fxmain;
  1157.         StateType type;
  1158.     } Args;
  1159.     Args      *args;
  1160.  
  1161.     fxmain = (FxMain *)data;
  1162.     user = fxmain->user;
  1163.  
  1164.     struct {
  1165.         const gchar *name;
  1166.         const gchar *icon;
  1167.         int type;
  1168.     } presence[] = {
  1169.         { N_("Online")   , SKIN_DIR"online.svg" , P_ONLINE } ,
  1170.         { N_("Leave")    , SKIN_DIR"away.svg" , P_AWAY } ,
  1171.         { N_("Busy")     , SKIN_DIR"busy.svg" , P_BUSY } ,
  1172.         { N_("Hide")     , SKIN_DIR"invisible.svg" , P_HIDDEN } ,
  1173.         { N_("Eating out") , SKIN_DIR"away.svg" , P_OUTFORLUNCH } ,
  1174.         { N_("Do Not Disturb") , SKIN_DIR"away.svg" , P_DONOTDISTURB } ,
  1175.         { N_("Back Soon") , SKIN_DIR"away.svg" , P_RIGHTBACK } ,
  1176.         { N_("Meeting")  , SKIN_DIR"away.svg" , P_MEETING } ,
  1177.         { N_("Calling")  , SKIN_DIR"away.svg" , P_ONTHEPHONE} ,
  1178.         { NULL           , NULL                            , -1}
  1179.     };
  1180.  
  1181.     menu = gtk_menu_new();
  1182.     fx_main_create_menu1(_("About OpenFetion") , GTK_STOCK_ABOUT
  1183.                          , menu , fx_main_about_fetion_clicked , NULL);
  1184.  
  1185.     if(fxmain->user && fxmain->user->loginStatus != -1) {
  1186.         config = fxmain->user->config;
  1187.  
  1188.         item = gtk_check_menu_item_new_with_label(_("Close sound"));
  1189.  
  1190.         if(config->isMute == MUTE_ENABLE)
  1191.             gtk_check_menu_item_set_active(
  1192.                 GTK_CHECK_MENU_ITEM(item) , TRUE);
  1193.         else
  1194.             gtk_check_menu_item_set_active(
  1195.                 GTK_CHECK_MENU_ITEM(item) , FALSE);
  1196.  
  1197.         g_signal_connect(item, "activate",
  1198.                          G_CALLBACK(fx_main_mute_clicked) , fxmain);
  1199.         gtk_menu_shell_append(GTK_MENU_SHELL(menu) , item);
  1200.  
  1201.         item = gtk_check_menu_item_new_with_label(_("Receive SMS"));
  1202.  
  1203.         if(strcmp(user->smsOnLineStatus , "0.00:00:00") &&
  1204.                 strcmp(user->smsOnLineStatus , "0.0:0:0"))
  1205.             gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item) , FALSE);
  1206.         else
  1207.             gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item) , TRUE);
  1208.  
  1209.         gtk_menu_shell_append(GTK_MENU_SHELL(menu) , item);
  1210.         g_signal_connect(item, "activate",
  1211.                          G_CALLBACK(fx_head_set_sms_clicked) , fxmain);
  1212.  
  1213.         fx_main_create_menu1(_("Information query") , GTK_STOCK_FIND
  1214.                              , menu , fx_main_info_lookup_clicked , fxmain);
  1215.  
  1216.  
  1217.         statemenu = fx_main_create_menu1(_("Edit statement"),
  1218.                                          GTK_STOCK_INFO , menu , NULL , NULL);
  1219.  
  1220.         submenu = gtk_menu_new();
  1221.         for(i = 0 ; presence[i].type != -1 ; i++) {
  1222.             args = (Args *)malloc(sizeof(Args));
  1223.             args->fxmain = fxmain;
  1224.             args->type = presence[i].type;
  1225.  
  1226.             sprintf(stateMenu , "%s      " , _(presence[i].name));
  1227.             fx_main_create_menu(stateMenu , presence[i].icon
  1228.                                 , submenu , fx_main_set_state_clicked , args);
  1229.         }
  1230.  
  1231.         gtk_menu_item_set_submenu(GTK_MENU_ITEM(statemenu) , submenu);
  1232.  
  1233.         statemenu = fx_main_create_menu1(_("Message Function"),
  1234.                                          GTK_STOCK_INFO , menu , NULL , NULL);
  1235.         submenu = gtk_menu_new();
  1236.         fx_main_create_menu(_("SMS to many") , SKIN_DIR"groupsend.png"
  1237.                             , submenu , fx_main_send_to_many_clicked , fxmain);
  1238.         fx_main_create_menu(_("SMS directly") , SKIN_DIR"directsms.png"
  1239.                             , submenu , fx_main_direct_sms_clicked , fxmain);
  1240.         if(fxmain->user->boundToMobile == BOUND_MOBILE_ENABLE)
  1241.             fx_main_create_menu(_("SMS myself") , SKIN_DIR"myselfsms.png"
  1242.                                 , submenu , fx_main_send_to_myself_clicked , fxmain);
  1243.         gtk_menu_item_set_submenu(GTK_MENU_ITEM(statemenu) , submenu);
  1244.  
  1245.         fx_main_create_menu1(_("Add contact") , GTK_STOCK_ADD
  1246.                              , menu , fx_main_add_buddy_clicked , fxmain);
  1247.         fx_main_create_menu1(_("Personal setting") ,  GTK_STOCK_EDIT
  1248.                              , menu , fx_main_personal_setting_clicked , fxmain);
  1249.         fx_main_create_menu1(_("System setting") , GTK_STOCK_PREFERENCES
  1250.                              , menu , fx_main_system_setting_clicked , fxmain);
  1251.     }
  1252.  
  1253.     fx_main_create_menu1(_("Exit OpenFetion ") , GTK_STOCK_QUIT
  1254.                          , menu , fx_main_destroy , fxmain);
  1255.     gtk_widget_show_all(menu);
  1256.     gtk_menu_popup(GTK_MENU(menu) , NULL , NULL , NULL , NULL
  1257.                    , button , activate_time);
  1258. }
  1259. int main(int argc , char *argv[]) {
  1260.  
  1261.     FxMain *fxmain = fx_main_new();
  1262.  
  1263.     setlocale(LC_ALL, "");
  1264.     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
  1265.     bindtextdomain(GETTEXT_PACKAGE , LOCALE_DIR);
  1266.     textdomain(GETTEXT_PACKAGE);
  1267.  
  1268.     if(!g_thread_supported())
  1269.         g_thread_init(NULL);
  1270.     gdk_threads_init();
  1271.  
  1272.     struct sigaction sa;
  1273.     sa.sa_handler = SIG_IGN;
  1274.     sigaction(SIGPIPE, &sa, 0 );
  1275.  
  1276. #ifdef USE_GSTREAMER
  1277.     gst_init(&argc , &argv);
  1278. #endif
  1279.  
  1280. #ifdef USE_LIBNOTIFY
  1281.     notify_init("Openfetion");
  1282. #endif
  1283.     gtk_init(&argc , &argv);
  1284.  
  1285.     fx_conn_init(fxmain);
  1286.  
  1287.     fx_main_initialize(fxmain);
  1288.  
  1289.     return 0;
  1290. }
  1291.  
  1292. static void chat_listen_thread_end(FxMain *fxmain, const char *sipuri) {
  1293.     FxList       *clist;
  1294.     FxChat       *fxchat;
  1295.     Conversation *conv;
  1296.  
  1297.     clist = fxmain->clist;
  1298.  
  1299.     if(!sipuri || strlen(sipuri) == 0)
  1300.         return;
  1301.  
  1302.     fx_list_remove_sip_by_sipuri(fxmain->slist , sipuri);
  1303.  
  1304.     fxchat = fx_list_find_chat_by_sipuri(clist , sipuri);
  1305.     if(!fxchat) {
  1306.         debug_info("User %s left conversation" , sipuri);
  1307.         debug_info("Thread exit");
  1308.         g_thread_exit(0);
  1309.     }
  1310.     conv = fxchat->conv;
  1311.     conv->currentSip = NULL;
  1312.  
  1313.     debug_info("User %s left conversation" , sipuri);
  1314.     debug_info("Thread exit");
  1315.     g_thread_exit(0);
  1316. }
  1317.  
  1318. void *fx_main_listen_thread_func(void *data) {
  1319.     ThreadArgs *args;
  1320.     FxMain     *fxmain;
  1321.     FetionSip  *sip;
  1322.     SipMsg     *msg;
  1323.     SipMsg     *pos;
  1324.     User       *user;
  1325.     gint        type;
  1326.     gint        ret;
  1327.     gint        error;
  1328.  
  1329.     args = (ThreadArgs *)data;
  1330.     fxmain = args->fxmain;
  1331.     user = fxmain->user;
  1332.     sip = args->sip;
  1333.  
  1334.     struct timeval tv;
  1335.  
  1336.     debug_info("A new thread entered");
  1337.  
  1338.     sip = (sip == NULL ? fxmain->user->sip : sip);
  1339.  
  1340.     for(;;) {
  1341.  
  1342.         if(!fxmain)
  1343.             g_thread_exit(0);
  1344.  
  1345.         FD_ZERO(&fd_read);
  1346.  
  1347.         g_static_mutex_lock(&mutex);
  1348.         if(!sip || !sip->tcp) {
  1349.             debug_info("thread exited");
  1350.             g_thread_exit(0);
  1351.         }
  1352.         FD_SET(sip->tcp->socketfd, &fd_read);
  1353.         g_static_mutex_unlock(&mutex);
  1354.  
  1355.         tv.tv_sec = 13;
  1356.         tv.tv_usec = 0;
  1357.  
  1358.         ret = select(sip->tcp->socketfd + 1, &fd_read, NULL, NULL, &tv);
  1359.  
  1360.         if(ret == 0)
  1361.             continue;
  1362.  
  1363.         if (ret == -1) {
  1364.             debug_info ("Error.. to read socket %d,exit thread",
  1365.                         sip->tcp->socketfd);
  1366.             if(sip != user->sip) {
  1367.                 debug_info("Error.. thread sip freed\n");
  1368.                 g_free(sip);
  1369.             }
  1370.             g_thread_exit(0);
  1371.         }
  1372.  
  1373.         if (!FD_ISSET (sip->tcp->socketfd, &fd_read)) {
  1374.             g_usleep (100);
  1375.             continue;
  1376.         }
  1377.  
  1378.         msg = fetion_sip_listen(sip, &error);
  1379.  
  1380.         if(!msg && error) {
  1381.             /* if it is the main listening thread */
  1382.             if(sip == user->sip) {
  1383.                 gdk_threads_enter();
  1384.                 printf("\n\nError ...... break out...\n\n");
  1385.                 fx_conn_offline(fxmain);
  1386.                 gdk_threads_leave();
  1387.                 g_thread_exit(0);
  1388.             } else {
  1389.                 printf("\n\n Error ... user listen thread break out\n\n");
  1390.                 chat_listen_thread_end(fxmain, sip->sipuri);
  1391.                 tcp_connection_free(sip->tcp);
  1392.                 g_thread_exit(0);
  1393.             }
  1394.         }
  1395.  
  1396.         pos = msg;
  1397.         while(pos) {
  1398.  
  1399.             type = fetion_sip_get_type(pos->message);
  1400.             switch(type) {
  1401.             case SIP_NOTIFICATION :
  1402.                 fx_main_process_notification(fxmain , pos->message);
  1403.                 break;
  1404.             case SIP_MESSAGE:
  1405.                 fx_main_process_message(fxmain , sip , pos->message);
  1406.                 break;
  1407.             case SIP_INVITATION:
  1408.                 fx_main_process_invitation(fxmain , pos->message);
  1409.                 break;
  1410.             case SIP_INCOMING :
  1411.                 fx_main_process_incoming(fxmain , sip , pos->message);
  1412.                 break;
  1413.             case SIP_SIPC_4_0:
  1414.                 fx_main_process_sipc(fxmain , pos->message);
  1415.                 break;
  1416.             default:
  1417.                 //printf("%s\n" , pos->message);
  1418.                 break;
  1419.             }
  1420.             pos = pos->next;
  1421.         }
  1422.  
  1423.         if(msg)
  1424.             fetion_sip_message_free(msg);
  1425.     }
  1426.  
  1427.     return NULL;
  1428. }
  1429. void fx_main_message_func(GtkWidget *UNUSED(widget) , gpointer data) {
  1430.     FxMain        *fxmain;
  1431.     FxList        *mlist;
  1432.     FxList        *cur;
  1433.     FxList        *tmp;
  1434.     FxChat        *fxchat;
  1435.     FxPGGroup     *fxpg;
  1436.     PGGroupMember *memcur;
  1437.     Message       *msg;
  1438.  
  1439.     fxmain = (FxMain *)data;
  1440.     mlist = fxmain->mlist;
  1441.     cur = mlist->pre;
  1442.  
  1443. #ifdef USE_LIBNOTIFY
  1444.     notify_notification_close(fxmain->notify , NULL);
  1445. #endif
  1446.  
  1447.     while(cur != fxmain->mlist) {
  1448.         msg = (Message *)(cur->data);
  1449.  
  1450.         /* ordinary message */
  1451.         if(!msg->pguri) {
  1452.             fxchat = fx_main_create_chat_window(fxmain , msg->sipuri);
  1453.  
  1454.             if(!fxchat) {
  1455.                 g_print("Unknow Message\n");
  1456.                 g_print("%s:%s\n" , msg->sipuri ,  msg->message);
  1457.                 continue;
  1458.             }
  1459.             fx_chat_add_message(fxchat , msg->message,
  1460.                                 &(msg->sendtime) , 0 , msg->sysback);
  1461.         } else {
  1462.             /*group message*/
  1463.             fxpg = pg_create_window(fxmain , msg->pguri);
  1464.  
  1465.             foreach_pg_member(fxpg->pggroup->member , memcur) {
  1466.                 if(strcmp(memcur->sipuri , msg->sipuri) == 0) {
  1467.                     pg_add_message(fxpg, msg->message,
  1468.                                    &(msg->sendtime) , memcur );
  1469.                     break;
  1470.                 }
  1471.             }
  1472.         }
  1473.         fetion_message_free(msg);
  1474.         tmp = cur;
  1475.         cur = cur->pre;
  1476.         fx_list_remove(tmp);
  1477.         free(tmp);
  1478.     }
  1479.     fx_head_set_state_image(fxmain , fxmain->user->state);
  1480.     gtk_status_icon_set_blinking(
  1481.         GTK_STATUS_ICON(fxmain->trayIcon) , FALSE);
  1482.     g_signal_handler_disconnect(fxmain->trayIcon,
  1483.                                 fxmain->iconConnectId);
  1484.     fxmain->iconConnectId = g_signal_connect(
  1485.                                 G_OBJECT(fxmain->trayIcon)
  1486.                                 , "activate"
  1487.                                 , GTK_SIGNAL_FUNC(fx_main_tray_activate_func)
  1488.                                 , fxmain);
  1489.  
  1490.     foreach_list(fxmain->clist, cur) {
  1491.         fxchat = (FxChat *)cur->data;
  1492.         if(fxchat->unreadMsgCount != 0)
  1493.             gtk_window_present(GTK_WINDOW(fxchat->dialog));
  1494.  
  1495.     }
  1496. }
  1497. gboolean fx_main_register_func(User *user) {
  1498.     if(fetion_user_keep_alive(user) < 0) {
  1499.         debug_info("keep alive terminated");
  1500.         return FALSE;
  1501.     }
  1502.     return TRUE;
  1503. }
  1504.  
  1505. gboolean fx_main_check_func(FxMain *fxmain) {
  1506.     struct unacked_list *list;
  1507.     struct tm           *now;
  1508.     char                *msg;
  1509.     time_t               now_t;
  1510.     time_t               msg_time_t;
  1511.     long                 seconds;
  1512.  
  1513.     start_popup_presence = 1;
  1514.  
  1515.     if(fxmain->user->state == P_OFFLINE) {
  1516.         debug_info("Error.. check function exited");
  1517.         return FALSE;
  1518.     }
  1519.  
  1520.     now = get_currenttime();
  1521.     foreach_unacked_list(unackedlist , list) {
  1522.         now_t = mktime(now);
  1523.         msg_time_t = mktime(&(list->message->sendtime));
  1524.         seconds = (long)now_t - (long)msg_time_t;
  1525.         if(seconds > 20) {
  1526.             unacked_list_remove(unackedlist , list);
  1527.             msg = contruct_message_sip(fxmain->user->sId , list->message);
  1528.             fx_main_process_message(fxmain , fxmain->user->sip , msg);
  1529.             free(msg);
  1530.             fetion_message_free(list->message);
  1531.             free(list);
  1532.         }
  1533.     }
  1534.  
  1535.     idle_autoaway(fxmain);
  1536.  
  1537.     return TRUE;
  1538. }
  1539.  
  1540. void fx_main_about_fetion_clicked(GtkWidget *UNUSED(widget) , gpointer UNUSED(data)) {
  1541.     show_about();
  1542. }
  1543.  
  1544. void fx_main_send_to_myself_clicked(GtkWidget *widget , gpointer data) {
  1545.     fx_bottom_on_sendtome_clicked(widget , data);
  1546. }
  1547.  
  1548. void fx_main_send_to_many_clicked(GtkWidget *widget , gpointer data) {
  1549.     fx_bottom_on_sendtomany_clicked(widget , data);
  1550. }
  1551.  
  1552. void fx_main_personal_setting_clicked(GtkWidget *widget , gpointer data) {
  1553.     fx_bottom_on_setting_clicked(widget , data);
  1554. }
  1555.  
  1556. void fx_main_system_setting_clicked(GtkWidget *UNUSED(widget) , gpointer data) {
  1557.     FxMain *fxmain = (FxMain *)data;
  1558.     FxSet *fxset = fx_set_new(fxmain);
  1559.     fx_set_initialize(fxset);
  1560.     g_object_set(fxset->notebook , "page" , 1 , NULL);
  1561.     gtk_window_set_position(GTK_WINDOW(fxset->dialog) , GTK_WIN_POS_CENTER);
  1562.     gtk_dialog_run(GTK_DIALOG(fxset->dialog));
  1563.     gtk_widget_destroy(fxset->dialog);
  1564. }
  1565.  
  1566. void fx_main_set_state_clicked(GtkWidget *widget , gpointer data) {
  1567.     fx_head_change_state_func(widget , data);
  1568. }
  1569.  
  1570. void fx_main_add_buddy_clicked(GtkWidget *widget , gpointer data) {
  1571.     fx_bottom_on_addfriend_clicked(widget , data);
  1572. }
  1573.  
  1574. void fx_main_info_lookup_clicked(GtkWidget *widget , gpointer data) {
  1575.     fx_bottom_on_lookup_clicked(widget , data);
  1576. }
  1577.  
  1578. FetionSip *fx_list_find_sip_by_sipuri(FxList *fxlist , const char *sipuri) {
  1579.     FxList    *cur;
  1580.     FetionSip *sip;
  1581.     gchar     *sid;
  1582.     gchar     *sid1;
  1583.  
  1584.     foreach_list(fxlist , cur) {
  1585.         sip = (FetionSip *)(cur->data);
  1586.         sid = fetion_sip_get_sid_by_sipuri(sip->sipuri);
  1587.         sid1 = fetion_sip_get_sid_by_sipuri(sipuri);
  1588.         if(strcmp(sid , sid1) == 0) {
  1589.             g_free(sid);
  1590.             sid = NULL;
  1591.             g_free(sid1);
  1592.             sid1 = NULL;
  1593.             return sip;
  1594.         }
  1595.         g_free(sid);
  1596.         sid = NULL;
  1597.         g_free(sid1);
  1598.         sid1 = NULL;
  1599.     }
  1600.     return NULL;
  1601. }
  1602. void fx_list_remove_sip_by_sipuri(FxList *fxlist , const char *sipuri) {
  1603.     FxList    *cur;
  1604.     FetionSip *sip;
  1605.     gchar     *sid;
  1606.     gchar     *sid1;
  1607.  
  1608.     foreach_list(fxlist , cur) {
  1609.         sip = (FetionSip *)(cur->data);
  1610.         sid = fetion_sip_get_sid_by_sipuri(sip->sipuri);
  1611.         sid1 = fetion_sip_get_sid_by_sipuri(sipuri);
  1612.         if(strcmp(sid , sid1) == 0)     {
  1613.             debug_info("Removing sip from sip list");
  1614.             cur->next->pre = cur->pre;
  1615.             cur->pre->next = cur->next;
  1616.             g_free(sid);
  1617.             sid = NULL;
  1618.             g_free(sid1);
  1619.             sid1 = NULL;
  1620.             g_free(cur);
  1621.             break;
  1622.         }
  1623.         g_free(sid);
  1624.         sid = NULL;
  1625.         g_free(sid1);
  1626.         sid1 = NULL;
  1627.     }
  1628. }
  1629.  
  1630. FxChat *fx_list_find_chat_by_sipuri(FxList *fxlist , const char *sipuri) {
  1631.     FxChat  *fxchat;
  1632.     FxList  *cur;
  1633.     Contact *contact;
  1634.     gchar   *sid;
  1635.     gchar   *sid1;
  1636.  
  1637.     foreach_list(fxlist , cur) {
  1638.         fxchat = (FxChat *)(cur->data);
  1639.         contact = fxchat->conv->currentContact;
  1640.         sid = fetion_sip_get_sid_by_sipuri(contact->sipuri);
  1641.         sid1 = fetion_sip_get_sid_by_sipuri(sipuri);
  1642.         if(strcmp(sid , sid1) == 0) {
  1643.             g_free(sid);
  1644.             g_free(sid1);
  1645.             return fxchat;
  1646.         }
  1647.         g_free(sid);
  1648.         g_free(sid1);
  1649.     }
  1650.     return NULL;
  1651. }
  1652. void fx_list_remove_chat_by_sipuri(FxList *fxlist , const char *sipuri) {
  1653.     FxList  *cur;
  1654.     Contact *contact;
  1655.     FxChat  *fxchat;
  1656.     gchar   *sid;
  1657.     gchar   *sid1;
  1658.  
  1659.     foreach_list(fxlist , cur) {
  1660.         fxchat = (FxChat *)(cur->data);
  1661.         contact = fxchat->conv->currentContact;
  1662.         if(!contact) {
  1663.             printf("Unknown FxChat\n");
  1664.             continue;
  1665.         }
  1666.         sid = fetion_sip_get_sid_by_sipuri(contact->sipuri);
  1667.         sid1 = fetion_sip_get_sid_by_sipuri(sipuri);
  1668.         if(strcmp(sid , sid1) == 0) {
  1669.             debug_info("Removing chat struct from chat list");
  1670.             g_free(sid);
  1671.             sid = NULL;
  1672.             g_free(sid1);
  1673.             sid1 = NULL;
  1674.             cur->next->pre = cur->pre;
  1675.             cur->pre->next = cur->next;
  1676.             break;
  1677.         }
  1678.         g_free(sid);
  1679.         sid = NULL;
  1680.         g_free(sid1);
  1681.         sid1 = NULL;
  1682.     }
  1683. }
  1684.  
  1685. TimeOutArgs *fx_list_find_timeout_by_sipuri(FxList *fxlist , const char *sipuri) {
  1686.     TimeOutArgs *args;
  1687.     FxList      *cur;
  1688.     gchar       *sid;
  1689.     gchar       *sid1;
  1690.  
  1691.     foreach_list(fxlist , cur) {
  1692.         args = (TimeOutArgs *)(cur->data);
  1693.         sid = fetion_sip_get_sid_by_sipuri(args->sipuri);
  1694.         sid1 = fetion_sip_get_sid_by_sipuri(sipuri);
  1695.         if(strcmp(sid , sid1) == 0) {
  1696.             g_free(sid);
  1697.             sid = NULL;
  1698.             g_free(sid1);
  1699.             sid1 = NULL;
  1700.             return args;
  1701.         }
  1702.         g_free(sid);
  1703.         sid = NULL;
  1704.         g_free(sid1);
  1705.         sid1 = NULL;
  1706.     }
  1707.     return NULL;
  1708. }
  1709.  
  1710. void fx_list_remove_timeout_by_sipuri(FxList *fxlist , const char *sipuri) {
  1711.     FxList      *cur;
  1712.     TimeOutArgs *args;
  1713.     gchar       *sid;
  1714.     gchar       *sid1;
  1715.  
  1716.     foreach_list(fxlist , cur) {
  1717.         args = (TimeOutArgs *)(cur->data);
  1718.         sid = fetion_sip_get_sid_by_sipuri(args->sipuri);
  1719.         sid1 = fetion_sip_get_sid_by_sipuri(sipuri);
  1720.         if(strcmp(sid , sid1) == 0) {
  1721.             cur->next->pre = cur->pre;
  1722.             cur->pre->next = cur->next;
  1723.             g_free(sid);
  1724.             sid = NULL;
  1725.             g_free(sid1);
  1726.             sid1 = NULL;
  1727.             g_free(cur);
  1728.             break;
  1729.         }
  1730.         g_free(sid);
  1731.         sid = NULL;
  1732.         g_free(sid1);
  1733.         sid1 = NULL;
  1734.     }
  1735.  
  1736. }
  1737.  
  1738. void fx_list_remove_pg_by_sipuri(FxList *fxlist , const char *sipuri) {
  1739.     FxList    *cur;
  1740.     FxPGGroup *fxpg;
  1741.  
  1742.     foreach_list(fxlist , cur) {
  1743.         fxpg = (FxPGGroup *)(cur->data);
  1744.         if(strcmp(fxpg->pggroup->pguri , sipuri) == 0) {
  1745.             cur->next->pre = cur->pre;
  1746.             cur->pre->next = cur->next;
  1747.             g_free(cur);
  1748.             break;
  1749.         }
  1750.     }
  1751.  
  1752. }
  1753.  
  1754. void fx_main_add_history(FxMain *fxmain, const char *name,
  1755.                          const char *sid, const char *msg, int issend) {
  1756.     History   *history;
  1757.     struct tm *now;
  1758.     User      *user;
  1759.  
  1760.     user = fxmain->user;
  1761.     now = get_currenttime();
  1762.  
  1763.     history = fetion_history_message_new(name
  1764.                                          , sid , *now , msg , issend);
  1765.  
  1766.     g_static_mutex_lock(&mutex);
  1767.     fetion_history_add(fxmain->history , history);
  1768.     fetion_history_message_free(history);
  1769.     g_static_mutex_unlock(&mutex);
  1770. }
  1771.  
  1772. static void fx_main_process_pggetgroupinfo(FxMain *fxmain , const char *sipmsg) {
  1773.     PGGroup *pggroup = fxmain->user->pggroup;
  1774.     pg_group_parse_info(pggroup , sipmsg);
  1775.     gdk_threads_enter();
  1776.     fx_tree_bind_pg_data(fxmain);
  1777.     gdk_threads_leave();
  1778.  
  1779. }
  1780. static void fx_main_process_pgpresencechanged(FxMain *fxmain , const char *sipmsg) {
  1781.     PGGroup *pggroup = fxmain->user->pggroup;
  1782.  
  1783.     pg_group_parse_member(pggroup , sipmsg);
  1784.  
  1785. #if 0
  1786.     PGGroup *pgcur;
  1787.     /* get member contact info of current group */
  1788.     foreach_pg_group(pggroup , pgcur) {
  1789.         if(pgcur->hasDetails == 0)
  1790.             pg_group_update_group_info(fxmain->user , pgcur);
  1791.     }
  1792. #endif
  1793. }
  1794.  
  1795. static gboolean key_press_func(GtkWidget *widget , GdkEventKey *event
  1796.                                , gpointer data) {
  1797.     if(event->keyval == GDK_w) {
  1798.         if(event->state & GDK_CONTROL_MASK) {
  1799.             gtk_window_iconify(GTK_WINDOW(widget));
  1800.             return TRUE;
  1801.         } else {
  1802.             return FALSE;
  1803.         }
  1804.     }
  1805.     if(event->keyval == GDK_q) {
  1806.         if(event->state & GDK_CONTROL_MASK) {
  1807.             fx_main_delete(widget , NULL , data);
  1808.             return TRUE;
  1809.         } else {
  1810.             return FALSE;
  1811.         }
  1812.     }
  1813.  
  1814.     return FALSE;
  1815. }
  1816.  

回复 "飞信源代码(c++)"

这儿你可以回复上面这条便签

captcha