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

  1. /*
  2.  
  3.  gui.c : User interface
  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 <signal.h>
  25. #include <ctype.h>
  26.  
  27. #include <gtk/gtk.h>
  28. #include <gdk/gdkkeysyms.h>
  29. #include <glib.h>
  30.  
  31. #include "os.h"
  32. #include "gui.h"
  33. #include "txt.h"
  34. #include "irc.h"
  35. #include "commands.h"
  36.  
  37. /*#include <gdk/gdkx.h>
  38. #include <X11/Xlib.h>*/
  39.  
  40. /* default colors */
  41. GdkColor colors[] =
  42. {
  43.     { 0, 0, 0, 0 },
  44.     { 0, 0, 0, 0 },
  45.     { 0, 0, 0, 0x7fff },
  46.     { 0, 0, 0x7fff, 0 },
  47.     { 0, 0, 0x7fff, 0x7fff },
  48.     { 0, 0x7fff, 0, 0 },
  49.     { 0, 0x7fff, 0, 0x7fff },
  50.     { 0, 0x7fff, 0x7fff, 0 },
  51.     { 0, 0xbfff, 0xbfff, 0xbfff },
  52.     { 0, 0x3fff, 0x3fff, 0x3fff },
  53.     { 0, 0, 0, 0xffff },
  54.     { 0, 0, 0xffff, 0 },
  55.     { 0, 0, 0xffff, 0xffff },
  56.     { 0, 0xffff, 0, 0 },
  57.     { 0, 0xffff, 0, 0xffff },
  58.     { 0, 0xffff, 0xffff, 0 },
  59.     { 0, 0xffff, 0xffff, 0xffff },
  60. };
  61.  
  62. GdkColor default_color, default_bgcolor;
  63. GdkColor yag_colors[15];
  64.  
  65. /* command history */
  66. #define MAX_CMDHIST_LINES 100
  67. static GList *cmdhist, *histpos;
  68. static int histlines;
  69.  
  70. static int setup_open;
  71.  
  72. #define FLAG_BOLD 1
  73. #define FLAG_REVERSE 2
  74. #define FLAG_UNDERLINE 4
  75.  
  76. static GdkFont *font_normal, *font_bold, *font_italic, *font_bolditalic;
  77.  
  78. static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
  79.  
  80. /* parse ANSI color string */
  81. static char *convert_ansi(char *str, int *fgcolor, int *bgcolor, int *flags)
  82. {
  83.     char *start;
  84.     int fg, bg, fl, num;
  85.  
  86.     if (*str != '[') return str;
  87.  
  88.     start = str;
  89.     fg = *fgcolor-1; bg = *bgcolor; fl = *flags;
  90.     if (bg != -1) bg--;
  91.  
  92.     str++; num = 0;
  93.     for (;; str++)
  94.     {
  95.         if (*str == '\0') return start;
  96.  
  97.         if (isdigit(*str))
  98.         {
  99.             num = num*10 + (*str-'0');
  100.             continue;
  101.         }
  102.  
  103.         if (*str != ';' && *str != 'm') return start;
  104.  
  105.         switch (num)
  106.         {
  107.             case 0:
  108.                 /* reset colors back to default */
  109.                 fg = 7;
  110.                 bg = -1;
  111.                 break;
  112.             case 1:
  113.                 /* hilight */
  114.                 fg |= 8;
  115.                 break;
  116.             case 5:
  117.                 /* blink */
  118.                 bg = bg == -1 ? 8 : bg | 8;
  119.                 break;
  120.             case 7:
  121.                 /* reverse */
  122.                 fl |= FLAG_REVERSE;
  123.                 break;
  124.             default:
  125.                 if (num >= 30 && num <= 37)
  126.                     fg = (fg & 0xf8) + ansitab[num-30];
  127.                 if (num >= 40 && num <= 47)
  128.                 {
  129.                     if (bg == -1) bg = 0;
  130.                     bg = (bg & 0xf8) + ansitab[num-40];
  131.                 }
  132.                 break;
  133.         }
  134.         num = 0;
  135.  
  136.         if (*str == 'm')
  137.         {
  138.             *fgcolor = fg+1;
  139.             *bgcolor = bg == -1 ? -1 : bg+1;
  140.             *flags = fl;
  141.             str++;
  142.             break;
  143.         }
  144.     }
  145.  
  146.     return str;
  147. }
  148.  
  149. int gui_is_sb_down(WINDOW_REC *win)
  150. {
  151.     GtkAdjustment *adj;
  152.  
  153.     g_return_val_if_fail(win != NULL, 1);
  154.     g_return_val_if_fail(win->gui != NULL, 1);
  155.  
  156.     adj = win->gui->text->vadj;
  157.     return adj->value == adj->upper - adj->lower - adj->page_size;
  158. }
  159.  
  160. void gui_set_sb_down(WINDOW_REC *win)
  161. {
  162.     GtkAdjustment *adj;
  163.  
  164.     g_return_if_fail(win != NULL);
  165.     g_return_if_fail(win->gui != NULL);
  166.  
  167.     adj = win->gui->text->vadj;
  168.     gtk_adjustment_set_value(adj, adj->upper - adj->lower - adj->page_size);
  169. }
  170.  
  171. /* Write text to window */
  172. static void printtext(char *str, WINDOW_REC *win)
  173. {
  174.     char *ptr, type;
  175.     GdkColor *fg, *bg;
  176.     int fgcolor, bgcolor;
  177.     int flags;
  178.  
  179.     int scroll_down;
  180.  
  181.     g_return_if_fail(str != NULL);
  182.     g_return_if_fail(win != NULL);
  183.     g_return_if_fail(win->gui != NULL);
  184.  
  185.     scroll_down = gui_is_sb_down(win);
  186.  
  187.     gtk_text_freeze (win->gui->text);
  188.     gtk_text_insert (win->gui->text, NULL, NULL, NULL, "\n", 1);
  189.     if (win->gui->lines < MAX_TEXTLINES_HISTORY)
  190.     {
  191.         win->gui->linelen[win->gui->lines++] = strlen(str)+1;
  192.     }
  193.     else
  194.     {
  195.         gtk_text_set_point(win->gui->text, 0);
  196.         gtk_text_forward_delete(win->gui->text, win->gui->linelen[0]);
  197.         gtk_text_set_point(win->gui->text, gtk_text_get_length(win->gui->text));
  198.         memmove(win->gui->linelen, &win->gui->linelen[1],
  199.                 (MAX_TEXTLINES_HISTORY-1)*sizeof(win->gui->linelen[0]));
  200.         win->gui->linelen[MAX_TEXTLINES_HISTORY-1] = strlen(str)+1;
  201.     }
  202.  
  203.     flags = 0;
  204.     fg = &default_color; fgcolor = -2; bgcolor = -1; type = '\0';
  205.     while (*str != '\0')
  206.     {
  207.         for (ptr = str; *ptr != '\0'; ptr++)
  208.             if (*ptr == 2 || *ptr == 3 || *ptr == 4 || *ptr == 22 || *ptr == 27 || *ptr == 31)
  209.             {
  210.                 type = *ptr;
  211.                 *ptr++ = '\0';
  212.                 break;
  213.             }
  214.  
  215.         if (*str != '\0')
  216.         {
  217.             GdkFont *font;
  218.  
  219.             if (flags & FLAG_BOLD)
  220.                 font = flags & FLAG_UNDERLINE ? font_bolditalic : font_bold;
  221.             else if (flags & FLAG_UNDERLINE)
  222.                 font = font_italic;
  223.             else
  224.                 font = font_normal;
  225.  
  226.             if (flags & FLAG_REVERSE)
  227.             {
  228.                 if (fgcolor == -2) bg = fg; else bg = &colors[fgcolor];
  229.                 fg = bgcolor == -1 ? &default_bgcolor : &colors[bgcolor];
  230.             }
  231.             else
  232.             {
  233.                 if (fgcolor != -2) fg = &colors[fgcolor];
  234.                 bg = bgcolor == -1 ? NULL : &colors[bgcolor];
  235.             }
  236.             gtk_text_insert (win->gui->text, font, fg, bg, str, -1);
  237.         }
  238.         if (*ptr == '\0') break;
  239.  
  240.         if (type == '\0')
  241.         {
  242.             /* ... */
  243.         }
  244.         else if (type == 2)
  245.         {
  246.             /* bold */
  247.             flags ^= FLAG_BOLD;
  248.         }
  249.         else if (type == 22)
  250.         {
  251.             /* reverse */
  252.             flags ^= FLAG_REVERSE;
  253.         }
  254.         else if (type == 31)
  255.         {
  256.             /* underline, display as italic.. */
  257.             flags ^= FLAG_UNDERLINE;
  258.         }
  259.         else if (type == 27)
  260.         {
  261.             /* ansi color code */
  262.             ptr = convert_ansi(ptr, &fgcolor, &bgcolor, &flags);
  263.         }
  264.         else if (type == 4)
  265.         {
  266.             /* user specific colors */
  267.             fg = &yag_colors[((int) *ptr++)-1];
  268.             fgcolor = -2;
  269.             bgcolor = -1;
  270.         }
  271.         else if (type == 3)
  272.         {
  273.             /* color! */
  274.             if (*ptr < 16)
  275.             {
  276.                 fgcolor = *ptr++;
  277.                 bgcolor = -1;
  278.             }
  279.             else
  280.             {
  281.                 fgcolor = 0; bgcolor = -1;
  282.                 if (!isdigit(*ptr))
  283.                     fgcolor = -2;
  284.                 else
  285.                 {
  286.                     /* foreground color */
  287.                     fgcolor = *ptr++-'0';
  288.                     if (isdigit(*ptr))
  289.                         fgcolor = fgcolor*10 + (*ptr++-'0');
  290.                     fgcolor++;
  291.                     if (*ptr == ',')
  292.                     {
  293.                         /* back color */
  294.                         bgcolor = 0;
  295.                         if (!isdigit(*++ptr))
  296.                             bgcolor = -1;
  297.                         else
  298.                         {
  299.                             bgcolor = *ptr++-'0';
  300.                             if (isdigit(*ptr))
  301.                                 bgcolor = bgcolor*10 + (*ptr++-'0');
  302.                             bgcolor++;
  303.                         }
  304.                     }
  305.                 }
  306.             }
  307.         }
  308.  
  309.         str = ptr;
  310.     }
  311.     gtk_text_thaw (win->gui->text);
  312.  
  313.     if (scroll_down) gui_set_sb_down(win);
  314. }
  315.  
  316. void gui_update_statusbar(WINDOW_REC *win)
  317. {
  318.     char str[200];
  319.     int connected;
  320.     GList *tmp;
  321.     int windows;
  322.     char *act, *ptr;
  323.  
  324.     if (win != NULL && win != win->gui->parent->selected)
  325.     {
  326.         /* window is hidden - status doesn't need to be displayed */
  327.         return;
  328.     }
  329.  
  330.     /* find which windows have new text */
  331.     windows = g_list_length(winlist);
  332.  
  333.     if (windows == 0)
  334.         act = NULL;
  335.     else
  336.     {
  337.         act = (char *) g_malloc0(windows*(sprintf(str, "%d", windows)+1)+10);
  338.  
  339.         ptr = act;
  340.         for (tmp = g_list_first(winlist); tmp != NULL; tmp = tmp->next)
  341.         {
  342.             WINDOW_REC *w;
  343.  
  344.             w = (WINDOW_REC *) tmp->data;
  345.             if (w->new_data)
  346.             {
  347.                 if (act == ptr) ptr += sprintf(ptr, "[ act: ");
  348.                 ptr += sprintf(ptr, "%d ", w->num);
  349.             }
  350.         }
  351.         if (ptr != act) strcpy(ptr, "]");
  352.     }
  353.  
  354.     for (tmp = g_list_first(winlist); tmp != NULL || win != NULL; tmp = tmp->next)
  355.     {
  356.         WINDOW_REC *w;
  357.         SERVER_REC *server;
  358.  
  359.         w = win != NULL ? win : (WINDOW_REC *) tmp->data;
  360.  
  361.         server = w->curchan == NULL ? w->defserv : w->curchan->server;
  362.         connected = server != NULL && server->connected;
  363.         g_snprintf(str, 200, "[ window %d ] [ %s ] [ %s%s ] %s",
  364.                    w->num,
  365.                    connected ? server->nick : default_nick,
  366.                    connected ? _("Connected to ") : _("Not connected"),
  367.                    connected ? server->name : "",
  368.                    act == NULL ? "" : act);
  369.  
  370.         gtk_statusbar_pop(GTK_STATUSBAR(w->gui->parent->statusbar), 1);
  371.         gtk_statusbar_push(GTK_STATUSBAR(w->gui->parent->statusbar), 1, str);
  372.         if (win != NULL) break;
  373.     }
  374.     if (act != NULL) g_free(act);
  375. }
  376.  
  377. void gui_set_style(GtkWidget *widget, char *channel)
  378. {
  379.     GtkStyle style;
  380.     GdkPixmap *pixmap;
  381.     GdkBitmap *mask;
  382.  
  383.     memcpy(&style, gtk_widget_get_style(widget), sizeof(GtkStyle));
  384.  
  385.     /* single color */
  386.     style.bg[0] = default_bgcolor;
  387.     gdk_color_alloc(gtk_widget_get_colormap(widget), &default_bgcolor);
  388.  
  389.     if (default_text_pixmap != NULL)
  390.     {
  391.         /* pixmap */
  392.         pixmap = gdk_pixmap_create_from_xpm(widget->window, &mask, NULL,
  393.                                             default_text_pixmap);
  394.         style.bg_pixmap[0] = pixmap;
  395.     }
  396.  
  397.     gtk_widget_set_style(widget, &style);
  398. }
  399.  
  400. /* set window style for all windows */
  401. void gui_refresh_windows(void)
  402. {
  403.     GList *tmp;
  404.  
  405.     for (tmp = g_list_first(winlist); tmp != NULL; tmp = tmp->next)
  406.     {
  407.         WINDOW_REC *w;
  408.  
  409.         w = (WINDOW_REC *) tmp->data;
  410.         gui_set_style(GTK_WIDGET(w->gui->text),
  411.                       w->curchan == NULL ? NULL : w->curchan->name);
  412.     }
  413. }
  414.  
  415. /* allocate colors */
  416. static void init_colors(GtkWidget *window)
  417. {
  418.     int n;
  419.  
  420.     g_return_if_fail(window != NULL);
  421.  
  422.     for (n = 0; n < COLORS; n++)
  423.     {
  424.         colors[n].pixel =
  425.             (gulong)((colors[n].red & 0xff00)*256 +
  426.                      (colors[n].green & 0xff00) +
  427.                      (colors[n].blue & 0xff00)/256);
  428.         gdk_color_alloc(gtk_widget_get_colormap(window), &colors[n]);
  429.     }
  430.  
  431.     for (n = 0; n < 15; n++)
  432.     {
  433.         yag_colors[n].pixel =
  434.             (gulong)((yag_colors[n].red & 0xff00)*256 +
  435.                      (yag_colors[n].green & 0xff00) +
  436.                      (yag_colors[n].blue & 0xff00)/256);
  437.         gdk_color_alloc(gtk_widget_get_colormap(window), &yag_colors[n]);
  438.     }
  439.  
  440.     gdk_color_alloc(gtk_widget_get_colormap(window), &default_color);
  441.     gdk_color_alloc(gtk_widget_get_colormap(window), &default_bgcolor);
  442. }
  443.  
  444. /* signal: enter pressed - process entry */
  445. static int enter_text(GtkEntry *entry)
  446. {
  447.     if (entry->text == NULL || *entry->text == '\0') return 0;
  448.  
  449.     /* save line for history */
  450.     if (histlines >= MAX_CMDHIST_LINES)
  451.     {
  452.         g_free(g_list_first(cmdhist)->data);
  453.         cmdhist = g_list_remove_link(cmdhist, g_list_first(cmdhist));
  454.     }
  455.     else
  456.         histlines++;
  457.     cmdhist = g_list_append(cmdhist, g_strdup(entry->text));
  458.  
  459.     irc_parse_outgoing(curwin->curchan, entry->text);
  460.  
  461.     gtk_entry_set_text(entry, "");
  462.     histpos = NULL;
  463.  
  464.     return 0;
  465. }
  466.  
  467. /* signal: key pressed in entry field */
  468. int keyevent(GtkWidget *widget, GdkEventKey *event, GtkEntry *entry)
  469. {
  470.     GList *pos;
  471.  
  472.     gtk_widget_grab_focus(GTK_WIDGET(entry));
  473.     switch (event->keyval)
  474.     {
  475.         case GDK_Up:
  476.             /* previous line */
  477.             pos = histpos;
  478.             if (histpos == NULL)
  479.                 histpos = g_list_last(cmdhist);
  480.             else
  481.                 histpos = histpos->prev;
  482.             if (*entry->text != '\0' &&
  483.                 (pos == NULL || strcmp(pos->data, entry->text) != 0))
  484.             {
  485.                 /* save the old entry to history */
  486.                 if (histlines >= MAX_CMDHIST_LINES)
  487.                 {
  488.                     g_free(g_list_first(cmdhist)->data);
  489.                     cmdhist = g_list_remove_link(cmdhist, g_list_first(cmdhist));
  490.                 }
  491.                 cmdhist = g_list_append(cmdhist, g_strdup(entry->text));
  492.             }
  493.             gtk_entry_set_text(entry, histpos == NULL ? "" : histpos->data);
  494.             break;
  495.  
  496.         case GDK_Down:
  497.             /* next line */
  498.             pos = histpos;
  499.             if (histpos == NULL)
  500.                 histpos = g_list_first(cmdhist);
  501.             else
  502.                 histpos = histpos->next;
  503.  
  504.             if (*entry->text != '\0' &&
  505.                 (pos == NULL || strcmp(pos->data, entry->text) != 0))
  506.             {
  507.                 /* save the old entry to history */
  508.                 if (histlines >= MAX_CMDHIST_LINES)
  509.                 {
  510.                     g_free(g_list_first(cmdhist)->data);
  511.                     cmdhist = g_list_remove_link(cmdhist, g_list_first(cmdhist));
  512.                 }
  513.                 cmdhist = g_list_prepend(cmdhist, g_strdup(entry->text));
  514.             }
  515.             gtk_entry_set_text(entry, histpos == NULL ? "" : histpos->data);
  516.             break;
  517.  
  518.         case GDK_Page_Up:
  519.             /* scrollback buffer up.. */
  520.             {
  521.                 GtkAdjustment *adj;
  522.                 int val;
  523.  
  524.                 adj = curwin->gui->text->vadj;
  525.                 val = adj->value - (adj->page_size/2);
  526.                 gtk_adjustment_set_value(adj, val > 0 ? val : 0);
  527.             }
  528.             break;
  529.  
  530.         case GDK_Page_Down:
  531.             /* scrollback buffer down.. */
  532.             {
  533.                 GtkAdjustment *adj;
  534.                 int val, max;
  535.  
  536.                 adj = curwin->gui->text->vadj;
  537.                 val = adj->value + (adj->page_size/2);
  538.                 max = adj->upper - adj->lower - adj->page_size;
  539.                 gtk_adjustment_set_value(adj, val <= max ? val : max);
  540.             }
  541.             break;
  542.  
  543.         default:
  544.             if (event->keyval >= '0' && event->keyval <= '9' && (event->state & 0x0d) == 8)
  545.             {
  546.                 /* alt-1..0 pressed */
  547.                 GList *tmp;
  548.  
  549.                 tmp = g_list_nth(winlist, event->keyval == '0' ? 9 : event->keyval-'0'-1);
  550.                 if (tmp != NULL) gui_window_select((WINDOW_REC *) tmp->data);
  551.             }
  552.             return 0;
  553.     }
  554.  
  555.     /* key was used, stop signal */
  556.     gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event");
  557.     return 1;
  558. }
  559.  
  560. /* signal: window closed */
  561. static int delete_event(GtkWidget *window, GtkWidget *t, GUI_TOPWIN_REC *win)
  562. {
  563.     GList *tmp, *next;
  564.  
  565.     /* close all subwindows in this window */
  566.     tmp = g_list_first(win->windows);
  567.     while (tmp != NULL)
  568.     {
  569.         next = tmp->next;
  570.         irc_window_close(tmp->data);
  571.         tmp = next;
  572.     }
  573.     return 0;
  574. }
  575.  
  576. /* signal: got focus for some widget */
  577. static void got_focus(GtkWindow *a, GtkWidget *b, GUI_TOPWIN_REC *top)
  578. {
  579.     irc_window_focus(top->selected);
  580. }
  581.  
  582. static void size_request(GtkWidget *win, GtkRequisition *req)
  583. {
  584.     if (win->allocation.width < 50) req->width = gdk_screen_width()*2/3;
  585.     if (win->allocation.height <= 1) req->height = gdk_screen_height()/2;
  586. }
  587.  
  588. /* Create new toplevel window */
  589. static void gui_top_window_new(WINDOW_REC *win)
  590. {
  591.     GUI_TOPWIN_REC *top;
  592.     GtkWidget *window;
  593.     GtkWidget *vbox, *hbox;
  594.     GtkWidget *entry;
  595.     GtkWidget *statusbar;
  596.     GtkWidget *nickscroll;
  597.  
  598.     g_return_if_fail(win != NULL);
  599.  
  600.     top = (GUI_TOPWIN_REC *) g_malloc(sizeof(GUI_TOPWIN_REC));
  601.     memset(top, 0, sizeof(GUI_TOPWIN_REC));
  602.     win->gui->parent = top;
  603.  
  604.     top->windows = g_list_append(NULL, win);
  605.  
  606.     /* main window */
  607. #ifdef USE_GNOME
  608.     top->mainwin = window = gnome_app_new("yagIRC", PROGRAM_TITLE);
  609. #else
  610.     top->mainwin = window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  611.     gtk_window_set_title(GTK_WINDOW(window), PROGRAM_TITLE);
  612. #endif
  613.     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
  614.                         GTK_SIGNAL_FUNC(delete_event), top);
  615.     gtk_signal_connect (GTK_OBJECT (window), "focus_in_event",
  616.                         GTK_SIGNAL_FUNC(got_focus), top);
  617.     gtk_signal_connect (GTK_OBJECT (window), "size_request",
  618.                         GTK_SIGNAL_FUNC(size_request), window);
  619.     /*
  620.     setting size here doesn't work - if window is resized and nicklist changes
  621.     it's always resized back to startup size, don't know why.. so size_request
  622.     signal works for now.
  623.  
  624.     gtk_widget_set_usize(window, gdk_screen_width()*2/3, gdk_screen_height()/2);
  625.     */
  626.     gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
  627.  
  628.     vbox = gtk_vbox_new(FALSE, 0);
  629. #ifdef USE_GNOME
  630.     gnome_app_set_contents(GNOME_APP(window), vbox);
  631. #else
  632.     gtk_container_add(GTK_CONTAINER(window), vbox);
  633. #endif
  634.     gtk_widget_show(vbox);
  635.  
  636.     /* menu */
  637.     gui_menu_create(win);
  638.     /*gtk_window_add_accelerator_table(GTK_WINDOW(window), top->table);*/
  639. #ifdef USE_GNOME
  640.     gnome_app_set_menus(GNOME_APP(window), GTK_MENU_BAR(top->menubar));
  641. #else
  642.     gtk_box_pack_start(GTK_BOX(vbox), top->menubar, FALSE, TRUE, 0);
  643.     gtk_widget_show(top->menubar);
  644. #endif
  645.  
  646.     /* channel list */
  647.     top->chanbox = gtk_hbox_new(FALSE, 0);
  648.     gtk_box_pack_start(GTK_BOX(vbox), top->chanbox, FALSE, FALSE, 0);
  649.     gtk_widget_show(top->chanbox);
  650.  
  651.     top->hbox = hbox = gtk_hbox_new(FALSE, 0);
  652.     gtk_container_add(GTK_CONTAINER(vbox), hbox);
  653.     gtk_widget_show(hbox);
  654.  
  655.     /* nick list */
  656.     nickscroll = gtk_scrolled_window_new(NULL, NULL);
  657.     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(nickscroll),
  658.                                    GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
  659.     gtk_box_pack_start(GTK_BOX(hbox), nickscroll, FALSE, FALSE, 0);
  660.     gtk_widget_show (nickscroll);
  661.     gtk_widget_set_usize(nickscroll, 120, -1);
  662.  
  663.     top->nicklist = gtk_list_new();
  664.     gtk_list_set_selection_mode (GTK_LIST(top->nicklist), GTK_SELECTION_BROWSE);
  665.     gtk_signal_connect (GTK_OBJECT (top->nicklist), "button_press_event",
  666.                         GTK_SIGNAL_FUNC(signick_button_pressed), win);
  667.     gtk_signal_connect (GTK_OBJECT (top->nicklist), "button_release_event",
  668.                         GTK_SIGNAL_FUNC(signick_button_released), win);
  669.     gtk_container_add(GTK_CONTAINER(nickscroll), top->nicklist);
  670.     gtk_widget_show(top->nicklist);
  671.     top->nicklistlen = 0;
  672.  
  673.     /* entry field */
  674.     top->entry = entry = gtk_entry_new_with_max_length(490);
  675.     gtk_signal_connect (GTK_OBJECT (entry), "activate",
  676.                         GTK_SIGNAL_FUNC(enter_text), NULL);
  677.     gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
  678.     gtk_widget_show(entry);
  679.  
  680.     /* redirect all key presses in window to entry field */
  681.     gtk_signal_connect (GTK_OBJECT (window), "key_press_event",
  682.                         GTK_SIGNAL_FUNC(keyevent), entry);
  683.  
  684.     top->statusbar = statusbar = gtk_statusbar_new();
  685.     gtk_statusbar_push(GTK_STATUSBAR(top->statusbar), 1, "");
  686.     gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
  687.     gtk_widget_show(statusbar);
  688.  
  689.     init_colors(window);
  690.  
  691.     gui_update_statusbar(win);
  692.  
  693.     gtk_widget_show(window);
  694. }
  695.  
  696. void gui_window_init(WINDOW_REC *win, WINDOW_REC *parent)
  697. {
  698.     GtkWidget *text;
  699.     GtkWidget *textscroll;
  700.  
  701.     win->drawfunc = (DRAW_FUNC) printtext;
  702.     win->drawfuncdata = win;
  703.  
  704.     win->gui = (GUI_WINDOW_REC *) g_malloc(sizeof(GUI_WINDOW_REC));
  705.     memset(win->gui, 0, sizeof(GUI_WINDOW_REC));
  706.  
  707.     if (parent == NULL)
  708.     {
  709.         gui_top_window_new(win);
  710.     }
  711.     else
  712.     {
  713.         win->gui->parent = parent->gui->parent;
  714.         win->gui->parent->windows = g_list_append(win->gui->parent->windows, win);
  715.     }
  716.  
  717.     /* irc text field */
  718.     text = gtk_text_new(NULL, NULL);
  719.     win->gui->text = GTK_TEXT(text);
  720.     gtk_signal_connect (GTK_OBJECT (text), "button_release_event",
  721.                         GTK_SIGNAL_FUNC(sigchantext_button_released), win);
  722.     gtk_box_pack_start(GTK_BOX(win->gui->parent->hbox), text, TRUE, TRUE, 0);
  723.     gtk_box_reorder_child(GTK_BOX(win->gui->parent->hbox), text, 0);
  724.     gtk_text_set_word_wrap(GTK_TEXT(text), TRUE);
  725.  
  726.     win->gui->textscroll = textscroll =
  727.         gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
  728.     gtk_box_pack_start(GTK_BOX(win->gui->parent->hbox), textscroll, FALSE, FALSE, 0);
  729.     gtk_box_reorder_child(GTK_BOX(win->gui->parent->hbox), textscroll, 1);
  730.  
  731.     gui_window_select(win);
  732.  
  733.     gui_set_style(text, NULL);
  734. }
  735.  
  736. /* Deinitialize IRC window */
  737. void gui_window_deinit(WINDOW_REC *window)
  738. {
  739.     g_return_if_fail(window != NULL);
  740.  
  741.     if (window->gui->parent->selected == window)
  742.         window->gui->parent->selected = NULL;
  743.  
  744.     gtk_widget_destroy(GTK_WIDGET(window->gui->text));
  745.     gtk_widget_destroy(window->gui->textscroll);
  746.  
  747.     window->gui->parent->windows =
  748.         g_list_remove(window->gui->parent->windows, window);
  749.  
  750.     if (window->gui->parent->windows == NULL)
  751.     {
  752.         /* Remove main window */
  753.         gtk_widget_destroy(window->gui->parent->mainwin);
  754.         g_free(window->gui->parent); window->gui->parent = NULL;
  755.     }
  756.     g_free(window->gui); window->gui = NULL;
  757.  
  758.     if (winlist == NULL)
  759.     {
  760.         /* This was the last window */
  761.         gtk_main_quit();
  762.     }
  763. }
  764.  
  765. /* IRC channel/window changed, update everything you can think of.. */
  766. void gui_window_update(WINDOW_REC *win)
  767. {
  768.     g_return_if_fail(win != NULL);
  769.  
  770.     /* Enable/disable (dis)connect menu items */
  771.     if (cserver == NULL)
  772.     {
  773.         menus_set_sensitive(win, "<Main>/IRC/Connect", TRUE);
  774.         menus_set_sensitive(win, "<Main>/IRC/Disconnect", FALSE);
  775.     }
  776.     else
  777.     {
  778.         menus_set_sensitive(win, "<Main>/IRC/Connect", FALSE);
  779.         menus_set_sensitive(win, "<Main>/IRC/Disconnect", TRUE);
  780.     }
  781. }
  782.  
  783. /* Change focus to specified window */
  784. void gui_window_select(WINDOW_REC *win)
  785. {
  786.     GUI_WINDOW_REC *gui;
  787.     int scroll_down;
  788.  
  789.     g_return_if_fail(win != NULL);
  790.  
  791.     if (curwin != NULL && win->gui->parent != curwin->gui->parent)
  792.     {
  793.         /* not in same toplevel window .. we should set focus to that window,
  794.         but how?? Didn't find any such function from GDK/GTK, XSetInputFocus
  795.         changes to that window but WM doesn't notice the change so I think it
  796.         should be done with some WM hints.. If there is such... */
  797.         gdk_window_raise(win->gui->parent->mainwin->window);
  798.         /*XSetInputFocus(GDK_WINDOW_XDISPLAY(win->gui->parent->mainwin->window),
  799.                        GDK_WINDOW_XWINDOW(win->gui->parent->mainwin->window),
  800.                        RevertToParent, CurrentTime);*/
  801.         /*gtk_widget_grab_focus(win->gui->parent->mainwin);*/
  802.     }
  803.  
  804.     scroll_down = gui_is_sb_down(win);
  805.  
  806.     if (win->gui->parent->selected != NULL)
  807.     {
  808.         /* Hide old window */
  809.         gui = win->gui->parent->selected->gui;
  810.         gtk_widget_hide(GTK_WIDGET(gui->text));
  811.         gtk_widget_hide(gui->textscroll);
  812.     }
  813.  
  814.     gtk_widget_show(GTK_WIDGET(win->gui->text));
  815.     gtk_widget_show(win->gui->textscroll);
  816.     win->gui->parent->selected = win;
  817.  
  818.     irc_window_focus(win);
  819.     if (win->curchan != NULL)
  820.         gui_select_channel(win, win->curchan);
  821.     else
  822.         gui_draw_channel(win, NULL);
  823.  
  824.     gui_update_statusbar(curwin);
  825. }
  826.  
  827. /* Quit program requested */
  828. void gui_exit(void)
  829. {
  830.     gtk_main_quit();
  831. }
  832.  
  833. /* Someone in notify list joined IRC */
  834. void gui_notify_join(char *nick)
  835. {
  836.     drawtext(curwin, TXT_TYPE_NOTICE, IRCTXT_IRCJOIN, nick);
  837. }
  838.  
  839. /* Someone in notify list left IRC */
  840. void gui_notify_part(char *nick)
  841. {
  842.     drawtext(curwin, TXT_TYPE_NOTICE, IRCTXT_IRCPART, nick);
  843. }
  844.  
  845. /* server got connected */
  846. void gui_connected(SERVER_REC *serv, int state)
  847. {
  848.     gui_update_statusbar(NULL);
  849. }
  850.  
  851. #ifdef USE_GNOME
  852. /* drop signal: channel dropped to desktop */
  853. static void rootwin_drop(GtkWidget *widget, GdkEvent *event)
  854. {
  855.     WINDOW_REC *win;
  856.     CHAN_REC *from;
  857.  
  858.     from = *((CHAN_REC **) event->dropdataavailable.data);
  859.     win = irc_window_new(cserver, NULL);
  860.     win->curchan = from;
  861.     gui_select_channel(win, from);
  862. }
  863. #endif
  864.  
  865. /* Initialize GUI */
  866. void gui_init(void)
  867. {
  868. #ifdef USE_GNOME
  869.     char *channel_drop_types[] = {"yagirc/channel"};
  870.     GtkWidget *root;
  871. #endif
  872.  
  873.     histlines = 0;
  874.     cmdhist = NULL;
  875.  
  876.     setup_open = 0;
  877.  
  878.     if (!gui_read_config())
  879.     {
  880.         /* configuration file not created yet - run setup */
  881.         setup_open = 1;
  882.         gui_write_config();
  883.     }
  884.  
  885.     font_normal = gdk_font_load("-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*");
  886.     font_bold = gdk_font_load("-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*");
  887.     font_italic = gdk_font_load("-adobe-helvetica-medium-o-normal--*-120-*-*-*-*-*-*");
  888.     font_bolditalic = gdk_font_load("-adobe-helvetica-bold-o-normal--*-120-*-*-*-*-*-*");
  889.  
  890. #ifdef USE_GNOME
  891.     /* dropping channels to desktop creates new window for them */
  892.     root = gnome_rootwin_new();
  893.     gtk_signal_connect (GTK_OBJECT(root), "drop_data_available_event",
  894.             GTK_SIGNAL_FUNC(rootwin_drop), NULL);
  895.     gtk_widget_show(root);
  896.     gtk_widget_dnd_drop_set (root, TRUE, channel_drop_types, 1, FALSE);
  897. #endif
  898. }
  899.  
  900. /* deinitialize GUI */
  901. void gui_deinit(void)
  902. {
  903.     GList *tmp;
  904.  
  905.     if (cmdhist != NULL)
  906.     {
  907.         for (tmp = g_list_first(cmdhist); tmp != NULL; tmp = tmp->next)
  908.             g_free(tmp->data);
  909.         g_list_free(cmdhist);
  910.     }
  911. }
  912.  
  913. int main (int argc, char *argv[])
  914. {
  915.     WINDOW_REC *window;
  916.  
  917. #ifdef USE_GNOME
  918.     gnome_init ("yagIRC", NULL, argc, argv, 0, NULL);
  919. #else
  920.  
  921.     gtk_init (&argc, &argv);
  922. #endif
  923.  
  924.     gui_setup_init();
  925.     gui_init();
  926.     irc_init();
  927.  
  928.     window = irc_window_new(NULL, NULL);
  929.     if (setup_open) gui_setup();
  930.  
  931.     gtk_main ();
  932.  
  933.     irc_deinit();
  934.     gui_deinit();
  935.     gui_setup_deinit();
  936.  
  937.     return 0;
  938. }
  939.