diff --git a/src/sbbs3/gtkchat/GNUmakefile b/src/sbbs3/gtkchat/GNUmakefile new file mode 100644 index 0000000000000000000000000000000000000000..ff73a4788c370dcc32476799d1b9febca6715e09 --- /dev/null +++ b/src/sbbs3/gtkchat/GNUmakefile @@ -0,0 +1,30 @@ +# GNUmakefile + +######################################################################### +# Makefile for Synchronet monitor for Unix # +# For use with GNU make and GNU C Compiler or Borland Kylix C++ # +# @format.tab-size 4, @format.use-tabs true # +# # +# gcc: gmake # +# Borland (still in testing/debuging stage): gmake bcc=1 # +# # +# Optional build targets: dlls, utils, mono, all (default) # +######################################################################### + +# $Id$ + +SRC_ROOT = ../.. +include $(SRC_ROOT)/build/Common.gmake + +ifeq ($(os),sunos) + LDFLAGS += -lnsl +endif + +vpath %.c .. + +CFLAGS += -I.. $(SMBLIB_CFLAGS) $(XPDEV-MT_CFLAGS) `pkg-config gtk+-2.0 --cflags` +LDFLAGS += $(SMBLIB_LDFLAGS) $(XPDEV-MT_LDFLAGS) $(MT_LDFLAGS) `pkg-config gtk+-2.0 --libs` + +$(GTKCHAT): $(OBJS) + @echo Linking $@ + $(QUIET)$(CC) $(LDFLAGS) $(OBJS) -o $@ $(SMBLIB_LIBS) $(XPDEV-MT_LIBS) diff --git a/src/sbbs3/gtkchat/callbacks.c b/src/sbbs3/gtkchat/callbacks.c new file mode 100644 index 0000000000000000000000000000000000000000..7867e2346de82389e8e7fe60d4e8deb20b47a268 --- /dev/null +++ b/src/sbbs3/gtkchat/callbacks.c @@ -0,0 +1,145 @@ +#include <gtk/gtk.h> + +#include "chatfuncs.h" +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +gint +get_from_remote(gpointer data) +{ + int ch; + gchar *outstr; + gchar instr[2]; + int inbytes; + int outbytes; + + instr[1]=0; + switch(chat_check_remote()) { + case 2: /* Chat active */ + while(ch=chat_read_byte()) { + if(ch==-1) { + chat_close(); + gtk_main_quit(); + return(FALSE); + } + if(ch==8 || ch==127) { + GtkTextIter start; + GtkTextIter end; + + gtk_text_buffer_get_iter_at_mark( + gtk_text_view_get_buffer(GTK_TEXT_VIEW(data)) + ,&start + ,gtk_text_buffer_get_insert( + gtk_text_view_get_buffer(GTK_TEXT_VIEW(data)) + ) + ); + end=start; + gtk_text_iter_backward_cursor_position(&end); + gtk_text_buffer_delete( + gtk_text_view_get_buffer(GTK_TEXT_VIEW(data)) + ,&start + ,&end + ); + } + else { + instr[0]=ch; + outstr=g_convert(instr, 1, "UTF-8", "CP437", &inbytes, &outbytes, NULL); + gtk_text_buffer_insert_at_cursor( + gtk_text_view_get_buffer(GTK_TEXT_VIEW(data)) + ,outstr + ,1 + ); + g_free(outstr); + } + } + return(TRUE); + } + chat_close(); + return(FALSE); +} + + +gint +connect_wait(gpointer data) +{ + GtkWidget *MainWindow; + + switch(chat_check_remote()) { + case -1: /* Error */ + case 0: /* Remote has gone away */ + chat_close(); + return(FALSE); + case 1: /* Waiting for remote */ + return(TRUE); + case 2: /* Chat active */ + MainWindow = create_MainWindow (); + gtk_widget_hide (GTK_WIDGET(data)); + gtk_widget_show (MainWindow); + return(FALSE); + } + return(TRUE); +} + + +void +on_MainWindow_destroy (GtkObject *object, + gpointer user_data) +{ + chat_close(); + gtk_main_quit(); +} + + +gboolean +on_LocalText_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data) +{ + gchar *outstr; + gchar instr[2]; + int inbytes; + int outbytes; + + if(event->keyval=='\b' || event->keyval==127) { + GtkTextIter start; + GtkTextIter end; + + chat_write_byte(event->keyval); + gtk_text_buffer_get_iter_at_mark( + gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)) + ,&start + ,gtk_text_buffer_get_insert( + gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)) + ) + ); + end=start; + gtk_text_iter_backward_cursor_position(&end); + gtk_text_buffer_delete( + gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)) + ,&start + ,&end + ); + } + if(event->keyval >= 32 && event->keyval < 127) { + instr[1]=0; + instr[0]=event->keyval; + outstr=g_convert(instr, 1, "UTF-8", "CP437", &inbytes, &outbytes, NULL); + gtk_text_buffer_insert_at_cursor( + gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)) + ,outstr + ,1 + ); + g_free(outstr); + } + return FALSE; +} + + +void +on_CancelButton_clicked (GtkButton *button, + gpointer user_data) +{ + chat_close(); + gtk_main_quit(); +} diff --git a/src/sbbs3/gtkchat/callbacks.h b/src/sbbs3/gtkchat/callbacks.h new file mode 100644 index 0000000000000000000000000000000000000000..944a5a0adc2600ed7f8d11ee0c39caa345edfe1f --- /dev/null +++ b/src/sbbs3/gtkchat/callbacks.h @@ -0,0 +1,22 @@ +#include <gtk/gtk.h> + + +void +on_MainWindow_destroy (GtkObject *object, + gpointer user_data); + +gboolean +on_LocalText_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +void +on_CancelButton_clicked (GtkButton *button, + gpointer user_data); + +gint +get_from_remote(gpointer data); + + +gint +connect_wait(gpointer data); diff --git a/src/sbbs3/gtkchat/chatfuncs.c b/src/sbbs3/gtkchat/chatfuncs.c new file mode 100644 index 0000000000000000000000000000000000000000..a030ba6df18a19ccc3de30c128846520ef2a39dd --- /dev/null +++ b/src/sbbs3/gtkchat/chatfuncs.c @@ -0,0 +1,178 @@ +#include <sys/types.h> +#include <sys/uio.h> +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> +#include <time.h> +#include <utime.h> +#include <unistd.h> + +#include "sbbs.h" +#include "chatfuncs.h" + +#define PCHAT_LEN 1000 + +char usrname[128]; + +static node_t node; +static int nodenum; +static int in,out; +static char inpath[MAX_PATH+1]; +static char outpath[MAX_PATH+1]; +static scfg_t cfg; + +static int togglechat(int on) +{ + static int org_act; + int nodefile; + + if(getnodedat(&cfg,nodenum,&node,&nodefile)) + return(-1); + if(on) { + org_act=node.action; + if(org_act==NODE_PCHT) + org_act=NODE_MAIN; + node.misc|=NODE_LCHAT; + } + else { + node.action=org_act; + node.misc&=~NODE_LCHAT; + } + if(putnodedat(&cfg,nodenum,&node,nodefile)) + return(-1); + return(0); +} + +int chat_open(int node_num, char *ctrl_dir) +{ + char *p; + char str[1024]; + + /* Read .cfg files here */ + memset(&cfg,0,sizeof(cfg)); + cfg.size=sizeof(cfg); + SAFECOPY(cfg.ctrl_dir,ctrl_dir); + if(!load_cfg(&cfg, NULL, TRUE, str)) + return(-1); + + nodenum=node_num; + + if(getnodedat(&cfg,nodenum,&node,NULL)) + return(-1); + + username(&cfg,node.useron,usrname); + + sprintf(outpath,"%slchat.dab",cfg.node_path[nodenum-1]); + if((out=sopen(outpath,O_RDWR|O_CREAT|O_BINARY,O_DENYNONE + ,S_IREAD|S_IWRITE))==-1) { + return(-1); + } + + sprintf(inpath,"%schat.dab",cfg.node_path[nodenum-1]); + if((in=sopen(inpath,O_RDWR|O_CREAT|O_BINARY,O_DENYNONE + ,S_IREAD|S_IWRITE))==-1) { + close(out); + return(-1); + } + + if((p=(char *)malloc(PCHAT_LEN))==NULL) { + close(in); + close(out); + return(-1); + } + memset(p,0,PCHAT_LEN); + write(in,p,PCHAT_LEN); + write(out,p,PCHAT_LEN); + free(p); + lseek(in,0,SEEK_SET); + lseek(out,0,SEEK_SET); + + if(togglechat(TRUE)) + return(-1); + return(0); +} + +int chat_check_remote(void) +{ + time_t now; + static time_t last_nodechk=0; + + now=time(NULL); + if(now!=last_nodechk) { + if(getnodedat(&cfg,nodenum,&node,NULL)!=0) + return(-1); /* Failed to read nodedat! */ + last_nodechk=now; + } + if(node.misc&NODE_LCHAT) + return(1); /* Still Waiting */ + + if(node.status==NODE_WFC || node.status>NODE_QUIET || node.action!=NODE_PCHT) + return(0); /* Remote has gone away */ + + if(in==-1) + return(0); /* Remote has gone away */ + + if(out==-1) + return(-1); /* Write error or some such */ + + return(2); /* Everything is good! */ +} + +int chat_read_byte(void) +{ + unsigned char ch=0; + + if(in==-1) + return(-1); + utime(inpath,NULL); + switch(read(in,&ch,1)) { + case -1: + close(in); + in=-1; + return(-1); + case 0: + if(lseek(in,0,SEEK_SET)==-1); /* Wrapped */ + return(-1); + switch(read(in,&ch,1)) { + case -1: + close(in); + in=-1; + return(-1); + } + /* Fall-through */ + case 1: + lseek(in,-1L,SEEK_CUR); + if(ch) { + write(in,"",1); + return(ch); + } + } + + return(0); +} + +int chat_write_byte(unsigned char ch) +{ + if(out==-1) + return(-1); + if(lseek(out,0,SEEK_CUR)>=PCHAT_LEN) + lseek(out,0,SEEK_SET); + switch(write(out,&ch,1)) { + case -1: + close(out); + out=-1; + return(-1); + } + utime(outpath,NULL); + return(0); +} + +int chat_close(void) +{ + if(in != -1) + close(in); + if(out != -1) + close(out); + return(togglechat(FALSE)); +} diff --git a/src/sbbs3/gtkchat/chatfuncs.h b/src/sbbs3/gtkchat/chatfuncs.h new file mode 100644 index 0000000000000000000000000000000000000000..94f1af0cfccfbd5af7558cc4c5cbb4d935331d68 --- /dev/null +++ b/src/sbbs3/gtkchat/chatfuncs.h @@ -0,0 +1,11 @@ +#ifndef _CHATFUNCS_H_ +#define _CHATFUNCS_H_ + +extern char usrname[128]; +int chat_open(int node_num, char *ctrl_dir); +int chat_check_remote(void); +int chat_read_byte(void); +int chat_write_byte(unsigned char ch); +int chat_close(void); + +#endif diff --git a/src/sbbs3/gtkchat/gtk-chat.glade b/src/sbbs3/gtkchat/gtk-chat.glade new file mode 100644 index 0000000000000000000000000000000000000000..02c3efb0116ca37ebeb8c918ce52293c72226954 --- /dev/null +++ b/src/sbbs3/gtkchat/gtk-chat.glade @@ -0,0 +1,216 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkWindow" id="MainWindow"> + <property name="width_request">400</property> + <property name="height_request">300</property> + <property name="visible">True</property> + <property name="title" translatable="yes">Synchronet Sysop Chat</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="icon_name">stock_help-chat</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_UTILITY</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <signal name="destroy" handler="on_MainWindow_destroy" last_modification_time="Wed, 08 Mar 2006 07:15:35 GMT"/> + + <child> + <widget class="GtkVPaned" id="SplitPane"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="position">148</property> + + <child> + <widget class="GtkTextView" id="RemoteText"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Remote Text Window</property> + <property name="editable">False</property> + <property name="overwrite">False</property> + <property name="accepts_tab">True</property> + <property name="justification">GTK_JUSTIFY_LEFT</property> + <property name="wrap_mode">GTK_WRAP_WORD</property> + <property name="cursor_visible">True</property> + <property name="pixels_above_lines">0</property> + <property name="pixels_below_lines">0</property> + <property name="pixels_inside_wrap">0</property> + <property name="left_margin">0</property> + <property name="right_margin">0</property> + <property name="indent">0</property> + <property name="text" translatable="yes"></property> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">False</property> + </packing> + </child> + + <child> + <widget class="GtkTextView" id="LocalText"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="has_focus">True</property> + <property name="editable">False</property> + <property name="overwrite">False</property> + <property name="accepts_tab">True</property> + <property name="justification">GTK_JUSTIFY_LEFT</property> + <property name="wrap_mode">GTK_WRAP_WORD</property> + <property name="cursor_visible">True</property> + <property name="pixels_above_lines">0</property> + <property name="pixels_below_lines">0</property> + <property name="pixels_inside_wrap">0</property> + <property name="left_margin">0</property> + <property name="right_margin">0</property> + <property name="indent">0</property> + <property name="text" translatable="yes"></property> + <signal name="key_press_event" handler="on_LocalText_key_press_event" last_modification_time="Wed, 08 Mar 2006 07:13:25 GMT"/> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="WaitWindow"> + <property name="visible">True</property> + <property name="title" translatable="yes">Waiting for user</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + + <child> + <widget class="GtkFixed" id="fixed1"> + <property name="width_request">400</property> + <property name="height_request">40</property> + <property name="visible">True</property> + + <child> + <widget class="GtkLabel" id="MessageLabel"> + <property name="width_request">400</property> + <property name="height_request">16</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Waiting for user to connect.</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="x">0</property> + <property name="y">0</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="CancelButton"> + <property name="width_request">88</property> + <property name="height_request">24</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_CancelButton_clicked" last_modification_time="Thu, 09 Mar 2006 02:41:33 GMT"/> + + <child> + <widget class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <property name="top_padding">0</property> + <property name="bottom_padding">0</property> + <property name="left_padding">0</property> + <property name="right_padding">0</property> + + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="stock">gtk-cancel</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Cancel</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="x">160</property> + <property name="y">16</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> diff --git a/src/sbbs3/gtkchat/gtk-chat.gladep b/src/sbbs3/gtkchat/gtk-chat.gladep new file mode 100644 index 0000000000000000000000000000000000000000..3d6dc000aa11c73fa8a6dfddf2edd25d450ebff1 --- /dev/null +++ b/src/sbbs3/gtkchat/gtk-chat.gladep @@ -0,0 +1,10 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd"> + +<glade-project> + <name>Synchronet Sysop Chat</name> + <program_name>gtk-chat</program_name> + <source_directory></source_directory> + <gnome_support>FALSE</gnome_support> + <gettext_support>FALSE</gettext_support> +</glade-project> diff --git a/src/sbbs3/gtkchat/interface.c b/src/sbbs3/gtkchat/interface.c new file mode 100644 index 0000000000000000000000000000000000000000..99e4938c8cdc7f0cc11672739cf24bd8d24231d4 --- /dev/null +++ b/src/sbbs3/gtkchat/interface.c @@ -0,0 +1,142 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ + g_object_set_data_full (G_OBJECT (component), name, \ + gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + +#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ + g_object_set_data (G_OBJECT (component), name, widget) + +GtkWidget *MessageLabel; + +GtkWidget* +create_MainWindow (void) +{ + GtkWidget *MainWindow; + GtkWidget *SplitPane; + GtkWidget *RemoteText; + GtkWidget *LocalText; + GtkTooltips *tooltips; + + tooltips = gtk_tooltips_new (); + + MainWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_set_size_request (MainWindow, 400, 300); + gtk_window_set_title (GTK_WINDOW (MainWindow), "Synchronet Sysop Chat"); + gtk_window_set_icon_name (GTK_WINDOW (MainWindow), "stock_help-chat"); + gtk_window_set_type_hint (GTK_WINDOW (MainWindow), GDK_WINDOW_TYPE_HINT_UTILITY); + + SplitPane = gtk_vpaned_new (); + gtk_widget_show (SplitPane); + gtk_container_add (GTK_CONTAINER (MainWindow), SplitPane); + gtk_paned_set_position (GTK_PANED (SplitPane), 148); + + RemoteText = gtk_text_view_new (); + gtk_widget_show (RemoteText); + gtk_paned_pack1 (GTK_PANED (SplitPane), RemoteText, FALSE, TRUE); + GTK_WIDGET_UNSET_FLAGS (RemoteText, GTK_CAN_FOCUS); + gtk_tooltips_set_tip (tooltips, RemoteText, "Remote Text Window", NULL); + gtk_text_view_set_editable (GTK_TEXT_VIEW (RemoteText), FALSE); + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (RemoteText), GTK_WRAP_WORD); + + LocalText = gtk_text_view_new (); + gtk_widget_show (LocalText); + gtk_paned_pack2 (GTK_PANED (SplitPane), LocalText, TRUE, TRUE); + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (LocalText), GTK_WRAP_WORD); + gtk_text_view_set_editable (GTK_TEXT_VIEW (LocalText), FALSE); + + g_signal_connect ((gpointer) MainWindow, "destroy", + G_CALLBACK (on_MainWindow_destroy), + NULL); + g_signal_connect ((gpointer) LocalText, "key_press_event", + G_CALLBACK (on_LocalText_key_press_event), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (MainWindow, MainWindow, "MainWindow"); + GLADE_HOOKUP_OBJECT (MainWindow, SplitPane, "SplitPane"); + GLADE_HOOKUP_OBJECT (MainWindow, RemoteText, "RemoteText"); + GLADE_HOOKUP_OBJECT (MainWindow, LocalText, "LocalText"); + GLADE_HOOKUP_OBJECT_NO_REF (MainWindow, tooltips, "tooltips"); + + gtk_widget_grab_focus (LocalText); + + gtk_timeout_add(50, get_from_remote, RemoteText); + + return MainWindow; +} + +GtkWidget* +create_WaitWindow (void) +{ + GtkWidget *WaitWindow; + GtkWidget *fixed1; + GtkWidget *CancelButton; + GtkWidget *alignment1; + GtkWidget *hbox1; + GtkWidget *image1; + GtkWidget *label2; + + WaitWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (WaitWindow), "Waiting for user"); + + fixed1 = gtk_fixed_new (); + gtk_widget_show (fixed1); + gtk_container_add (GTK_CONTAINER (WaitWindow), fixed1); + gtk_widget_set_size_request (fixed1, 400, 40); + + MessageLabel = gtk_label_new ("Waiting for user to connect."); + gtk_widget_show (MessageLabel); + gtk_fixed_put (GTK_FIXED (fixed1), MessageLabel, 0, 0); + gtk_widget_set_size_request (MessageLabel, 400, 16); + + CancelButton = gtk_button_new (); + gtk_widget_show (CancelButton); + gtk_fixed_put (GTK_FIXED (fixed1), CancelButton, 160, 16); + gtk_widget_set_size_request (CancelButton, 88, 24); + + alignment1 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment1); + gtk_container_add (GTK_CONTAINER (CancelButton), alignment1); + + hbox1 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox1); + gtk_container_add (GTK_CONTAINER (alignment1), hbox1); + + image1 = gtk_image_new_from_stock ("gtk-cancel", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image1); + gtk_box_pack_start (GTK_BOX (hbox1), image1, FALSE, FALSE, 0); + + label2 = gtk_label_new_with_mnemonic ("Cancel"); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (hbox1), label2, FALSE, FALSE, 0); + + g_signal_connect ((gpointer) CancelButton, "clicked", + G_CALLBACK (on_CancelButton_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (WaitWindow, WaitWindow, "WaitWindow"); + GLADE_HOOKUP_OBJECT (WaitWindow, fixed1, "fixed1"); + GLADE_HOOKUP_OBJECT (WaitWindow, MessageLabel, "MessageLabel"); + GLADE_HOOKUP_OBJECT (WaitWindow, CancelButton, "CancelButton"); + GLADE_HOOKUP_OBJECT (WaitWindow, alignment1, "alignment1"); + GLADE_HOOKUP_OBJECT (WaitWindow, hbox1, "hbox1"); + GLADE_HOOKUP_OBJECT (WaitWindow, image1, "image1"); + GLADE_HOOKUP_OBJECT (WaitWindow, label2, "label2"); + + gtk_timeout_add(50, connect_wait, WaitWindow); + return WaitWindow; +} + diff --git a/src/sbbs3/gtkchat/interface.h b/src/sbbs3/gtkchat/interface.h new file mode 100644 index 0000000000000000000000000000000000000000..347c8407c3167833ba10e6cfd5c62122a1dc7a6b --- /dev/null +++ b/src/sbbs3/gtkchat/interface.h @@ -0,0 +1,7 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +extern GtkWidget *MessageLabel; +GtkWidget* create_MainWindow (void); +GtkWidget* create_WaitWindow (void); diff --git a/src/sbbs3/gtkchat/main.c b/src/sbbs3/gtkchat/main.c new file mode 100644 index 0000000000000000000000000000000000000000..d5a9b1ad4a2ea783f9b6077a54786c845979f8a1 --- /dev/null +++ b/src/sbbs3/gtkchat/main.c @@ -0,0 +1,56 @@ +#include <stdlib.h> + +#include <gtk/gtk.h> + +#include "dirwrap.h" + +#include "chatfuncs.h" +#include "interface.h" +#include "support.h" + +int lprintf(int level, char *fmt, ...) +{ + /* ToDo: Log output */ + return(0); +} + + +int +main (int argc, char *argv[]) +{ + int node; + char *ctrl_dir; + GtkWidget *WaitWindow; + + gtk_set_locale (); + gtk_init (&argc, &argv); + +/* add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); */ + + ctrl_dir=getenv("SBBSCTRL"); + if(ctrl_dir==NULL) + return(1); + + if(argc<1) + return(1); + + node=atoi(argv[1]); + + if(node<1) + return(1); + + /* + * Request a chat + */ + if(chat_open(node, ctrl_dir)) + return(1); + + /* + * Show "waiting" window + */ + WaitWindow = create_WaitWindow (); + gtk_widget_show (WaitWindow); + + gtk_main (); + return 0; +} diff --git a/src/sbbs3/gtkchat/objects.mk b/src/sbbs3/gtkchat/objects.mk new file mode 100644 index 0000000000000000000000000000000000000000..67dc2399faaa840a6e04c0256161dcc4963fb134 --- /dev/null +++ b/src/sbbs3/gtkchat/objects.mk @@ -0,0 +1,21 @@ +OBJS := \ + $(MTOBJODIR)$(DIRSEP)ars$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)dat_rec$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)date_str$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)load_cfg$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)nopen$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)scfglib1$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)scfglib2$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)userdat$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)str_util$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)chatfuncs$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)interface$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)support$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)callbacks$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)main$(OFILE) \ + +# $(MTOBJODIR)$(DIRSEP)chat$(OFILE) \ +# $(MTOBJODIR)$(DIRSEP)getmail$(OFILE) \ +# $(MTOBJODIR)$(DIRSEP)getstats$(OFILE) \ +# $(MTOBJODIR)$(DIRSEP)sbbs_ini$(OFILE) \ + diff --git a/src/sbbs3/gtkchat/support.c b/src/sbbs3/gtkchat/support.c new file mode 100644 index 0000000000000000000000000000000000000000..601777a1164102d853be394bc2515d57706667c7 --- /dev/null +++ b/src/sbbs3/gtkchat/support.c @@ -0,0 +1,136 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#include <gtk/gtk.h> + +#include "support.h" + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (!parent) + parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to find pixmap files. */ +static gchar* +find_pixmap_file (const gchar *filename) +{ + GList *elem; + + /* We step through each of the pixmaps directory to find it. */ + elem = pixmaps_directories; + while (elem) + { + gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data, + G_DIR_SEPARATOR_S, filename); + if (g_file_test (pathname, G_FILE_TEST_EXISTS)) + return pathname; + g_free (pathname); + elem = elem->next; + } + return NULL; +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *pathname = NULL; + GtkWidget *pixmap; + + if (!filename || !filename[0]) + return gtk_image_new (); + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return gtk_image_new (); + } + + pixmap = gtk_image_new_from_file (pathname); + g_free (pathname); + return pixmap; +} + +/* This is an internally used function to create pixmaps. */ +GdkPixbuf* +create_pixbuf (const gchar *filename) +{ + gchar *pathname = NULL; + GdkPixbuf *pixbuf; + GError *error = NULL; + + if (!filename || !filename[0]) + return NULL; + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return NULL; + } + + pixbuf = gdk_pixbuf_new_from_file (pathname, &error); + if (!pixbuf) + { + fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", + pathname, error->message); + g_error_free (error); + } + g_free (pathname); + return pixbuf; +} + +/* This is used to set ATK action descriptions. */ +void +glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description) +{ + gint n_actions, i; + + n_actions = atk_action_get_n_actions (action); + for (i = 0; i < n_actions; i++) + { + if (!strcmp (atk_action_get_name (action, i), action_name)) + atk_action_set_description (action, i, description); + } +} + diff --git a/src/sbbs3/gtkchat/support.h b/src/sbbs3/gtkchat/support.h new file mode 100644 index 0000000000000000000000000000000000000000..5c1a63f922f0e24caf3e751ec7b891a4412596db --- /dev/null +++ b/src/sbbs3/gtkchat/support.h @@ -0,0 +1,36 @@ +#include <gtk/gtk.h> + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps used in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + +/* This is used to create the pixbufs used in the interface. */ +GdkPixbuf* create_pixbuf (const gchar *filename); + +/* This is used to set ATK action descriptions. */ +void glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description); + diff --git a/src/sbbs3/gtkchat/targets.mk b/src/sbbs3/gtkchat/targets.mk new file mode 100644 index 0000000000000000000000000000000000000000..91ab785e46ff02f40b1e135101fcc260e94416cd --- /dev/null +++ b/src/sbbs3/gtkchat/targets.mk @@ -0,0 +1,5 @@ +GTKCHAT = $(EXEODIR)$(DIRSEP)gtkchat$(EXEFILE) + +all: xpdev-mt smblib $(MTOBJODIR) $(EXEODIR) $(GTKCHAT) + +$(GTKCHAT): $(XPDEV-MT_LIB) $(SMBLIB)