home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / yagirc-0.51.tar.gz / yagirc-0.51.tar / yagirc-0.51 / gui_nicklist.c < prev    next >
C/C++ Source or Header  |  1998-05-09  |  11KB  |  396 lines

  1. /*
  2.  
  3.  gui_nicklist.c : User interface for handling nicklist
  4.  
  5.     Copyright (C) 1998 Timo Sirainen
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <ctype.h>
  25.  
  26. #include <gtk/gtk.h>
  27. #include <glib.h>
  28.  
  29. #include "irc.h"
  30. #include "gui.h"
  31. #include "commands.h"
  32. #include "script.h"
  33.  
  34. static int doubleclick = 0;
  35. static char *doublesel = NULL;
  36.  
  37. /* Redraw nick list */
  38. void gui_nicklist_redraw(WINDOW_REC *window)
  39. {
  40.     GtkWidget *listitem;
  41.     GList *nicks;
  42.     GList *nlist;
  43.  
  44.     g_return_if_fail(window != NULL);
  45.     g_return_if_fail(window->gui != NULL);
  46.  
  47.     if (window->gui->parent->nicklistlen > 0)
  48.     {
  49.         /* first clear list */
  50.         GList *tmp;
  51.  
  52.         for (tmp = GTK_LIST(window->gui->parent->nicklist)->children; tmp != NULL; tmp = tmp->next)
  53.             g_free(gtk_object_get_data(GTK_OBJECT(tmp->data), "nick"));
  54.         gtk_list_clear_items(GTK_LIST(window->gui->parent->nicklist), 0, window->gui->parent->nicklistlen);
  55.         window->gui->parent->nicklistlen = 0;
  56.     }
  57.  
  58.     if (window->curchan == NULL)
  59.     {
  60.         /* no channel selected in this window */
  61.         return;
  62.     }
  63.  
  64.     if (window->gui->parent->selected != window)
  65.     {
  66.         /* this window is hidden right now.. */
  67.         return;
  68.     }
  69.  
  70.     /* draw all items.. */
  71.     nlist = NULL;
  72.     nicks = g_list_first(window->curchan->nicks);
  73.     while (nicks != NULL)
  74.     {
  75.         listitem = gtk_list_item_new_with_label((char *) nicks->data);
  76.         gtk_object_set_data(GTK_OBJECT(listitem), "nick", g_strdup(nicks->data));
  77.         nlist = g_list_append(nlist, listitem);
  78.         gtk_widget_show(listitem);
  79.         nicks = nicks->next;
  80.         window->gui->parent->nicklistlen++;
  81.     }
  82.     gtk_list_append_items(GTK_LIST(window->gui->parent->nicklist), nlist);
  83. }
  84.  
  85. /* Remove nick from GUI nicklist */
  86. static char *gui_nicklist_remove(CHAN_REC *chan, char *nick)
  87. {
  88.     GList *pos, *list;
  89.     char *data;
  90.  
  91.     g_return_val_if_fail(chan != NULL, 0);
  92.     g_return_val_if_fail(nick != NULL, 0);
  93.     if (chan->window->curchan != chan) return NULL;
  94.  
  95.     if (isircflag(*nick)) nick++; /* Skip @ and + */
  96.  
  97.     for (pos = GTK_LIST(chan->window->gui->parent->nicklist)->children; pos != NULL; pos = pos->next)
  98.     {
  99.         data = gtk_object_get_data(GTK_OBJECT(pos->data), "nick");
  100.         if (strcasecmp(isircflag(*data) ? data+1 : data, nick) == 0)
  101.             break;
  102.     }
  103.     if (pos == NULL) return NULL;
  104.  
  105.     list = g_list_append(NULL, pos->data);
  106.     gtk_list_remove_items(GTK_LIST(chan->window->gui->parent->nicklist), list);
  107.     chan->window->gui->parent->nicklistlen--;
  108.     g_list_free(list);
  109.     return data;
  110. }
  111.  
  112. /* Add nick to list */
  113. static int gui_nicklist_add(CHAN_REC *chan, char *nick)
  114. {
  115.     g_return_val_if_fail(chan != NULL, 0);
  116.     g_return_val_if_fail(nick != NULL, 0);
  117.  
  118.     if (chan->window->curchan == chan)
  119.     {
  120.         GList *list, *nlist;
  121.         GtkWidget *listitem;
  122.         int pos;
  123.  
  124.         listitem = gtk_list_item_new_with_label(nick);
  125.         gtk_object_set_data(GTK_OBJECT(listitem), "nick", g_strdup(nick));
  126.         gtk_widget_show(listitem);
  127.  
  128.         list = g_list_append(NULL, listitem);
  129.  
  130.         nlist = GTK_LIST(chan->window->gui->parent->nicklist)->children;
  131.         for (pos = 0; nlist != NULL; pos++, nlist = nlist->next)
  132.         {
  133.             char *data;
  134.  
  135.             data = gtk_object_get_data(GTK_OBJECT(nlist->data), "nick");
  136.             if (irc_nicks_compare(data, nick) > 0) break;
  137.         }
  138.         gtk_list_insert_items(GTK_LIST(chan->window->gui->parent->nicklist), list, pos);
  139.         chan->window->gui->parent->nicklistlen++;
  140.     }
  141.  
  142.     return 1;
  143. }
  144.  
  145. /* Change nick name */
  146. void gui_nick_change(SERVER_REC *server, char *from, char *to)
  147. {
  148.     GList *chanlist, *win;
  149.     char *tmp, *ptr;
  150.  
  151.     g_return_if_fail(server != NULL);
  152.     g_return_if_fail(from != NULL);
  153.     g_return_if_fail(to != NULL);
  154.  
  155.     tmp = (char *) g_malloc(strlen(to)+2);
  156.     strcpy(tmp+1, to);
  157.  
  158.     /* scan all windows */
  159.     for (win = g_list_first(winlist); win != NULL; win = win->next)
  160.     {
  161.         /* scan all channels */
  162.         for (chanlist = g_list_first(((WINDOW_REC *) win->data)->chanlist); chanlist != NULL; chanlist = chanlist->next)
  163.         {
  164.             char *rnick;
  165.             CHAN_REC *chan;
  166.  
  167.             chan = (CHAN_REC *) chanlist->data;
  168.             if (chan->server != server)
  169.             {
  170.                 /* nick wasn't changed in this server.. */
  171.                 continue;
  172.             }
  173.  
  174.             rnick = gui_nicklist_remove(chan, from);
  175.             if (rnick != NULL)
  176.             {
  177.                 /* nick found from this channel */
  178.                 tmp[0] = *rnick;
  179.                 ptr = isircflag(tmp[0]) ? tmp : tmp+1;
  180.                 gui_nicklist_add(chan, ptr);
  181.                 g_free(rnick);
  182.             }
  183.         }
  184.     }
  185.     g_free(tmp);
  186. }
  187.  
  188. /* Change nick's mode (@, +) */
  189. void gui_change_nick_mode(CHAN_REC *chan, char *nick, char type)
  190. {
  191.     char *rnick, *tmp, *ptr;
  192.  
  193.     g_return_if_fail(chan != NULL);
  194.     g_return_if_fail(nick != NULL);
  195.  
  196.     rnick = gui_nicklist_remove(chan, nick);
  197.     if (rnick != NULL)
  198.     {
  199.         tmp = (char *) g_malloc(strlen(nick)+2);
  200.         sprintf(tmp, "%c%s", type, nick);
  201.  
  202.         ptr = tmp[0] == ' ' ? tmp+1 : tmp;
  203.         gui_nicklist_add(chan, ptr);
  204.  
  205.         g_free(tmp);
  206.         g_free(rnick);
  207.     }
  208. }
  209.  
  210. /* Someone joined some channel.. If nick==NULL, you joined */
  211. void gui_channel_join(CHAN_REC *chan, char *nick)
  212. {
  213.     int scroll_down;
  214.  
  215.     g_return_if_fail(chan != NULL);
  216.  
  217.     if (nick == NULL)
  218.     {
  219.         /* You joined to channel */
  220.         scroll_down = gui_is_sb_down(chan->window);
  221.         chan->gui = gui_private_add_channel_button(GTK_BOX(chan->window->gui->parent->chanbox), chan);
  222.         gui_draw_channel(chan->window, chan);
  223.         if (scroll_down) gui_set_sb_down(chan->window);
  224.         return;
  225.     }
  226.  
  227.     /* someone else joined some channel */
  228.     gui_nicklist_add(chan, nick);
  229. }
  230.  
  231. /* Someone left some channel.. If nick==NULL, you left, if chan==NULL someone
  232.    quit from IRC */
  233. void gui_channel_part(CHAN_REC *chan, char *nick)
  234. {
  235.     GList *tmplist, *win;
  236.  
  237.     if (nick == NULL)
  238.     {
  239.         /* You've left some channel */
  240.         int scroll_down;
  241.  
  242.         if (chan == NULL) return;
  243.         scroll_down = gui_is_sb_down(chan->window);
  244.  
  245.         gui_draw_channel(chan->window, chan->window->curchan);
  246.         gui_private_remove_channel_button(chan);
  247.         if (scroll_down) gui_set_sb_down(chan->window);
  248.         return;
  249.     }
  250.  
  251.     if (chan != NULL)
  252.     {
  253.         /* Someone left some channel */
  254.         char *rnick = gui_nicklist_remove(chan, nick);
  255.         if (rnick != NULL) g_free(rnick);
  256.         return;
  257.     }
  258.  
  259.     /* Someone quit IRC, remove nick from all channels */
  260.     for (win = g_list_first(winlist); win != NULL; win = win->next)
  261.     {
  262.         WINDOW_REC *winrec;
  263.  
  264.         winrec = (WINDOW_REC *) win->data;
  265.         for (tmplist = g_list_first(winrec->chanlist); tmplist != NULL; tmplist = tmplist->next)
  266.         {
  267.             char *rnick;
  268.             rnick = gui_nicklist_remove((CHAN_REC *) tmplist->data, nick);
  269.             if (rnick != NULL) g_free(rnick);
  270.         }
  271.     }
  272. }
  273.  
  274. /* signal: button pressed */
  275. void signick_button_pressed(GtkWidget *widget, GdkEventButton *event)
  276. {
  277.     GList *sel;
  278.  
  279.     g_return_if_fail(widget != NULL);
  280.     g_return_if_fail(event != NULL);
  281.  
  282.     if (event->button == 1)
  283.     {
  284.         if (!doubleclick || doublesel == NULL)
  285.         {
  286.             sel = GTK_LIST(widget)->selection;
  287.             if (sel != NULL)
  288.                 doublesel = gtk_object_get_data(GTK_OBJECT(sel->data), "nick");
  289.             else
  290.                 doublesel = NULL;
  291.         }
  292.         if (doubleclick)
  293.         {
  294.             /* doubleclicked - query user */
  295.             doubleclick = 0;
  296.  
  297.             if (doublesel != NULL)
  298.             {
  299.                 if (isircflag(*doublesel)) doublesel++;
  300.                 irccmd_query(doublesel);
  301.                 doublesel = NULL;
  302.             }
  303.         }
  304.         else
  305.         {
  306.             doubleclick = 1;
  307.         }
  308.     }
  309. }
  310.  
  311. /* signal: button released */
  312. void signick_button_released(GtkWidget *widget, GdkEventButton *event)
  313. {
  314.     char *nick;
  315.  
  316.     g_return_if_fail(widget != NULL);
  317.     g_return_if_fail(event != NULL);
  318.  
  319.     if (event->button == 1)
  320.     {
  321.         doubleclick = 0;
  322.         doublesel = NULL;
  323.     }
  324.     if (event->button == 3)
  325.     {
  326.         /* show popup menu */
  327.         GList *sel;
  328.  
  329.         sel = (GList *) GTK_LIST(widget)->selection;
  330.         if (sel == NULL) return;
  331.         nick = gtk_object_get_data(GTK_OBJECT(sel->data), "nick");
  332.         if (isircflag(*nick)) nick++;
  333.  
  334.         nicklist_popup(NULL, nick, event);
  335.     }
  336. }
  337.  
  338. /* gtk_menu_popup() position function */
  339. static void posfunc(GtkMenu *menu, gint *x, gint *y, GdkEventButton *event)
  340. {
  341.     g_return_if_fail(x != NULL);
  342.     g_return_if_fail(y != NULL);
  343.     g_return_if_fail(event != NULL);
  344.  
  345.     *x = event->x_root;
  346.     *y = event->y_root;
  347. }
  348.  
  349. /* popup menu: CTCP PING */
  350. static void nicklist_ctcp_ping(char *nick)
  351. {
  352.     char *tmp;
  353.  
  354.     g_return_if_fail(nick != NULL);
  355.  
  356.     tmp = (char *) g_malloc(strlen(nick)+6);
  357.     sprintf(tmp, "%s PING", nick);
  358.     irccmd_ctcp(tmp);
  359. }
  360.  
  361. /* popup menu: CTCP VERSION */
  362. static void nicklist_ctcp_version(char *nick)
  363. {
  364.     char *tmp;
  365.  
  366.     g_return_if_fail(nick != NULL);
  367.  
  368.     tmp = (char *) g_malloc(strlen(nick)+9);
  369.     sprintf(tmp, "%s VERSION", nick);
  370.     irccmd_ctcp(tmp);
  371. }
  372.  
  373. /* Nicklist's popup menu */
  374. void nicklist_popup(GtkWidget *menu, char *nick, GdkEventButton *event)
  375. {
  376.     GtkWidget *mymenu, *ctcpmenu;
  377.  
  378.     g_return_if_fail(nick != NULL);
  379.     g_return_if_fail(menu != NULL || event != NULL);
  380.  
  381.     mymenu = menu != NULL ? menu : gtk_menu_new();
  382.  
  383.     ctcpmenu = gtk_menu_new();
  384.     add_popup(mymenu, "Whois", irccmd_whois, nick);
  385.     add_popup(mymenu, "Query", irccmd_query, nick);
  386.     add_popup(ctcpmenu, "Ping", nicklist_ctcp_ping, nick);
  387.     add_popup(ctcpmenu, "Version", nicklist_ctcp_version, nick);
  388.     add_popup_sub(mymenu, "CTCP", ctcpmenu);
  389. #ifdef USE_SCRIPT
  390.     script_add_popups(mymenu, POPUPMENU_NICK, nick);
  391. #endif
  392.  
  393.     if (menu == NULL)
  394.         gtk_menu_popup (GTK_MENU(mymenu), NULL, NULL, (GtkMenuPositionFunc) posfunc, event, 0, event->time);
  395. }
  396.