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_channels.c < prev    next >
C/C++ Source or Header  |  1998-05-11  |  10KB  |  346 lines

  1. /*
  2.  
  3.  gui_channels.c : User interface for handling channels
  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.  
  25. #include <gtk/gtk.h>
  26. #include <glib.h>
  27.  
  28. #include "dcc.h"
  29. #include "irc.h"
  30. #include "gui.h"
  31. #include "commands.h"
  32. #include "script.h"
  33.  
  34. static void chanlist_popup(CHAN_REC *chan, GdkEventButton *event);
  35.  
  36. /* Hilight channel button */
  37. void gui_channel_hilight(CHAN_REC *chan)
  38. {
  39.     GtkStyle style;
  40.     GtkWidget *wid;
  41.  
  42.     g_return_if_fail(chan != NULL);
  43.  
  44.     /* hilight new selected channel */
  45.     wid = gtk_container_children(GTK_CONTAINER(chan->gui))->data;
  46.     memcpy(&style, gtk_widget_get_style(wid), sizeof(style));
  47.     style.fg[0] = colors[BRED];
  48.     gtk_widget_set_style(wid, &style);
  49. }
  50.  
  51. /* Dehilight channel button */
  52. void gui_channel_dehilight(CHAN_REC *chan)
  53. {
  54.     GtkStyle style;
  55.     GtkWidget *wid;
  56.  
  57.     g_return_if_fail(chan != NULL);
  58.  
  59.     /* hilight new selected channel */
  60.     wid = gtk_container_children(GTK_CONTAINER(chan->gui))->data;
  61.     memcpy(&style, gtk_widget_get_style(wid), sizeof(style));
  62.     style.fg[0] = colors[BLACK];
  63.     gtk_widget_set_style(wid, &style);
  64. }
  65.  
  66. /* Channel changed in window - draw new topic, nicks, hilight channel button */
  67. void gui_draw_channel(WINDOW_REC *win, CHAN_REC *chan)
  68. {
  69.     g_return_if_fail(win != NULL);
  70.  
  71.     gui_nicklist_redraw(win);
  72.  
  73.     if (win->gui->parent->highchan != NULL)
  74.     {
  75.         /* Some channel was already hilighted, change it back to black */
  76.         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(win->gui->parent->highchan->gui), FALSE);
  77.     }
  78.  
  79.     if (chan == NULL)
  80.     {
  81.         /* just dehighlighted channel - no channel selected now.. */
  82.         gtk_window_set_title(GTK_WINDOW(win->gui->parent->mainwin), PROGRAM_TITLE);
  83.         win->gui->parent->highchan = NULL;
  84.         return;
  85.     }
  86.  
  87.     /* draw topic */
  88.     gui_change_topic(chan);
  89.  
  90.     /* hilight new selected channel */
  91.     win->gui->parent->highchan = chan;
  92.     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(chan->gui), TRUE);
  93. }
  94.  
  95. /* signal: channel clicked */
  96. static void sigchan_clicked(GtkWidget *widget, CHAN_REC *chan)
  97. {
  98.     char *tmp;
  99.  
  100.     if (chan->window->gui->parent->highchan == chan) return;
  101.  
  102.     if (chan->window != curwin) gui_window_select(chan->window);
  103.     gui_draw_channel(chan->window, chan);
  104.  
  105.     /* gtk's clicked-signal changes this back to TRUE... */
  106.     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(chan->gui), FALSE);
  107.  
  108.     tmp = (char *) g_malloc(strlen(chan->name)+20);
  109.     sprintf(tmp, "%d %s", chan->server->handle, chan->name);
  110.  
  111.     if (*chan->name == '&' || *chan->name == '#')
  112.         irccmd_join(tmp);
  113.     else
  114.         irccmd_query(tmp);
  115.  
  116.     g_free(tmp);
  117. }
  118.  
  119. /* signal: button released */
  120. static void sigchan_button_released(GtkWidget *widget, GdkEventButton *event, CHAN_REC *chan)
  121. {
  122.     g_return_if_fail(chan != NULL);
  123.  
  124.     if (event->button == 3)
  125.         chanlist_popup(chan, event);
  126. }
  127.  
  128. /* signal: started dragging */
  129. static void sigchan_drag(GtkWidget *widget, GdkEvent *event, CHAN_REC *chan)
  130. {
  131.     g_return_if_fail(chan != NULL);
  132.  
  133.     gtk_widget_dnd_data_set (widget, event, &chan, sizeof(CHAN_REC **));
  134. }
  135.  
  136. /* signal: dropped something here */
  137. static void sigchan_drop(GtkWidget *widget, GdkEvent *event, CHAN_REC *chan)
  138. {
  139.     CHAN_REC *from;
  140.  
  141.     g_return_if_fail(chan != NULL);
  142.  
  143.     from = *((CHAN_REC **) event->dropdataavailable.data);
  144.     if (from == curwin->curchan)
  145.         gui_window_select(chan->window);
  146.     gui_select_channel(chan->window, from);
  147. }
  148.  
  149. /* Draw new channel button */
  150. GtkWidget *gui_private_add_channel_button(GtkBox *box, CHAN_REC *chan)
  151. {
  152.     GtkWidget *but;
  153.     char *channel_drag_types[] = {"yagirc/channel"};
  154.     char *channel_drop_types[] = {"yagirc/channel"};
  155.  
  156.     g_return_val_if_fail(box != NULL, NULL);
  157.     g_return_val_if_fail(chan != NULL, NULL);
  158.  
  159.     /* create widget */
  160.     but = gtk_toggle_button_new_with_label(chan->name);
  161.     gtk_signal_connect (GTK_OBJECT (but), "button_release_event",
  162.                         GTK_SIGNAL_FUNC(sigchan_button_released), chan);
  163.     gtk_signal_connect (GTK_OBJECT (but), "clicked",
  164.                         GTK_SIGNAL_FUNC(sigchan_clicked), chan);
  165.     gtk_signal_connect (GTK_OBJECT (but), "drag_request_event",
  166.                         GTK_SIGNAL_FUNC(sigchan_drag), chan);
  167.     gtk_signal_connect (GTK_OBJECT (but), "drop_data_available_event",
  168.                         GTK_SIGNAL_FUNC(sigchan_drop), chan);
  169.     gtk_box_pack_start(box, but, FALSE, FALSE, 0);
  170.     gtk_widget_show(but);
  171.  
  172.     gtk_widget_dnd_drag_set (but, TRUE, channel_drag_types, 1);
  173.     gtk_widget_dnd_drop_set (but, TRUE, channel_drop_types, 1, FALSE);
  174.  
  175.     return but;
  176. }
  177.  
  178. /* Remove channel button */
  179. void gui_private_remove_channel_button(CHAN_REC *chan)
  180. {
  181.     g_return_if_fail(chan != NULL);
  182.  
  183.     if (chan->window->gui->parent->highchan == chan)
  184.     {
  185.         /* this channel was highlighted.. */
  186.         chan->window->gui->parent->highchan = NULL;
  187.     }
  188.     gtk_widget_destroy(chan->gui);
  189. }
  190.  
  191. /* Select channel in specific window, if channel is in some other window,
  192.    move it from there */
  193. void gui_select_channel(WINDOW_REC *win, CHAN_REC *chan)
  194. {
  195.     GList *oldchan;
  196.  
  197.     g_return_if_fail(win != NULL);
  198.     g_return_if_fail(chan != NULL);
  199.  
  200.     if (chan->window != win)
  201.     {
  202.         /* we need to move channel into this window.. */
  203.         WINDOW_REC *oldwin;
  204.  
  205.         oldwin = chan->window;
  206.         gui_private_remove_channel_button(chan);
  207.         chan->window = win;
  208.         chan->gui = gui_private_add_channel_button(GTK_BOX(win->gui->parent->chanbox), chan);
  209.  
  210.         for (oldchan = g_list_first(oldwin->chanlist); oldchan != NULL; oldchan = oldchan->next)
  211.             if (oldchan->data == chan) break;
  212.  
  213.         win->chanlist = g_list_append(win->chanlist, oldchan->data);
  214.  
  215.         if (oldwin->curchan != chan)
  216.             oldwin->chanlist = g_list_remove_link(oldwin->chanlist, oldchan);
  217.         else
  218.         {
  219.             int ret;
  220.             WINDOW_REC *win;
  221.  
  222.             win = curwin;
  223.  
  224.             /* channel was selected in it's old window */
  225.             ret = irc_select_new_channel(oldwin);
  226.             oldwin->chanlist = g_list_remove_link(oldwin->chanlist, oldchan);
  227.             if (ret == 0)
  228.             {
  229.                 /* no more channels in this window - remove it */
  230.                 irc_window_close(oldwin);
  231.             }
  232.             else
  233.             {
  234.                 /* draw topic */
  235.                 gui_draw_channel(oldwin, oldwin->curchan);
  236.             }
  237.             curwin = win;
  238.         }
  239.     }
  240.  
  241.     gui_draw_channel(win, chan);
  242. }
  243.  
  244. /* Change topic of channel */
  245. void gui_change_topic(CHAN_REC *chan)
  246. {
  247.     char *tmp;
  248.  
  249.     g_return_if_fail(chan != NULL);
  250.     if (chan->window->curchan != chan) return;
  251.  
  252.     if (chan->topic == NULL || *chan->topic == '\0')
  253.     {
  254.         /* No topic in channel */
  255.         tmp = (char *) g_malloc(strlen(chan->name)+PROGRAM_TITLE_SIZE+10);
  256.         sprintf(tmp, "%s - "PROGRAM_TITLE, chan->name);
  257.     }
  258.     else
  259.     {
  260.         tmp = (char *) g_malloc(strlen(chan->name)+strlen(chan->topic)+PROGRAM_TITLE_SIZE+10);
  261.         sprintf(tmp, "%s - %s - "PROGRAM_TITLE, chan->name, chan->topic);
  262.     }
  263.     gtk_window_set_title(GTK_WINDOW(chan->window->gui->parent->mainwin), tmp);
  264.     g_free(tmp);
  265. }
  266.  
  267. void sigchantext_button_released(GtkWidget *widget, GdkEventButton *event, WINDOW_REC *win)
  268. {
  269.     g_return_if_fail(widget != NULL);
  270.     g_return_if_fail(event != NULL);
  271.     g_return_if_fail(win != NULL);
  272.  
  273.     if (event->button == 3)
  274.     {
  275.         /* show popup menu */
  276.         if (win->curchan != NULL)
  277.             chanlist_popup(win->curchan, event);
  278.     }
  279. }
  280.  
  281. /* channel menu: move channel to new window */
  282. static void move_new_window(CHAN_REC *chan)
  283. {
  284.     WINDOW_REC *win;
  285.  
  286.     win = irc_window_new(chan->server, NULL);
  287.     win->curchan = chan;
  288.     gui_select_channel(win, chan);
  289. }
  290.  
  291. /* channel menu: move channel to new hidden window */
  292. static void move_new_hidden(CHAN_REC *chan)
  293. {
  294.     WINDOW_REC *win;
  295.  
  296.     win = irc_window_new(chan->server, chan->window);
  297.     win->curchan = chan;
  298.     gui_select_channel(win, chan);
  299. }
  300.  
  301. /* gtk_menu_popup() position function */
  302. static void posfunc(GtkMenu *menu, gint *x, gint *y, GdkEventButton *event)
  303. {
  304.     g_return_if_fail(x != NULL);
  305.     g_return_if_fail(y != NULL);
  306.     g_return_if_fail(event != NULL);
  307.  
  308.     *x = event->x_root;
  309.     *y = event->y_root;
  310. }
  311.  
  312. /* Channel popup menu */
  313. static void chanlist_popup(CHAN_REC *chan, GdkEventButton *event)
  314. {
  315.     GtkWidget *menu, *movemenu;
  316.  
  317.     g_return_if_fail(chan != NULL);
  318.     g_return_if_fail(event != NULL);
  319.  
  320.     menu = gtk_menu_new();
  321.  
  322.     movemenu = gtk_menu_new();
  323.     add_popup(movemenu, "New window", move_new_window, chan);
  324.     add_popup(movemenu, "New hidden window", move_new_hidden, chan);
  325.  
  326.     if (*chan->name == '#' || *chan->name == '&')
  327.     {
  328.         add_popup(menu, "Channel commands", NULL, NULL);
  329.         add_popup(menu, NULL, NULL, NULL);
  330.         add_popup(menu, "Part", irccmd_part, chan->name);
  331. #ifdef USE_SCRIPT
  332.         script_add_popups(menu, POPUPMENU_CHAN, chan->name);
  333. #endif
  334.     }
  335.     else
  336.     {
  337.         add_popup(menu, "Query commands", NULL, NULL);
  338.         add_popup(menu, NULL, NULL, NULL);
  339.         add_popup(menu, "Close query", irccmd_unquery, chan->name);
  340.         nicklist_popup(menu, chan->name, event);
  341.     }
  342.  
  343.     add_popup_sub(menu, "Move", movemenu);
  344.     gtk_menu_popup (GTK_MENU(menu), NULL, NULL, (GtkMenuPositionFunc) posfunc, event, 0, event->time);
  345. }
  346.