commit 980af5458adb5bd06044af36c3edd69ff2541ba2 Author: Gergely Polonkai Date: Wed Apr 27 20:28:51 2016 +0200 Released v1 diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..0d2e46a --- /dev/null +++ b/ChangeLog @@ -0,0 +1,4 @@ +2007-04-09 19:41 Gergely Polonkai + + * Added this ChangeLog file. + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..ef77c3a --- /dev/null +++ b/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.ac' is used to create `configure' by a program +called `autoconf'. You only need `configure.ac' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..edf73e6 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,51 @@ +include rules +subdirs = src doc pixmaps po data +SHELL = /bin/sh + +srcdir = @srcdir@ + +all: + @for dir in ${subdirs}; do \ + (cd $$dir && $(MAKE) all) \ + || case "$(MFLAGS)" in *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + +install: + @for dir in ${subdirs}; do \ + (cd $$dir && $(MAKE) install) \ + || case "$(MFLAGS)" in *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + +clean: + /bin/rm -f *~ + @for dir in ${subdirs}; do \ + (cd $$dir && $(MAKE) clean) \ + || case "$(MFLAGS)" in *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + +distclean: + @for dir in ${subdirs}; do \ + (cd $$dir && $(MAKE) distclean) \ + || case "$(MFLAGS)" in *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + /bin/rm -f Makefile config.h config.status config.cache config.log intltool-extract intltool-merge intltool-update rules configure aclocal.m4 + /bin/rm -rf autom4te.cache/ + +# automatic re-running of configure if the configure.in file has changed +${srcdir}/configure: configure.in aclocal.m4 + cd ${srcdir} && autoconf + +# autoheader might not change config.h.in, so touch a stamp file +${srcdir}/config.h.in: stamp-h.in +${srcdir}/stamp-h.in: configure.in aclocal.m4 + cd ${srcdir} && autoheader + echo timestamp > ${srcdir}/stamp-h.in + +config.h: stamp-h +stamp-h: config.h.in config.status + ./config.status +Makefile: Makefile.in config.status + ./config.status +config.status: configure + ./config.status --recheck + diff --git a/README b/README new file mode 100644 index 0000000..274b494 --- /dev/null +++ b/README @@ -0,0 +1,91 @@ +This short document is originally based on eggdrop's README file. + +Contents + +0. Important notice +1. What is BotCommander +2. How do I get BotCommander? +3. Quick startup +4. Frequently Asked Questions +5. Legal stuff +6. Documentation +7. Obtaining help + + _________________________________________________________________ + + + (0) NOTICE + + Please read this document, and the original BotCommander documentation + before asking for help! These files contain almost everything possible, and + are always growing, as people ask me more and more questions. + + _________________________________________________________________ + + + (1) WHAT IS BOTCOMMANDER? + + BotCommander is a customisable telnet client, heavily specialized with the + usage with Eggdrop IRC bots. Currently it possesses only the planned basic + functionality, but I have many-many plans, such as module-writing, + scripting and such. + + BotCommander is continously updated: bugs are getting fixed, and new + features are being added, which sometimes can cause new bugs. Currently + there is a so called "stable" version out there, but there are still known + bugs. + + _________________________________________________________________ + + + (2) HOW DO I GET BOTCOMMANDER? + + Before you can install/compile BotCommander, you will need several other + software installed on your machine. + + As BotCommander currently depends heavily on GTK+ 2 and Gnome 2, you will + need these. If you are planning (or must) install BotCommander from + sources, you will also need the development libraries of them. These + software comes with most of the Linux/Unix distributions, so the only thing + you may have to do is to install them. + + The current stable version (as of writing) is 1.0; you can download it + (amongst many other files) from http://www.botcommander.hu/. + + Optionally, you can get the latest SVN version from + http://www.botcommander.hu/files/botcommander-svn.tar.bz2. BUT BEWARE! This + version may contain code snippets which will never compile on any machine! + This is because I'm a nasty developer, and sometimes upload this kind of + code, so I can continue coding on my other machine after an svn update. I'm + also planning to add anonymous SVN access, but currently I don't have + enough knowledge about SVN to do such thing. + + _________________________________________________________________ + + + (3) QUICK STARTUP + + About installation quick-start you should read the INSTALL file; about + usage, you should go and read the original BotCommander documentation. The + latter is written in DocBook XML, and is compiled into a PDF document upon + a successful installation. It can be found in the doc/ directory. + + _________________________________________________________________ + + + (4) FREQUENTLY ASKED QUESTIONS + + _________________________________________________________________ + + + (5) LEGAL STUFF + + _________________________________________________________________ + + + (6) DOCUMENTATION + + _________________________________________________________________ + + + (7) OBTAINING HELP diff --git a/TODO b/TODO new file mode 100644 index 0000000..0878181 --- /dev/null +++ b/TODO @@ -0,0 +1,23 @@ +* Preferences + - Save recalled command at the end of history? + - Save command to history which is already there somewhere? + +* Bot list + - Edit Save in conf backend + +* Command completion + +* If there is a command which can be abbreviated and one + which can not, get_command_from_abbrev() should return the former. + +* User should be able to set local vhost to use. + +* (Channel and Handle list) hideable. + +* Create a status icon. + +* BotCommander SWITCH command. This will act like the CONNECT command, but it will connect in a new tab. If the specified bot is already connected in one of the tabs, BotCommander will switch to that tab instead of opening a new one. + +* Contents of aclocal.m4 can be splitted somehow. But where to? + +* http://www.botcommander.hu/files/botcommander-latest.tar.bz2 <= http://www.botcommander.hu/latest diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..bbb4bef --- /dev/null +++ b/config.h.in @@ -0,0 +1,165 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * config.h.in + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * This file holds some default settings. + }}} */ + +/* This is the GConf path where BC stores it's settings. You should leave this + * as the default */ +#define GCONF2_ROOT "/apps/botcommander" + +/* {{{ Default settings */ +#define DEFAULT_SCROLL_ON_OUTPUT TRUE +#define DEFAULT_CHANGE_TO_MESSAGE TRUE +#define DEFAULT_DEBUG FALSE +#define DEFAULT_TRANSPARENT_BACKGROUND FALSE +#define DEFAULT_BACKGROUND_SATURATION 1.0 +#define DEFAULT_DEFAULT_MODE "B" +#define DEFAULT_VTE_FONT "Courier 10 Pitch 12" +#define DEFAULT_CHANGE_TO_NEW_TAB FALSE +#define DEFAULT_HISTORY_LENGTH 100 +/* }}} */ + +/* Eggdrop itself uses ISO-8859-1 when using the default english language. You + * only have to change this if you use a different language file (e.g hungarian + * is usually in ISO-8859-2), or you use a script or module which sends out + * characters in a different character set. */ +#define BOT_CHARSET "ISO-8859-1" + +#define MAX_READ_LINE_LEN 1024 + +/* config.h.in. Most of this file is generated from configure.in by + * autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* GETTEXT package name */ +#undef GETTEXT_PACKAGE + +/* Define to 1 if you have the `gethostbyname' function. */ +#undef HAVE_GETHOSTBYNAME + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBINTL_H + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the `setlocale' function. */ +#undef HAVE_SETLOCALE + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strtol' function. */ +#undef HAVE_STRTOL + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Package pixmaps directory */ +#undef PACKAGE_PIXMAPS_DIR + +/* Package local directory */ +#undef PACKAGE_LOCALE_DIR + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..583c6c3 --- /dev/null +++ b/configure.in @@ -0,0 +1,110 @@ +AC_PREREQ(2.60) +AC_INIT(BotCommander, 1.0, polesz@botcommander.hu) +AM_INIT_AUTOMAKE + +PACKAGE=botcommander +BOTCOMMANDER_VERSION=1.0 +ALL_LINGUAS=hu +GETTEXT_PACKAGE=botcommander + +GLIB_REQUIRED=2.0.6 +GDK_PIXBUF_REQUIRED=2.0.0 +GTK_REQUIRED=2.2.0 +GNOME_REQUIRED=2.0.2 +GNOME_UI_REQUIRED=2.0.2 +VTE_REQUIRED=0.9.0 + +AC_GNU_SOURCE +AM_GNU_GETTEXT +AM_GLIB_GNU_GETTEXT + +AC_SUBST(GLIB_REQUIRED) +AC_SUBST(GDK_PIXBUF_REQUIRED) +AC_SUBST(GTK_REQUIRED) +AC_SUBST(GNOME_REQUIRED) +AC_SUBST(GNOME_UI_REQUIRED) +AC_SUBST(VTE_REQUIRED) +AC_SUBST(GETTEXT_PACKAGE) +AC_SUBST(PACKAGE) + +AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [GETTEXT package name]) + +if test "x${prefix}" = "xNONE"; then + packageprefix=${ac_default_prefix} +else + packageprefix=${prefix} +fi + +if test "x${prefix}" = "xNONE"; then + AC_DEFINE_UNQUOTED(PACKAGE_LOCALE_DIR, "${ac_default_prefix}/${DATADIRNAME}/locale", [Package local directory]) +else + AC_DEFINE_UNQUOTED(PACKAGE_LOCALE_DIR, "${prefix}/${DATADIRNAME}/locale", [Package local directory]) +fi + +packagepixmapsdir=share/pixmaps/${PACKAGE} + +PACKAGE_PIXMAPS_DIR="${packageprefix}/${packagepixmapsdir}" +AC_SUBST(PACKAGE_PIXMAPS_DIR) + +AC_DEFINE_UNQUOTED(PACKAGE_PIXMAPS_DIR, "${packageprefix}/${packagepixmapsdir}", [Package pixmaps directory]) + +AC_CONFIG_HEADER([config.h]) + +AC_ARG_ENABLE(debug, [ --enable-debug Enable debug mode], CFLAGS="$CFLAGS -DDEBUG -g -Wall") + +dnl Check for required programs +AC_PROG_CC +AC_PROG_CPP +AC_PROG_INSTALL +IT_PROG_INTLTOOL +AC_CHECK_PROGS([TEXI2PDF], [texi2pdf]) + +dnl Check for extensions +AC_OBJEXT +AC_EXEEXT + +dnl Check for math library +AC_CHECK_LIB([m], [exp10]) +AC_ISC_POSIX + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([fcntl.h libintl.h locale.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SSIZE_T + +# Checks for library functions. +AC_FUNC_MALLOC +AC_TYPE_SIGNAL +AC_CHECK_FUNCS([gethostbyname memset setlocale socket strchr strerror strtol]) + +PKG_PROG_PKG_CONFIG([0.9.0]) + +if test x$PKG_CONFIG = xno; then + AC_MSG_ERROR(Please install the pkg-config package!); +fi + +PKG_CHECK_MODULES(BOTCOMMANDER, glib-2.0 >= $GLIB_REQUIRED gtk+-2.0 >= $GTK_REQUIRED libgnome-2.0 >= $GNOME_REQUIRED libgnomeui-2.0 >= $GNOME_REQUIRED vte >= $VTE_REQUIRED gconf-2.0) + +AC_SUBST(BOTCOMMANDER_CFLAGS) +AC_SUBST(BOTCOMMANDER_LIBS) + +AM_GCONF_SOURCE_2 + +AC_PATH_PROG([GCONFTOOL], [gconftool-2], [no]) +if test "x$GCONFTOOL" = "xno"; then + AC_MSG_ERROR([gconftool-2 executable not found in your path - should be installed with GConf]) +fi + +AC_CONFIG_FILES([rules + Makefile + data/Makefile + doc/Makefile + src/Makefile + pixmaps/Makefile + po/Makefile.in + data/botcommander.desktop.in + data/botcommander.schemas]) +AC_OUTPUT diff --git a/create_source_htmls b/create_source_htmls new file mode 100755 index 0000000..07260ba --- /dev/null +++ b/create_source_htmls @@ -0,0 +1,33 @@ +#! /bin/sh + +MAIN_DIR=source_html +C2HTML=`which c2html` + +if [ x$C2HTML = x ] +then + echo "c2html not found. Please install that first!" + exit 1 +fi + +rm -rf $MAIN_DIR +mkdir -p $MAIN_DIR + +echo " + + BotCommander sources in HTML + + +

BotCommander sources in HTML

" >> $MAIN_DIR/index.html + +for FILE in `find -name \*.[ch]` +do + DIR=`dirname $FILE` + mkdir -p $MAIN_DIR/$DIR + cat $FILE | c2html > $MAIN_DIR/$FILE.html + echo " $FILE
" >> $MAIN_DIR/index.html +done + +echo " +" >> $MAIN_DIR/index.html + +exit 0 diff --git a/data/Makefile.in b/data/Makefile.in new file mode 100644 index 0000000..2526766 --- /dev/null +++ b/data/Makefile.in @@ -0,0 +1,46 @@ +include ../rules + +GCONFTOOL = @GCONFTOOL@ + +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ +sysconfdir = @sysconfdir@ +datarootdir = @datarootdir@ +datadir = @datadir@ + +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@ +INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@ +GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ +GCONF_SCHEMAS_INSTALL_TRUE = @GCONF_SCHEMAS_INSTALL_TRUE@ +GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ + +gnomemenudir = $(datadir)/applications +gnomemenu_premerge_file = botcommander.desktop.in +gnomemenu_DATA = $(gnomemenu_premerge_file:.desktop.in=.desktop) + +schema_in_files = botcommander.schemas.in +schemadir = $(GCONF_SCHEMA_FILE_DIR) +schema_DATA = $(schema_in_files:.schemas.in=.schemas) + +all: $(gnomemenu_DATA) +clean: + +install: $(gnomemenu_DATA) +@GCONF_SCHEMAS_INSTALL_TRUE@ if test -z "$(DESTDIR)" ; then \ +@GCONF_SCHEMAS_INSTALL_TRUE@ for p in $(schema_DATA) ; do \ +@GCONF_SCHEMAS_INSTALL_TRUE@ GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(top_builddir)/data/$$p >&1 > /dev/null; \ +@GCONF_SCHEMAS_INSTALL_TRUE@ done \ +@GCONF_SCHEMAS_INSTALL_TRUE@ fi + $(top_srcdir)/mkinstalldirs $(gnomemenudir) + $(top_srcdir)/mkinstalldirs $(schemadir) + $(INSTALL) -m 0644 $(gnomemenu_DATA) $(gnomemenudir) + $(INSTALL) -m 0644 $(schema_DATA) $(schemadir) + +distclean: + rm -f botcommander.desktop botcommander.desktop.in botcommander.schemas Makefile + +@INTLTOOL_DESKTOP_RULE@ + +@INTLTOOL_SCHEMAS_RULE@ + diff --git a/data/botcommander.desktop.in.in b/data/botcommander.desktop.in.in new file mode 100644 index 0000000..d48c9f2 --- /dev/null +++ b/data/botcommander.desktop.in.in @@ -0,0 +1,11 @@ +[Desktop Entry] +_Name=BotCommander +_Comment=BotCommander eggdrop client +Exec=botcommander +Icon=@PACKAGE_PIXMAPS_DIR@/bc48_trans.png +Terminal=false +X-MultipleArgs=false +Type=Application +Categories=Application;Network; +Encoding=UTF-8 +StartupNotify=true diff --git a/data/botcommander.schemas.in b/data/botcommander.schemas.in new file mode 100644 index 0000000..4af305e --- /dev/null +++ b/data/botcommander.schemas.in @@ -0,0 +1,154 @@ + + + + /schemas/apps/botcommander/background_saturation + /apps/botcommander/background_saturation + botcommander + float + 0.0 + + Background is not opaque by default + background_saturation only has effect when transparent_background is true. If so, this value gives the opacity of the VTE + + + A háttér alapértelmezés szerint nem áttetsző + A background_saturation értékét csak akkor veszi figyelembe a program, ha a transparent_background értéke true. Ha így van, ez az érték adja meg a VTE áttetszőségének mértékét. + + + + /schemas/apps/botcommander/change_to_message + /apps/botcommander/change_to_message + botcommander + bool + true + + By default, BotCommander will change to Message mode after connecting to a bot + When this option is true, BotCommander will set Message mode after connecting to a bot + + + Alapértelmezés szerint a BotCommander átvált Üzenet módba miután csatlakozott egy bothoz + Ha ez az opció true, a BotCommander átvált Üzenet módba, miután csatlakozott egy bothoz + + + + /schemas/apps/botcommander/change_to_new_tab + /apps/botcommander/change_to_new_tab + botcommander + bool + true + + BotCommander changes to the newly created tab by default + When this value is true, BotCommander will change to the newly opened tab. Otherwise, the new tab won't be activated + + + A BotCommander alapértelmezés szerint átvált az újonnan létrehozott fülre + Ha ez az érték true, a BotCommander automatikusan átvált az újonnan megnyitott fülre. Ha nem, a fül nem lesz aktiválva + + + + /schemas/apps/botcommander/debug + /apps/botcommander/debug + botcommander + bool + false + + By default, BotCommander won't print out debug messages + If this option is true, and the code is compiled with the DEBUG flag, BotCommander will print debug messages + + + Alapértelmezés szerint a BotCommander nem fogja kiírni a hibakereső üzeneteket + Ha ez az opció be van kapcsolva, és a kód a DEBUG opcióval lett fordítva, a BotCommander folyamatosan kiírja a hibakereső üzeneteket + + + + /schemas/apps/botcommander/default_mode + /apps/botcommander/default_mode + botcommander + string + B + + By default, BotCommander will use BotCommander command mode + When you open a new tab, BotCommander will use this mod as the initial mode of the tab + + + Alapértelmezés szerint a BotCommander Botcommander Parancs-módot használ + Mikor megnyitsz egy új fület, a BotCommander ezt a módot állítja be rajta + + + + /schemas/apps/botcommander/history_length + /apps/botcommander/history_length + botcommander + int + 300 + + The default scrollback-size for the VTEs is 300 lines + The VTEs scrollback is set to this value + + + A VTE-k memóritára alapértelmezésben 300 sor + A VTE-k memóriatárának mérete ennyi sorra van állítva + + + + /schemas/apps/botcommander/sanity + /apps/botcommander/sanity + botcommander + string + Needed for gconf sanity check, please don't remove! + + NEVER CHANGE THIS VALUE! + NEVER CHANGE THIS VALUE! This is for sanity check. Maybe I'll remove it soon. NEVER CHANGE THIS VALUE! + + + SOHA NE VÁLTOZTASD MEG EZT AZ ÉRTÉKET! + SOHA NE VÁLTOZTASD MEG EZT AZ ÉRTÉKET! Ez a gconf ellenőrzésére szolgál. Valószínűleg hamarosan törlöm. SOHA NE VÁLTOZTAST MEG EZT AZ ÉRTÉKET! + + + + /schemas/apps/botcommander/scroll_on_output + /apps/botcommander/scroll_on_output + botcommander + bool + true + + By default, BotCommander will scroll the contents of the VTE when new data arrives from the bot + When this option is true, BotCommander will automatically scroll to the bottom of the window when a new line arrives from the bot + + + Alapértelmezés szerint a BotCommander a VTE aljára görget, ha új adat érkezik a bottól + Ha ez az opció true, a BotCommander automatikusan a VTE aljára görget, ha új adat érkezik a bottól + + + + /schemas/apps/botcommander/transparent_background + /apps/botcommander/transparent_background + botcommander + bool + false + + By default, the VTEs' background is not transparent + If you set this option to true, and background_saturation to a number greater then 0, the VTEs' background will be opaque + + + Alapértelmezés szerint a VTE-k háttere nem áttetsző + Ha ezt az értéket true-ra állítod, a background_saturation értékét pedig 0-nál nagyobbra, a VTE-k háttere áttetsző lesz + + + + /schemas/apps/botcommander/vte_font + /apps/botcommander/vte_font + botcommander + string + Courier 10 Pitch 12 + + By default, the VTEs use the Courier 10 Pitch font with a 12pt size + The VTEs' font will set to this value + + + Alapértelmezés szerint a VTE-k a Courier 10 Pitch font 12pt méretű változatát használják + Ez az érték lesz megadva, mint a VTE-k betűkészlete + + + + diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 0000000..fa8abec --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,6 @@ +botcommander for Debian +----------------------- + + + + -- Gergely POLONKAI , Mon, 11 Sep 2006 07:31:20 +0200 diff --git a/debian/botcommander-default.ex b/debian/botcommander-default.ex new file mode 100644 index 0000000..4813ccd --- /dev/null +++ b/debian/botcommander-default.ex @@ -0,0 +1,10 @@ +# Defaults for botcommander initscript +# sourced by /etc/init.d/botcommander +# installed at /etc/default/botcommander by the maintainer scripts + +# +# This is a POSIX shell fragment +# + +# Additional options that are passed to the Daemon. +DAEMON_OPTS="" diff --git a/debian/botcommander.doc-base.EX b/debian/botcommander.doc-base.EX new file mode 100644 index 0000000..0be1ab0 --- /dev/null +++ b/debian/botcommander.doc-base.EX @@ -0,0 +1,22 @@ +Document: botcommander +Title: Debian botcommander Manual +Author: Gergely POLONKAI (polesz@botcommander.hu) +Abstract: This manual describes what botcommander is + and how it can be used to + manage online manuals on Debian systems. +Section: utils + +Format: debiandoc-sgml +Files: /usr/share/doc/botcommander/botcommander.sgml.gz + +Format: postscript +Files: /usr/share/doc/botcommander/botcommander.ps.gz + +Format: text +Files: /usr/share/doc/botcommander/botcommander.text.gz + +Format: HTML +Index: /usr/share/doc/botcommander/html/index.html +Files: /usr/share/doc/botcommander/html/*.html + + diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..1237317 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,6 @@ +botcommander (1.0-1) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- POLONKAI Gergely Mon, 11 Sep 2006 07:41:46 +0200 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..dba8943 --- /dev/null +++ b/debian/control @@ -0,0 +1,14 @@ +Source: botcommander +Section: utils +Priority: optional +Maintainer: Gergely POLONKAI +Build-Depends: debhelper (>= 5), autotools-dev, libgnomeui-0, libvte4, libgtk2.0-0, libgconf2-4 +Standards-Version: 3.7.2 + +Package: botcommander +Architecture: i386 +Depends: ${shlibs:Depends} +Description: BotCommander is a graphical eggdrop client for UN*X sytems + BotCommander is a graphical eggdrop client written for UN*X systems. This is + still a work-in-progress, as it already functional. There are still many plans + which are not implemented yet. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..a7928bf --- /dev/null +++ b/debian/copyright @@ -0,0 +1,14 @@ +This package was debianized by Gergely POLONKAI on +Mon, 11 Sep 2006 07:31:20 +0200. + +It was downloaded from http://www.botcommander.hu/ + +Upstream Author: Gergely POLONKAI + +Copyright: Gergely POLONKAI, 2006 + +License: GNU GPL, version 2 or later + +The Debian packaging is (C) 2006, Gergely POLONKAI and +is licensed under the GPL, see `/usr/share/common-licenses/GPL'. + diff --git a/debian/cron.d.ex b/debian/cron.d.ex new file mode 100644 index 0000000..af409a3 --- /dev/null +++ b/debian/cron.d.ex @@ -0,0 +1,4 @@ +# +# Regular cron jobs for the botcommander package +# +0 4 * * * root botcommander_maintenance diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..b99fd7c --- /dev/null +++ b/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/share/pixmaps/botcommander diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..1333ed7 --- /dev/null +++ b/debian/docs @@ -0,0 +1 @@ +TODO diff --git a/debian/emacsen-install.ex b/debian/emacsen-install.ex new file mode 100644 index 0000000..036afa3 --- /dev/null +++ b/debian/emacsen-install.ex @@ -0,0 +1,45 @@ +#! /bin/sh -e +# /usr/lib/emacsen-common/packages/install/botcommander + +# Written by Jim Van Zandt , borrowing heavily +# from the install scripts for gettext by Santiago Vila +# and octave by Dirk Eddelbuettel . + +FLAVOR=$1 +PACKAGE=botcommander + +if [ ${FLAVOR} = emacs ]; then exit 0; fi + +echo install/${PACKAGE}: Handling install for emacsen flavor ${FLAVOR} + +#FLAVORTEST=`echo $FLAVOR | cut -c-6` +#if [ ${FLAVORTEST} = xemacs ] ; then +# SITEFLAG="-no-site-file" +#else +# SITEFLAG="--no-site-file" +#fi +FLAGS="${SITEFLAG} -q -batch -l path.el -f batch-byte-compile" + +ELDIR=/usr/share/emacs/site-lisp/${PACKAGE} +ELCDIR=/usr/share/${FLAVOR}/site-lisp/${PACKAGE} + +# Install-info-altdir does not actually exist. +# Maybe somebody will write it. +if test -x /usr/sbin/install-info-altdir; then + echo install/${PACKAGE}: install Info links for ${FLAVOR} + install-info-altdir --quiet --section "" "" --dirname=${FLAVOR} /usr/info/${PACKAGE}.info.gz +fi + +install -m 755 -d ${ELCDIR} +cd ${ELDIR} +FILES=`echo *.el` +cp ${FILES} ${ELCDIR} +cd ${ELCDIR} + +cat << EOF > path.el +(setq load-path (cons "." load-path) byte-compile-warnings nil) +EOF +${FLAVOR} ${FLAGS} ${FILES} +rm -f *.el path.el + +exit 0 diff --git a/debian/emacsen-remove.ex b/debian/emacsen-remove.ex new file mode 100644 index 0000000..7dc9741 --- /dev/null +++ b/debian/emacsen-remove.ex @@ -0,0 +1,15 @@ +#!/bin/sh -e +# /usr/lib/emacsen-common/packages/remove/botcommander + +FLAVOR=$1 +PACKAGE=botcommander + +if [ ${FLAVOR} != emacs ]; then + if test -x /usr/sbin/install-info-altdir; then + echo remove/${PACKAGE}: removing Info links for ${FLAVOR} + install-info-altdir --quiet --remove --dirname=${FLAVOR} /usr/info/botcommander.info.gz + fi + + echo remove/${PACKAGE}: purging byte-compiled files for ${FLAVOR} + rm -rf /usr/share/${FLAVOR}/site-lisp/${PACKAGE} +fi diff --git a/debian/emacsen-startup.ex b/debian/emacsen-startup.ex new file mode 100644 index 0000000..70f1a36 --- /dev/null +++ b/debian/emacsen-startup.ex @@ -0,0 +1,25 @@ +;; -*-emacs-lisp-*- +;; +;; Emacs startup file, e.g. /etc/emacs/site-start.d/50botcommander.el +;; for the Debian botcommander package +;; +;; Originally contributed by Nils Naumann +;; Modified by Dirk Eddelbuettel +;; Adapted for dh-make by Jim Van Zandt + +;; The botcommander package follows the Debian/GNU Linux 'emacsen' policy and +;; byte-compiles its elisp files for each 'emacs flavor' (emacs19, +;; xemacs19, emacs20, xemacs20...). The compiled code is then +;; installed in a subdirectory of the respective site-lisp directory. +;; We have to add this to the load-path: +(let ((package-dir (concat "/usr/share/" + (symbol-name flavor) + "/site-lisp/botcommander"))) +;; If package-dir does not exist, the botcommander package must have +;; removed but not purged, and we should skip the setup. + (when (file-directory-p package-dir) + (setq load-path (cons package-dir load-path)) + (autoload 'botcommander-mode "botcommander-mode" + "Major mode for editing botcommander files." t) + (add-to-list 'auto-mode-alist '("\\.botcommander$" . botcommander-mode)))) + diff --git a/debian/init.d.ex b/debian/init.d.ex new file mode 100644 index 0000000..f975873 --- /dev/null +++ b/debian/init.d.ex @@ -0,0 +1,74 @@ +#! /bin/sh +# +# skeleton example file to build /etc/init.d/ scripts. +# This file should be used to construct scripts for /etc/init.d. +# +# Written by Miquel van Smoorenburg . +# Modified for Debian +# by Ian Murdock . +# +# Version: @(#)skeleton 1.9 26-Feb-2001 miquels@cistron.nl +# + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/sbin/botcommander +NAME=botcommander +DESC=botcommander + +test -x $DAEMON || exit 0 + +# Include botcommander defaults if available +if [ -f /etc/default/botcommander ] ; then + . /etc/default/botcommander +fi + +set -e + +case "$1" in + start) + echo -n "Starting $DESC: " + start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ + --exec $DAEMON -- $DAEMON_OPTS + echo "$NAME." + ;; + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \ + --exec $DAEMON + echo "$NAME." + ;; + #reload) + # + # If the daemon can reload its config files on the fly + # for example by sending it SIGHUP, do it here. + # + # If the daemon responds to changes in its config file + # directly anyway, make this a do-nothing entry. + # + # echo "Reloading $DESC configuration files." + # start-stop-daemon --stop --signal 1 --quiet --pidfile \ + # /var/run/$NAME.pid --exec $DAEMON + #;; + restart|force-reload) + # + # If the "reload" option is implemented, move the "force-reload" + # option to the "reload" entry above. If not, "force-reload" is + # just the same as "restart". + # + echo -n "Restarting $DESC: " + start-stop-daemon --stop --quiet --pidfile \ + /var/run/$NAME.pid --exec $DAEMON + sleep 1 + start-stop-daemon --start --quiet --pidfile \ + /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS + echo "$NAME." + ;; + *) + N=/etc/init.d/$NAME + # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2 + echo "Usage: $N {start|stop|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/debian/manpage.1.ex b/debian/manpage.1.ex new file mode 100644 index 0000000..bd395cc --- /dev/null +++ b/debian/manpage.1.ex @@ -0,0 +1,59 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH BOTCOMMANDER SECTION "szeptember 11, 2006" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +botcommander \- program to do something +.SH SYNOPSIS +.B botcommander +.RI [ options ] " files" ... +.br +.B bar +.RI [ options ] " files" ... +.SH DESCRIPTION +This manual page documents briefly the +.B botcommander +and +.B bar +commands. +.PP +.\" TeX users may be more comfortable with the \fB\fP and +.\" \fI\fP escape sequences to invode bold face and italics, +.\" respectively. +\fBbotcommander\fP is a program that... +.SH OPTIONS +These programs follow the usual GNU command line syntax, with long +options starting with two dashes (`-'). +A summary of options is included below. +For a complete description, see the Info files. +.TP +.B \-h, \-\-help +Show summary of options. +.TP +.B \-v, \-\-version +Show version of program. +.SH SEE ALSO +.BR bar (1), +.BR baz (1). +.br +The programs are documented fully by +.IR "The Rise and Fall of a Fooish Bar" , +available via the Info system. +.SH AUTHOR +botcommander was written by . +.PP +This manual page was written by Gergely POLONKAI , +for the Debian project (but may be used by others). diff --git a/debian/manpage.sgml.ex b/debian/manpage.sgml.ex new file mode 100644 index 0000000..c58d072 --- /dev/null +++ b/debian/manpage.sgml.ex @@ -0,0 +1,156 @@ + manpage.1'. You may view + the manual page with: `docbook-to-man manpage.sgml | nroff -man | + less'. A typical entry in a Makefile or Makefile.am is: + +manpage.1: manpage.sgml + docbook-to-man $< > $@ + + + The docbook-to-man binary is found in the docbook-to-man package. + Please remember that if you create the nroff version in one of the + debian/rules file targets (such as build), you will need to include + docbook-to-man in your Build-Depends control field. + + --> + + + FIRSTNAME"> + SURNAME"> + + szeptember 11, 2006"> + + SECTION"> + polesz@botcommander.hu"> + + BOTCOMMANDER"> + + + Debian"> + GNU"> + GPL"> +]> + + + +
+ &dhemail; +
+ + &dhfirstname; + &dhsurname; + + + 2003 + &dhusername; + + &dhdate; +
+ + &dhucpackage; + + &dhsection; + + + &dhpackage; + + program to do something + + + + &dhpackage; + + + + + + + + DESCRIPTION + + This manual page documents briefly the + &dhpackage; and bar + commands. + + This manual page was written for the &debian; distribution + because the original program does not have a manual page. + Instead, it has documentation in the &gnu; + Info format; see below. + + &dhpackage; is a program that... + + + + OPTIONS + + These programs follow the usual &gnu; command line syntax, + with long options starting with two dashes (`-'). A summary of + options is included below. For a complete description, see the + Info files. + + + + + + + + Show summary of options. + + + + + + + + Show version of program. + + + + + + SEE ALSO + + bar (1), baz (1). + + The programs are documented fully by The Rise and + Fall of a Fooish Bar available via the + Info system. + + + AUTHOR + + This manual page was written by &dhusername; &dhemail; for + the &debian; system (but may be used by others). Permission is + granted to copy, distribute and/or modify this document under + the terms of the &gnu; General Public License, Version 2 any + later version published by the Free Software Foundation. + + + On Debian systems, the complete text of the GNU General Public + License can be found in /usr/share/common-licenses/GPL. + + + +
+ + + + diff --git a/debian/manpage.xml.ex b/debian/manpage.xml.ex new file mode 100644 index 0000000..bafd0d6 --- /dev/null +++ b/debian/manpage.xml.ex @@ -0,0 +1,148 @@ + +.
will be generated. You may view the +manual page with: nroff -man .
| less'. A +typical entry in a Makefile or Makefile.am is: + +DB2MAN=/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/\ +manpages/docbook.xsl +XP=xsltproc -''-nonet + +manpage.1: manpage.dbk + $(XP) $(DB2MAN) $< + +The xsltproc binary is found in the xsltproc package. The +XSL files are in docbook-xsl. Please remember that if you +create the nroff version in one of the debian/rules file +targets (such as build), you will need to include xsltproc +and docbook-xsl in your Build-Depends control field. + +--> + + + FIRSTNAME"> + SURNAME"> + + szeptember 11, 2006"> + + SECTION"> + polesz@botcommander.hu"> + + BOTCOMMANDER"> + + + Debian"> + GNU"> + GPL"> +]> + + + +
+ &dhemail; +
+ + &dhfirstname; + &dhsurname; + + + 2003 + &dhusername; + + &dhdate; +
+ + &dhucpackage; + + &dhsection; + + + &dhpackage; + + program to do something + + + + &dhpackage; + + + + + + + + DESCRIPTION + + This manual page documents briefly the + &dhpackage; and bar + commands. + + This manual page was written for the &debian; distribution + because the original program does not have a manual page. + Instead, it has documentation in the &gnu; + Info format; see below. + + &dhpackage; is a program that... + + + + OPTIONS + + These programs follow the usual &gnu; command line syntax, + with long options starting with two dashes (`-'). A summary of + options is included below. For a complete description, see the + Info files. + + + + + + + + Show summary of options. + + + + + + + + Show version of program. + + + + + + SEE ALSO + + bar (1), baz (1). + + The programs are documented fully by The Rise and + Fall of a Fooish Bar available via the + Info system. + + + AUTHOR + + This manual page was written by &dhusername; &dhemail; for + the &debian; system (but may be used by others). Permission is + granted to copy, distribute and/or modify this document under + the terms of the &gnu; General Public License, Version 2 any + later version published by the Free Software Foundation. + + + On Debian systems, the complete text of the GNU General Public + License can be found in /usr/share/common-licenses/GPL. + + + +
+ diff --git a/debian/menu.ex b/debian/menu.ex new file mode 100644 index 0000000..dc29b4b --- /dev/null +++ b/debian/menu.ex @@ -0,0 +1,2 @@ +?package(botcommander):needs="X11|text|vc|wm" section="Apps/see-menu-manual"\ + title="botcommander" command="/usr/bin/botcommander" diff --git a/debian/postinst.ex b/debian/postinst.ex new file mode 100644 index 0000000..1cd89cd --- /dev/null +++ b/debian/postinst.ex @@ -0,0 +1,42 @@ +#!/bin/sh +# postinst script for botcommander +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package +# + +case "$1" in + configure) + + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/debian/postrm.ex b/debian/postrm.ex new file mode 100644 index 0000000..cf20add --- /dev/null +++ b/debian/postrm.ex @@ -0,0 +1,38 @@ +#!/bin/sh +# postrm script for botcommander +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' overwrit>r> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + + + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/debian/preinst.ex b/debian/preinst.ex new file mode 100644 index 0000000..cc8f816 --- /dev/null +++ b/debian/preinst.ex @@ -0,0 +1,38 @@ +#!/bin/sh +# preinst script for botcommander +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `install' +# * `install' +# * `upgrade' +# * `abort-upgrade' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + install|upgrade) + ;; + + abort-upgrade) + ;; + + *) + echo "preinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/debian/prerm.ex b/debian/prerm.ex new file mode 100644 index 0000000..bb00807 --- /dev/null +++ b/debian/prerm.ex @@ -0,0 +1,38 @@ +#!/bin/sh +# prerm script for botcommander +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + ;; + failed-upgrade) + ;; + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..2f33fdc --- /dev/null +++ b/debian/rules @@ -0,0 +1,107 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) + + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +config.status: configure + dh_testdir + # Add here commands to configure the package. + ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs" --with-gconf-schema-file-dir=\$${prefix}/share/gconf/schemas + + +build: build-stamp + +build-stamp: config.status + dh_testdir + + # Add here commands to compile the package. + $(MAKE) + #docbook-to-man debian/botcommander.sgml > botcommander.1 + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) distclean +ifneq "$(wildcard /usr/share/misc/config.sub)" "" + cp -f /usr/share/misc/config.sub config.sub +endif +ifneq "$(wildcard /usr/share/misc/config.guess)" "" + cp -f /usr/share/misc/config.guess config.guess +endif + + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/botcommander. + $(MAKE) install prefix=$(CURDIR)/debian/botcommander/usr + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/debian/watch.ex b/debian/watch.ex new file mode 100644 index 0000000..27a0f34 --- /dev/null +++ b/debian/watch.ex @@ -0,0 +1,22 @@ +# Example watch control file for uscan +# Rename this file to "watch" and then you can run the "uscan" command +# to check for upstream updates and more. +# See uscan(1) for format + +# Compulsory line, this is a version 3 file +version=3 + +# Uncomment to examine a Webpage +# +#http://www.example.com/downloads.php botcommander-(.*)\.tar\.gz + +# Uncomment to examine a Webserver directory +#http://www.example.com/pub/botcommander-(.*)\.tar\.gz + +# Uncommment to examine a FTP server +#ftp://ftp.example.com/pub/botcommander-(.*)\.tar\.gz debian uupdate + +# Uncomment to find new files on sourceforge, for debscripts >= 2.9 +# http://sf.net/botcommander/botcommander-(.*)\.tar\.gz + + diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..3c8b1d9 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,31 @@ +include ../rules + +TEXI2PDF = @TEXI2PDF@ + +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +prefix = @prefix@ +datarootdir = @datarootdir@ +docdir = @docdir@ +PDFTARGETDIR = @pdfdir@ +top_srcdir = @top_srcdir@ + +all: $(DOC_OBJECTS) + +botcommander.pdf: botcommander.texinfo + $(TEXI2PDF) botcommander.texinfo + +clean: + $(RM) $(DOC_OBJECTS) + $(RM) botcommander.aux botcommander.cp botcommander.cps botcommander.fn \ + botcommander.ky botcommander.log botcommander.pg botcommander.toc \ + botcommander.tp botcommander.vr + +distclean: clean + $(RM) Makefile config.status config.cache config.log + +install: all + $(top_srcdir)/mkinstalldirs $(PDFTARGETDIR) + $(INSTALL) -m 0644 botcommander.pdf $(PDFTARGETDIR) + +.PHONY: all clean distclean install + diff --git a/doc/botcommander.texinfo b/doc/botcommander.texinfo new file mode 100644 index 0000000..4ed4611 --- /dev/null +++ b/doc/botcommander.texinfo @@ -0,0 +1,349 @@ +\input texinfo +@c vim:textwidth=80 +@c Header +@setfilename botcommander.info +@include version.texinfo +@settitle BotCommander @value{VERSION} +@documentdescription +BotCommander manual for version @value{VERSION} +@end documentdescription +@setchapternewpage odd +@firstparagraphindent insert + +@c Summary and Copyright +@copying +This manual is for BotCommander +(version @value{VERSION}, @value{UPDATED}), +which is a specialized telnet client. + +Copyright @copyright{} 2005, Gergely POLONKAI + +@quotation +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,'' +and with the Back-Cover Texts as in (a) below. A copy of the +license is included in the section entitled ``GNU Free Documentation +License.'' + +(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify +this GNU Manual, like GNU software. Copies published by the Free +Software Foundation raise funds for GNU development.'' +@end quotation +@end copying + +@dircategory Network Applications +@direntry +* BotCommander: (botcommander). +@end direntry + +@c Title and Copyright +@titlepage +@title BotCommander +@subtitle for version @value{VERSION}, @value{UPDATED} +@author Gergely POLONKAI (@email{polesz@@botcommander.hu}) +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@contents + +@c Top node and master menu +@ifnottex +@node Top, About, , (dir) +@top BotCommander + +@insertcopying +@end ifnottex + +@menu +* About:: About the application +* Overview:: Features of BotCommander +* Installation:: How to install BotCommander +* Invoking:: Command line arguments +* Commands:: Internal commands +* Configuration:: The setup window +* Plans:: Plans in future versions +* Index:: Index +@end menu + +@c Body + +@node About, Overview, Top, Top +@chapter About BotCommander + +@cindex about + +@cindex homepage + +You can reach the project's homepage at @url{http://www.botcommander.hu/}. + +@cindex description + +BotCommander is a small tool, originally written for the Gnome2 interface, to +remotely manage your @url{http://www.eggheads.org/, eggdrop} IRC bots.@* +Actually, it's acting as a small, configurable telnet client, but it will know a +bit more. For example, it has command-line history. While you cannot recall your +previous command in a simple telnet client, you will be able to do it with this +program. As it uses a text box for the command line, you can easily edit that +command. + +The program uses @url{http://www.gnome.org/projects/gconf/, GConf2} +to store its configuration data. You can configure it to use a samba-like config +file instead, so you won't depend that heavily on @url{http://www.gnome.org/, +Gnome 2}, @xref{Installation}. In the near future I also plan +@url{http://www.w3.org/XML/, XML} config backend support. + +On 28 August, 2006 I decided to drop this plan, and also the samba-like config +backend for a longer period. I think the application should first function, and +only after that I can create such addons. + +@cindex status + +The code is in alpha status. You can see how will it look like, also can use +for one connection, and decide if you will like it or not. + +@cindex icon + +BotCommander icon is from @url{http://www.eggheads.org/, Eggdrop}'s official +homepage. I will draw a new one, but until then, this is perfect. + +@node Overview, Installation, About, Top +@chapter Features + +BotCommander is a telnet client and much more. It can connect to one or more +@url{http://www.eggheads.org/, eggdrop} IRC bots, and give commands to them. In +the near future it will also possible to give the same command to each connected +bots. + +Unlike the normal telnet client, this program has command line editing and +recalling possibilities. E.g if you have a long command line such + +@code{ +.process very much ugly paramters username +} +@*what you have to run multiple times, and in which you only change the username, +it is possible to recall the previous command, change the username, and send the +changed command. Thus, you don't have to enter the whole line again and again. + +It uses @url{http://www.gtk.org/, GTK2} and some @url{http://www.gnome.org/, +GnomeUI} components, and stores its configuration data in +@url{http://www.gnome.org/projects/gconf/, GConf2}. + +As it uses tabs, you can connect to many bots in one application, and at last +you won't have one icon for every bot in your task bar. + +If you want (and you are at least have global +o in the bot), you can have a +sidebar on your tabs, in which you can see a list of the channels and the users +you have. For this, you will need to install the @file{botcommander.tcl} script +(can be found in the @file{eggdrop/} directory) in your bot (@code{.source +botcommander.tcl}). When the script loads, or when someone connects to the bot +via DCC + +@node Installation, Invoking, Overview, Top +@chapter How to install? + +@cindex installation + +As BotCommander is currently in alpha phase, you cannot compile it with the +usual + +@example +./configure +make +make install +@end example + +sequence. First, you should edit the config.h file, and change the location of +the pixmaps dir. Then You should run @code{make check} to check if all the +required packages are installed on your system. At the moment these are + +@itemize +@item +pkg-config + +@item +gtk + +@item +vte + +@item +gconf2 + +@item +gnomeui2 +@end itemize + +If all is OK, simply run @code{make}. If nothing goes wrong, the binary will be +src/botcommander. + +If you want to install BotCommander, copy the binary to /usr/local/bin. You +should change the @code{PIXMAPSDIR} variable in @file{config.h} to something +like @code{/usr/local/share/botcommander}, and recompile the whole thing. + +@node Invoking, Commands, Installation, Top +@chapter Command line arguments + +@cindex command line args + +No command line arguments are defined yet. This means that BotCommander +currently accepts the @url{http://www.gnome.org/, Gnome} and +@url{http://www.gtk.org, GTK} standard command line parameters. + +Yet I don't even have any plans for such parameters. + +@node Commands, QUIT, Invoking, Top +@chapter Internal commands + +@cindex command + +BotCommander is a bit like an IRC client. As is, there are many commands built +in. + +Most of the commands can be abbreviated. This means you can shorten a command +while it is still obvious. + +For example, you can write @code{CON botname} instead of +@code{CONNECT botname}, as no other commands begin with ``CON''. + +However, there are some ``dangerous'' commands which cannot be abbreviated. One +such command is QUIT. + +@cindex internal command list + +@menu +* QUIT:: Exits BotCommander +* CLOSE:: Closes the active tab +* CONNECT:: Connects to a bot or a host +* ASSIGN:: Assigns a bot to the active tab +* MODE:: Changes the mode in the current tab +* HISTLIST:: Lists the previously issued commands and sent messages +* BOTLIST:: Opens the bot list window +* PREFERENCES:: Opens the setup dialog +* DISCONNECT:: Disconnects the current tab +@end menu + +@node QUIT, CLOSE, Commands, Commands +@section The QUIT command + +@cindex command, QUIT + +This command simply exists BotCommander. + +If at least one tab is open with an opened connection, BotCommander will pop up +a dialog if the user really wants to exit. + +These commands cannot be abbreviated. + +@node CLOSE, CONNECT, QUIT, Commands +@section The CLOSE command + +@cindex command, CLOSE + +This will close the active tab. If a connection is opened in the tab, +BotCommander will pop up a dialog if the user really wants to do that. + +@node CONNECT, ASSIGN, CLOSE, Commands +@section The CONNECT command + +@cindex command, CONNECT + +This will open a connection. You can use it in several ways. + +If you have already assigned a bot to the tab with the ASSIGN (@xref{ASSIGN}.) command, +you can use it without parameters, so it will connect to the assigned bot. + +If you have a bot in your bot list, you can connect to it with @code{CONNECT +botname}. It will also assign that bot to the tab. + +You can use it in the form @code{CONNECT host port}. + +@node ASSIGN, MODE, CONNECT, Commands +@section The ASSIGN command + +@cindex command, ASSIGN + +Assigns a bot to the active tab. You can use it in the form @code{ASSING +botname} or @code{ASSIGN host port}. After assigning a bot, you can use the +@code{CONNECT} command without parameters to connect to the bot. + +@node MODE, HISTLIST, ASSIGN, Commands +@section The MODE command + +@cindex command, MODE + +Sets the mode in the current tab. It has only one parameter, the new mode +character. It can be B for BotCommander command mode, E for Eggdrop command mode +or M for Message mode. + +You can see the current mode in the right side of the status bar. + +@node HISTLIST, BOTLIST, MODE, Commands +@section The HISTLIST command + +@cindex command, HISTLIST + +It's a very useless command. Prints out all the commands and messages you +entered in the current tab. + +@node BOTLIST, PREFERENCES, HISTLIST, Commands +@section The BOTLIST command + +@cindex command, BOTLIST + +This command simply opens the bot list dialog window. + +@node PREFERENCES, DISCONNECT, BOTLIST, Commands +@section The PREFERENCES command + +@cindex command, PREFERENCES + +This command simply opens the setup dialog. + +@node DISCONNECT, Configuration, PREFERENCES, Commands +@section The DISCONNECT command + +@cindex command, DISCONNECT + +This command forces the disconnection of the current tab. This is useful if you +try to connect a bot which doesn't respond, and you don't want to wait for the +"connection timeout" message before connecting to somewhere else. + +@node Configuration, Plans, DISCONNECT, Top +@chapter The preferences window + +@node Plans, Index, Configuration, Top +@chapter Future plans + +@cindex plans + +@itemize +@item +ADDBOT botname host port [nick] will add a new bot to the bot list + +@item +DELBOT botname will remove a bot from the bot list + +@item +Scripting. BotCommander will be able to run small scripts, perhaps in TCL + +@item +Macros and command aliases, so you have to type only one command to achieve the +same as you type in many + +@item +Windows port. This will be done after the whole application is functioning. So +this will be in the very far future, though I already got requests for it +@end itemize + +@node Index, , Plans, Top +@unnumbered Index + +@printindex cp + +@c End +@bye + diff --git a/doc/botcommander.xml b/doc/botcommander.xml new file mode 100644 index 0000000..a32bb00 --- /dev/null +++ b/doc/botcommander.xml @@ -0,0 +1,542 @@ + + + + BotCommander + + + + + Gergely + + POLONKAI + + + polesz@botcommander.hu + + + + 2005-2007 + + Gergely POLONKAI + + + + + + + I dedicate this book to my girlfriend, as she was so patient while I + wrote it. + + + + + + Table of Contents + + + Part I: About BotCommander and this book + + + Chapter 1: Who should read this book? + + + + Chapter 2: About BotCommander + + + + + + + + Preface + + This document tries to explain the history and usage of the software + BotCommander briefly. + + + + About BotCommander and this book + + + Who should read this book? + + + + Everyone, who handles at least one eggdrop IRC bot + + + + Everyone, who wants to write addons (modules) for + BotCommander + + + + Everyone, who wants to learn the script-writing methods for + BotCommander + + + + + + About BotCommander + + BotCommander is a specialized telnet client, and a bit more. It is + specialized in eggdrop IRC bot handling, enhanced with scripting + possibility, and may also be enhanced with self-written modules (just + like eggdrop itself). + + The project has its own homepage at + http://www.botcommander.hu/ + + + + BotCommander features + + + + Command line history + + + BotCommander has command line history. This means you can + recall your previous commands with the Up/Down keys, edit them, + and/or issue them again. + + + + + Tabbed interface + + + BotCommander has a tabbed interface, which means you can + have several connections in only one window - just like an IRC, or + IM client. + + + + + Channel and user list + + + If you have the correct permissions, you can have a list of + the bot's users and channels; also you will be able to manage + these: change user and channel flags and more. However, this + feature requires a small TCL script to be loaded in the bot (that + script is provided with BotCommander). + + + + + + + Some technical background + + BotCommander uses GConf2 to store its configuration, and all + bot-related data. The graphical part (the widgets) are from GTK+ + (currently using 2.6 features), and some are from libgnomeui. + + + + + Installation + + + About this part + + In this chapter you will learn about the installation methods of + BotCommander. You will be able to install BotCommander under several + Linux distributions, such as Debian and Gentoo, and also will know how + to install it from the sources. + + + + Install on Debian machines + + For a few years, I was a hardcore Debian-user. Thus, it was almost + my first task to create a Debian package out of BotCommander. + + I also created a Debian repository, so it is an easy task to + install BotCommander under a Debian system. Just add the following lines + to your sources list file. + + + The <filename>sources.list</filename> snippet required to + install BotCommander .deb packages with apt. + + deb http://www.botcommander.hu/debian testing main + + deb-src http://www.botcommander.hu/debian testing main + + + This snippet is only for debian etch (as of writing, at the end of + 2006). + + + + Install on Gentoo machines + + After my Debian years, my next Linux-breed was Gentoo. It's + absolutely does what the user wants (sure, if the user is smart enough). + After a few days of coding, a Gentoo ebuild was born. It is the part of + the BotCommander package, can be downloaded from + http://www.botcommander.hu/, and I'm also trying to add it to + the official Gentoo portage. + + + + Install from sources + + If you are not the user of the above systems, then currently no + package exists for your needs. I'm really sorry for that, but I always + welcome if someone sends me a package for any OS-es. + + So, you arrived here, you want to install BotCommander from + sources. This is good, but has some prerequisites: you will need bunch + of software you may not currently have installed. I'm trying to make + this list as correct as possible, but it may happen that I forgot about + something. I'm really sorry if so. + + + + autoconf v2.60 + + + This is required only if you want to compile the SVN tree, + as it doesn't contain a configure script. + + + + + gcc + + + gcc is the GNU C Compiler. This is a necessary tool. + + + + + gdk-pixbuf + + + This is the GDK-pixbuf library, required by BotCommander to + render some icons. + + + + + glib + + + This is the GLib library. BotCommander uses its + memory-handling routines. + + + + + GTK+ v2.6.2 or greater + + + This is the GTK library. BotCommander uses its widgets + heavily. + + + + + libgnome2 + + + This is the Gnome library. BotCommander uses some widgets in + it. + + + + + libgnomeui2 + + + This is the Gnome-UI library. BotCommander uses the file + open dialog from it. + + + + + VTE + + + This is the VTE (Virtual Terminal Emulation) library. + BotCommander displays all the bot-messages in such a + widget. + + + + + GNU Gettext package + + + This package is required for BotCommander to speak many + languages. I'm trying to make this one optional, so one will be + able to compile BotCommander without multilingual support (may be + good for english-speaking people, and for minimalist + systems) + + + + + + + + Basic eggdrop usage + + + Terms and assumptions + + Throughout this part we assume that you install your bot yourself, + and thus you have an owner flag in it. Many functions are not + accessible, if you don't possess that +n flag. + + + + Compiling and installing eggdrop + + + This chapter assumes that you have TCL installed system-wide. If + not, please consult the eggdrop manual on how to install it for one + single user, and how to make eggdrop use that library. I also assume + that you know how to use the basic Unix/Linux commands, such as tar, + thus you can unpack the eggdrop archive. + + + First things first, you much fetch eggdrop from somewhere. The + best place for this is eggheads' homepage at + http://www.eggheads.org/. Download the latest version (as of + writing, it is 1.6.18), and unpack it. Then enter the unpacked + distibution's directory, and issue the following commands: + + + Commands to configure and compile eggdrop + + ./configure + + make iconfig + + make + + + After issuing make iconfig, that script will + ask you several questions if you want to install this-or-that module. + Read the module descriptions, and choose whichever you need. + + + I'm currently planning to write my + botcommander.tcl script as an eggdrop module. If + I'm ready with that, I will instruct you how to compile new modules + for eggdrop. + + + After make finishes without errors, you can + issue the last, make install command. This will + install eggdrop to the given directory (if none was given, the default + is $HOME/eggdrop. + + + + Configuring your bot + + Configuring eggdrop is a long, yet not hard process, which + requires almost no understanding of eggdrop, if you know english. + + + The following is only a suggestion; contains my way on + configuring an eggdrop bot.You may do it several other ways; it's up + to you. However, if you read through this chapter, and follow my + words, I will assume that the name you have chosen your bot is + BCbot. + + + First of all, enter the directory which contains your eggdrop + installation. As said in the previous chapter, by default it is + $HOME/eggdrop. After that, make a copy of + eggdrop.conf with a filename as you will call your bot; then make it + executable for at least yourself. + + + Copy eggdrop.conf to your own file, and make it + executable. + + cp eggdrop.conf BCbot + + chmow 755 BCbot + + + Now begin to edit your newly created configuration. The most + important thing (of course, if you follow my way) it the very first row, + which now looks like this: + + #! /path/to/executable/eggdrop + + This tells the Unix/Linux shell to use + /path/to/executable/eggdrop to interpret this file. + Thus, the shell, instead of trying on interpreting the command in that + file, will run the given command with this file as a parameter. Unless + your eggdrop is at that location, you must change that line to something + like this: + + #! /home/yourusername/eggdrop/eggdrop + + + + + Usage + + + Command line parameters + + BotCommander doesn't have any defined command line parameters. + This means that it accepts only the standard Gnome and GTK+ parameters + only. I don't even have any plans on defining such things (yet). + + + + Built-in commands + + BotCommander has several built-in commands. These can be called + from BotCommander or external scripts, thus extending BotCommander's + functionality. + + Most of these commands can be abbreviated. This means that you can + cut off the end of the commands, until it is obvious to the application. + For example, as of the time of writing, the CONNECT command can be + abbreviated as CON. + + There are some "dangerous" commands, such as QUIT, which cannot be + abbreviated, so - in this case - you won't exit BotCommander if you + accidently type in the Q command. + +
+ QUIT + + The QUIT command does what it should according to its name: + exits BotCommander. + + If at least one connected tab is open, a small dialog will pop + up, asking if you are serious about quitting. + + This command cannot be abbreviated. +
+ +
+ CLOSE + + This command closes the currently active tab. If there is an + active connection in that tab, a dialog will pop up asking if you + really want to do that. + + This command cannot be abbreviated. +
+ +
+ CONNECT + + This will open a connection in the current tab. It has many + different invokations, depending on the parameters given. + + + + CONNECT without parameters will work if you previously + assigned a bot to the active tab with the ASSIGN command. If so, + the connection will be open to the given bot. + + + + CONNECT botname will connect to the named bot in the bot + list. + + + + CONNECT host port will connect to the specified host, on the + specified port. This can be useful, if you want to connect to a + bot only once, e.g to check some settings or such. + + + + CONNECT host port username does exactly as the above + command, but it will automatically send the given username also. + This will be useful as the initial connection to a bot, as I'm + planning to implement a SAVEBOT command, which will do just what + it name suggests: save the current bot to the bot list. + + +
+ +
+ ASSIGN + + The ASSIGN command does the same as CONNECT, with only one + difference: it won't connect. It will assign all the connection + parameters to the current tab, so when you are ready, you can use the + CONNECT command without any parameters to do the actual + connection. +
+ +
+ MODE + + The MODE command changes the current tab's mode. You can read + more about modes in +
+
+ + + Modes + + BotCommander uses modes to distinguish between commands addressed + to itself, and addressed to the connected bot. + + There are three modes, identified by their english names' first + character. + + + + B, or BotCommander command mode (/) + + + In this mode, entered text is validated against the commands + built in to BotCommander, or commands provided by scripts and + modules. + + + + + E, or Eggdrop command mode (.) + + + In this mode, text is sent to the connected bot (if any), so + eggdrop itself will validate it. + + + + + M, or Message mode (@) + + + In this mode, entered text is sent to the connected bot. As + you see, it is just the same as E mode, but there is a small + difference. If the entered text begins with a dot (.), eggdrop + would identify and parse it as a command. So in this case, the + entered text is prefixed with a space. + + + + + You can change between these modes in the Mode menu, or with + hotkeys (Ctrl-B, Ctrl-E and Ctrl-M respectively). However, if you want + to use one specific mode for a long time, and issue one line in a + different mode, you can prefix your text with the character in + parentheses in the above list. E.g if you use Message mode for hours, + and want to issue one BotCommander command, you can do it by entering + /COMMAND. As this happens, BotCommander will parse and execute the given + row as a BotCommander command, and return to message mode. + +
+
\ No newline at end of file diff --git a/doc/version.texinfo b/doc/version.texinfo new file mode 100644 index 0000000..dd64404 --- /dev/null +++ b/doc/version.texinfo @@ -0,0 +1,2 @@ +@set VERSION 1.0 +@set UPDATED 15 November 2005 diff --git a/eggdrop/botcommander.tcl b/eggdrop/botcommander.tcl new file mode 100644 index 0000000..5f5e5d5 --- /dev/null +++ b/eggdrop/botcommander.tcl @@ -0,0 +1,50 @@ +bind chon - * botcommander:chon +bind dcc - botcomm_chanlist botcommander:chanlist +bind dcc - botcomm_userlist botcommander:userlist +bind dcc - botcomm_chanprop botcommander:chanprop + +proc botcommander:chon {handle connid} { + putdcc $connid "BC+ ABILITY\r\n" +} + +proc botcommander:chanlist {handle connid params} { + if {[matchattr $handle o]} { + putdcc $connid "BC+ CHANLIST_START\r\n" + foreach chan [channels] { + set active [channel get $chan inactive] + if {$active != 0} { set active 0 } else { set active 1 } + putdcc $connid "BC+ CHAN $active $chan\r\n" + } + putdcc $connid "BC+ CHANLIST_END\r\n" + } else { + putcc $connid "BC- NOPRIV\r\n" + } +} + +proc botcommander:userlist {handle connid params} { + if {[matchattr $handle o]} { + putdcc $connid "BC+ USERLIST_START\r\n" + foreach user [userlist] { + putdcc $connid "BC+ USER $user\r\n" + } + putdcc $connid "BC+ USERLIST_END\r\n" + } else { + putdcc $connid "BC- NOPRIV\r\n" + } +} + +proc botcommander:chanprop {handle connid params} { + if {[matchattr $handle o]} { + set chan [lindex $params 0] + putdcc $connid "BC+ CHANPROPS_START $chan\r\n" + foreach prop [channel info $chan] { + putdcc $connid "BC+ CHANPROP $chan $prop\r\n" + } + putdcc $connid "BC+ CHANPROPS_END $chan\r\n" + } else { + putdcc $connid "BC- NOPRIV" + } +} + +putlog "BC+ ABILITY" + diff --git a/gentoo/net-misc/botcommander/ChangeLog b/gentoo/net-misc/botcommander/ChangeLog new file mode 100644 index 0000000..6f63b8f --- /dev/null +++ b/gentoo/net-misc/botcommander/ChangeLog @@ -0,0 +1,9 @@ +# ChangeLog for net-misc/botcommander +# Copyright 1999-2007 Gentoo Foundation; Distributed under the GPL v2 +# $Header: $ + +*botcommander-1.0 (07 May 2007) + + 07 May 2007; Gergely POLONKAI ChangeLog, + metadata.xml, botcommander-1.0.ebuild : + Initial import. Ebuild submitted by Gergely POLONKAI . diff --git a/gentoo/net-misc/botcommander/Manifest b/gentoo/net-misc/botcommander/Manifest new file mode 100644 index 0000000..c2ffc9f --- /dev/null +++ b/gentoo/net-misc/botcommander/Manifest @@ -0,0 +1,16 @@ +DIST botcommander-1.0.tar.gz 199432 RMD160 2b215e140f4be8d606e50851f62a768415dc20bd SHA1 4791e1ef953447769e185dd09378959111a472bb SHA256 60c9b2304ffd52710896a3fc23cbe7d2a1a311e930588e1c0ff0770832d7d34c +EBUILD botcommander-1.0.ebuild 824 RMD160 ba7a4d6d66187ff84a5b0f34099b0cae33c1d67d SHA1 5c236fa215ad00120ecc0d688e039e60a10537b2 SHA256 07b5b914e2a59f5a45b48fafa52ff391703a478a91a7a7722570af59b310145b +MD5 02966d62ff21c59a56c6e49205d7ea73 botcommander-1.0.ebuild 824 +RMD160 ba7a4d6d66187ff84a5b0f34099b0cae33c1d67d botcommander-1.0.ebuild 824 +SHA256 07b5b914e2a59f5a45b48fafa52ff391703a478a91a7a7722570af59b310145b botcommander-1.0.ebuild 824 +MISC ChangeLog 347 RMD160 f388beb33308560a58336982968c1a42a10010e8 SHA1 f93cc861296127765a24db8027842f31ac7d7e58 SHA256 6bbc25b9c2de498ab7912fc269d55b4c56273f413215f8f89a4731ad6999c0ef +MD5 8da252e524f30f329737a630a99822a5 ChangeLog 347 +RMD160 f388beb33308560a58336982968c1a42a10010e8 ChangeLog 347 +SHA256 6bbc25b9c2de498ab7912fc269d55b4c56273f413215f8f89a4731ad6999c0ef ChangeLog 347 +MISC metadata.xml 228 RMD160 63206419b7b7c6a2c350d341159550195e4a6c39 SHA1 5459d1b0d5252954b1e03749daf24fae8328241c SHA256 77715d077c12ef5f4fb0210a6ab0afbd1ce72893197b00172e113bc1feefd7b8 +MD5 12db369dccd15f41022110f874eec256 metadata.xml 228 +RMD160 63206419b7b7c6a2c350d341159550195e4a6c39 metadata.xml 228 +SHA256 77715d077c12ef5f4fb0210a6ab0afbd1ce72893197b00172e113bc1feefd7b8 metadata.xml 228 +MD5 3b1381c413a444be4c2ccf88873fb996 files/digest-botcommander-1.0 250 +RMD160 06d1d7d46814dd557e6d8e280747fc1efa37315b files/digest-botcommander-1.0 250 +SHA256 69bea651c8d76ef75dad3c4ad15772813f75e1673b7c8d54bc448ac60f89de3c files/digest-botcommander-1.0 250 diff --git a/gentoo/net-misc/botcommander/botcommander-1.0.ebuild b/gentoo/net-misc/botcommander/botcommander-1.0.ebuild new file mode 100644 index 0000000..5de5506 --- /dev/null +++ b/gentoo/net-misc/botcommander/botcommander-1.0.ebuild @@ -0,0 +1,34 @@ +# Copyright 1999-2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +inherit eutils versionator gnome2 + +DESCRIPTION="Eggdrop IRC bot maintanence program" +HOMEPAGE="http://www.botcommander.hu/" +SRC_URI="http://www.botcommander.hu/dl/${P}.tar.gz" +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="x86 amd64" +IUSE="-debug" +DEPEND="" +RDEPEND=">=dev-libs/glib-2.6.0 + >=x11-libs/gtk+-2.10.0" + +src_compile() { + econf \ + --prefix="${D}"/usr \ + --mandir="${D}"/usr/share/man \ + --infodir="${D}"/usr/share/info \ + --libdir="${D}"/usr/$(get_libdir) || die "econf failed" + emake || die "emake failed" +} + +src_install() { + emake \ + prefix="${D}"/usr \ + mandir="${D}"/usr/share/man \ + infodir="${D}"/usr/share/info \ + libdir="${D}"/usr/$(get_libdir) \ + install || die "emake install failed" +} diff --git a/gentoo/net-misc/botcommander/files/digest-botcommander-1.0 b/gentoo/net-misc/botcommander/files/digest-botcommander-1.0 new file mode 100644 index 0000000..6ea2dbc --- /dev/null +++ b/gentoo/net-misc/botcommander/files/digest-botcommander-1.0 @@ -0,0 +1,3 @@ +MD5 1d44a59bc7466b2f36dbc812bb793793 botcommander-1.0.tar.gz 199432 +RMD160 2b215e140f4be8d606e50851f62a768415dc20bd botcommander-1.0.tar.gz 199432 +SHA256 60c9b2304ffd52710896a3fc23cbe7d2a1a311e930588e1c0ff0770832d7d34c botcommander-1.0.tar.gz 199432 diff --git a/gentoo/net-misc/botcommander/metadata.xml b/gentoo/net-misc/botcommander/metadata.xml new file mode 100644 index 0000000..14ca7d6 --- /dev/null +++ b/gentoo/net-misc/botcommander/metadata.xml @@ -0,0 +1,8 @@ + + + +net-misc + + polesz@botcommander.hu + + diff --git a/include/defines.h b/include/defines.h new file mode 100644 index 0000000..e35aef2 --- /dev/null +++ b/include/defines.h @@ -0,0 +1,76 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * defines.h + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Macro definitions used in many places + }}} */ + +/* {{{ _BC_DEFINES_H */ +#ifndef _BC_DEFINES_H +# define _BC_DEFINES_H + +/* {{{ Locale-related definition. It's much easier this way */ +#define _(String) gettext(String) +/* }}} */ + +/* {{{ BC_COMMAND prototype definition */ +#define BC_COMMAND(x) gboolean x (t_tab_data *tab, int paramnum, gchar **param) +/* In typedefs.h there is a struct which is for the command list. + * To make life easier, you only have to change the functions' type here (and + * in the previous line). + */ +#define BC_COMMAND_DEF(x) gboolean (* x )(t_tab_data *, int, gchar **) +/* }}} */ + +/* {{{ Command types */ +#define CT_INTERNAL 0 +#define CT_MODULE 1 +#define CT_SCRIPT 2 +/* }}} */ + +/* {{{ BotCommander error constants */ +#define BCE_SUCCESS 0 +#define BCE_BOT_EXISTS 1 +#define BCE_NOMEM 2 +#define BCE_NOBOT 3 +#define BCE_NOPROTO 4 +#define BCE_CANTRESOLV 5 +#define BCE_CANTCONNECT 6 +/* }}} */ + +/* {{{ The eggdrops character for eggdrop commands. You should never change this! */ +#define EGG_CMD_CHAR "." +/* }}} */ + +/* {{{ The telnet codes we use, from RFC 854) */ +#define TELNET_IAC "\xff" /* Interpret As Command */ +#define TELNET_WILL "\xfb" /* Will */ +#define TELNET_WONT "\xfc" /* Won't */ +#define TELNET_ECHO "\x01" /* Echo */ + +#define TELNET_WILL_ECHO TELNET_IAC TELNET_WILL TELNET_ECHO +#define TELNET_WONT_ECHO TELNET_IAC TELNET_WONT TELNET_ECHO +/* }}} */ + +#endif +/* }}} */ + diff --git a/include/functions.h b/include/functions.h new file mode 100644 index 0000000..cdc51ce --- /dev/null +++ b/include/functions.h @@ -0,0 +1,161 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * functions.h + * + * Wed Nov 09 22:16:59 2005 + * Copyright 2004 Gergely POLONKAI + * polesz@techinfo.hu + * + * Function prototypes + }}} */ + +/* {{{ _BC_FUNCTIONS_H */ +#ifndef _BC_FUNCTIONS_H +# define _BC_FUNCTIONS_H + +/* {{{ Includes */ +# include +# include +# include "typedefs.h" +/* }}} */ + +/* {{{ widgets.c */ +void set_title(t_tab_data *, char *, ...); +int create_main_window(void); +void feed_message_to_terminal(t_tab_data *, gboolean, gchar *, ...); +void feed_error_to_terminal(t_tab_data *, gboolean, gchar *, ...); +void feed_info_to_terminal(t_tab_data *, gboolean, gchar *, ...); +/* }}} */ + +/* {{{ callbacks.c */ +void destroy_event(GtkWidget *, gpointer); +gboolean delete_event(GtkWidget *, GdkEvent *, gpointer); +void toolbar_quit(GtkButton *, gpointer); +void toolbar_add_tab(GtkButton *, gpointer); +void toolbar_close_active(GtkButton *, gpointer); +void toolbar_open_prefs(GtkButton *, gpointer); +void book_change_tab(GtkNotebook *, GtkNotebookPage *newpage, guint, gpointer); +void close_tab_cb(GtkWidget *, gpointer); +gboolean entry_activate(GtkWidget *, gpointer); +void menu_exit(GtkWidget *, gpointer); +void menu_mode_changed(GtkWidget *, gpointer); +void menu_botlist_open(GtkWidget *, gpointer); +void menu_prefs_open(GtkWidget *, gpointer); +void menu_new_tab(GtkWidget *, gpointer); +void menu_close_tab(GtkWidget *, gpointer); +void menu_about(GtkWidget *, gpointer); +int vte_clicked(GtkWidget *, gpointer); +int entry_keypress(GtkEntry *, GdkEventKey *, gpointer); +void socket_event(gpointer, gint, GdkInputCondition); +void menu_showhide_sidebar(GtkWidget *, gpointer); +/* }}} */ + +/* {{{ main.c */ +void exit_cleanly(gboolean); +void change_mode(char, gboolean); +/* }}} */ + +/* {{{ tabs.c */ +int add_tab(t_tab_data **); +t_tab_data *get_active_tab(void); +gboolean close_tab(t_tab_data *); +gboolean assign_bot_to_tab_by_name(t_tab_data *, gchar *); +void assign_bot_to_tab(t_tab_data *, t_bot_data *); +gint connect_tab(t_tab_data *); +void update_channel_list(t_tab_data *); +void update_user_list(t_tab_data *); +gint find_tab_by_pagenum(gconstpointer, gconstpointer); +void disconnect_tab(t_tab_data *); +void change_active_tab(gint); +/* }}} */ + +/* {{{ string.c */ +gboolean streq(gchar *, gchar *, gboolean); +int wordwrap(gchar *, gchar *, gchar ***, gint *); +void wl_free(gchar ***, gint); +gboolean is_numeric(gchar *, gint *); +gchar *trim(gchar *); +/* }}} */ + +/* {{{ bots.c */ +#ifdef DEBUG +void list_bots(void); +#endif +gint add_bot(gchar *, gchar *, guint, gchar *); +t_bot_data *get_bot_by_botname(gchar *); +gint create_bot_record(gchar *, gint, t_bot_data **); +gint update_bot(t_bot_data *, gchar *, gchar *, guint, gchar *); +void save_bot(t_bot_data *, t_bot_data *); +void free_bot_data(gpointer, gpointer); +t_bot_data *get_bot_by_conf_num(guint); +/* }}} */ + +/* {{{ commands.c */ +gboolean process_commandline(gchar *, t_tab_data *); +void process_botcommander_script_commands(t_tab_data *, char *); +/* }}} */ + +/* {{{ config.c */ +gboolean init_config(void); +void read_config_data(void); +gboolean set_int_conf_value(gchar *, gint); +gboolean set_string_conf_value(gchar *, gchar *); +void read_bot_list_from_config(void); +void save_bot_list_to_config(void); +/* }}} */ + +/* {{{ about.c */ +void display_about_box(void); +/* }}} */ + +/* {{{ setup.c */ +void display_setup_window(void); +/* }}} */ + +/* {{{ networking.c */ +gint connect_to_host(gchar *, guint, int *, gint *, t_tab_data *); +void process_incoming_data(t_tab_data *, char *); +/* }}} */ + +/* {{{ history.c */ +void history_add(t_tab_data *, gchar, gchar *); +gint get_history_len(t_tab_data *); +/* }}} */ + +/* {{{ botlist.c */ +void display_botlist_window(void); +void create_bot_editor(t_bot_data *); +/* }}} */ + +/* {{{ chanprops.c */ +void update_channel_property(t_tab_data *, gchar *, gchar *); +/* }}} */ + +/* {{{ debug.c */ +/* This one is only compiled if DEBUG is defined */ +# ifdef DEBUG +void debug_init(void); +void set_context(char *file, int line); +# define Context set_context(__FILE__, __LINE__) +# else /* DEBUG */ +# define Context +# endif /* DEBUG */ +/* }}} */ + +#endif /* _BC_FUNCTIONS_H */ +/* }}} */ diff --git a/include/typedefs.h b/include/typedefs.h new file mode 100644 index 0000000..b9a3b16 --- /dev/null +++ b/include/typedefs.h @@ -0,0 +1,187 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * typedefs.h + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Type definitions + }}} */ + +/* {{{ _BC_TYPEDEFS_H */ +#ifndef _BC_TYPEDEFS_H +# define _BC_TYPEDEFS_H + +/* {{{ Includes */ +# include + +# include "defines.h" +/* }}} */ + +/* {{{ Bot data */ +typedef struct _t_bot_data { + /* The bot's name. NULL if now known */ + gchar *botname; + /* The hostname of the bot */ + gchar *host; + /* The port number of the bot */ + guint port; + /* The handle in the bot (may be NULL) */ + gchar *handle; + /* The config key value for this bot (used only when loading bot data from config */ + guint id; +} t_bot_data; +/* }}} */ + +/* {{{ History data */ +typedef struct _t_history_data { + gchar *line; + struct _t_history_data *next; +} t_history_data; +/* }}} */ + +/* {{{ Tab data */ +typedef struct _t_tab_data { + /* General data */ + + /* The number of the tab */ + gint num; + /* The current mode in the tab (b|e|m)*/ + char mode; + /* The bot assigned to this tab */ + t_bot_data *bot; + /* The history data */ + t_history_data *history; + /* The current position in the history list */ + gint history_position; + + /* BC script related data */ + + /* Currently we are in the middle of the channel list */ + gboolean chanlist_process; + /* Currently we are in the middle of the user list */ + gboolean userlist_process; + /* Currently we are processing the properties of this channel */ + gchar *chanprops_process; + /* This is number x in the property list */ + gint chanprops_list_num; + /* The channel list */ + GList *actual_channel_list; + /* The user list */ + GList *actual_user_list; + + /* Networking data */ + + /* TRUE if the tab is connected, FALSE otherwise */ + gboolean connected; + /* The socket descriptor */ + int sock; + /* The GDK socket tag */ + gint socktag; + /* Set to TRUE when the first byte arrives from the other side */ + gboolean data_arrived; + + /* Widgets */ + + /* The virtual terminal */ + GtkWidget *vt; + /* Command line */ + GtkWidget *editbox; + /* The hbox containing the tab label and the close button */ + GtkWidget *labelbox; + /* The tab label */ + GtkWidget *label; + /* The close button */ + GtkWidget *closebutton; + /* List of channels */ + GtkWidget *channel_list; + /* List of users (handles) */ + GtkWidget *user_list; + /* Channel store */ + GtkListStore *channel_store; + /* User store */ + GtkListStore *user_store; +} t_tab_data; +/* }}} */ + +/* {{{ Configuration data */ +typedef struct _t_config_data { + /* GUI options */ + gboolean change_to_new_tab; + /* VTE options */ + gboolean scroll_on_output; + gboolean transparent_background; + gfloat background_saturation; + gchar *vte_font; + /* General options */ + gboolean change_to_message; +#ifdef DEBUG + gboolean debug; +#endif /* DEBUG */ + gchar default_mode; + gboolean save_prefs; + gint history_len; +} t_config_data; +/* }}} */ + +/* {{{ Command Data */ +typedef struct _t_command { + /* The command verb */ + gchar *command_verb; + /* Type of the command: 0 - Internal; 1 - From a module; 2 - From a script */ + guint type; + /* How many parameters do we require? */ + gint min_paramnum; + /* Can this command be abbreviated? */ + gboolean can_abbrev; + /* The commands function */ + BC_COMMAND_DEF(func); +} t_command; +/* }}} */ + +/* {{{ Channel data */ +typedef struct _t_channel { + /* The channel name */ + char *name; + /* TRUE if then channel is active */ + gboolean active; + /* The property list */ + GList *properties; +} t_channel; +/* }}} */ + +/* {{{ User data */ +typedef struct _t_user { + /* The use name */ + char *name; +} t_user; +/* }}} */ + +/* {{{ Channel properties */ +typedef struct _t_chan_prop { + char *name; + gboolean bool_prop; + gboolean bool_value; + gchar *string_value; +} t_chan_prop; +/* }}} */ + +#endif +/* }}} */ + diff --git a/include/variables.h b/include/variables.h new file mode 100644 index 0000000..e5d157b --- /dev/null +++ b/include/variables.h @@ -0,0 +1,63 @@ +/* vim: set foldmethod=marker : */ +/* {{{ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ + * variables.h + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Variable definitions + }}} */ + +/* {{{ _BC_VARIABLES_H */ +#ifndef _BC_VARIABLES_H +# define _BC_VARIABLES_H + +/* {{{ Includes */ +# include +# include + +#include "typedefs.h" +/* }}} */ + +/* {{{ widgets.c */ +extern GtkWidget *main_window; +extern GtkWidget *main_book; +extern GtkWidget *main_statuslabel_mode; +extern GtkWidget *main_menu_mode_b; +extern GtkWidget *main_menu_mode_e; +extern GtkWidget *main_menu_mode_m; +extern GtkWidget *main_menu_show_sidebar; +/* }}} */ + +/* {{{ tabs.c */ +extern GList *tab_list; +/* }}} */ + +/* {{{ bots.c */ +extern GList *internal_bot_list; +/* }}} */ + +/* {{{ config.c */ +extern t_config_data config_data; +extern GConfClient *gconf_client; +/* }}} */ + +#endif +/* }}} */ + diff --git a/pixmaps/Makefile.in b/pixmaps/Makefile.in new file mode 100644 index 0000000..6453107 --- /dev/null +++ b/pixmaps/Makefile.in @@ -0,0 +1,16 @@ +include ../rules + +top_srcdir = @top_srcdir@ + +PACKAGE_PIXMAPS_DIR = @datarootdir@/pixmaps/@PACKAGE_TARNAME@ + +all: +clean: + +install: + $(top_srcdir)/mkinstalldirs $(PACKAGE_PIXMAPS_DIR) + $(INSTALL) -m 0644 $(PIXMAPS_OBJECTS) $(PACKAGE_PIXMAPS_DIR) + +distclean: + /bin/rm -f Makefile + diff --git a/pixmaps/bc48.png b/pixmaps/bc48.png new file mode 100644 index 0000000..199c4d2 Binary files /dev/null and b/pixmaps/bc48.png differ diff --git a/pixmaps/bc48_trans.png b/pixmaps/bc48_trans.png new file mode 100644 index 0000000..36dd87c Binary files /dev/null and b/pixmaps/bc48_trans.png differ diff --git a/po/BotCommander.pot b/po/BotCommander.pot new file mode 100644 index 0000000..5756ec6 --- /dev/null +++ b/po/BotCommander.pot @@ -0,0 +1,307 @@ +# BotCommander gettext messages. +# Original file created by Gergely POLONKAI for BotCommander v1.0 + +#: src/widgets.c:223 +msgid "_About" +msgstr "" + +#: src/tabs.c:103 +msgid "Activate" +msgstr "" + +#: src/botlist.c:180 +msgid "Add bot" +msgstr "" + +#: src/widgets.c:114 +msgid "_BotCommander command mode" +msgstr "" + +#: src/botlist.c:351 +msgid "Bot list" +msgstr "" + +#: src/widgets.c:147 +msgid "_Bot list" +msgstr "" + +#: src/botlist.c:384 +#: src/botlist.c:482 +msgid "Bot name" +msgstr "" + +#: src/widgets.c:106 +msgid "_Bot" +msgstr "" + +#: src/tabs.c:510 +msgid "Can not connect to bot" +msgstr "" + +#: src/tabs.c:504 +msgid "Can not get IP protocol" +msgstr "" + +#: src/tabs.c:507 +msgid "Can not resolv hostname %s" +msgstr "" + +#: src/setup.c:247 +msgid "Change to message mode after connect" +msgstr "" + +#: src/setup.c:253 +msgid "Change to newly created tab" +msgstr "" + +#: src/tabs.c:309 +msgid "Channels" +msgstr "" + +#: src/widgets.c:269 +msgid "Close active tab" +msgstr "" + +#: src/widgets.c:200 +msgid "_Close tab" +msgstr "" + +#: src/setup.c:265 +msgid "Command line history length" +msgstr "" + +#: src/callbacks.c:357 +msgid "Connected" +msgstr "" + +#: src/commands.c:131 +#: src/networking.c:53 +msgid "Connecting to %s:%d" +msgstr "" + +#: src/commands.c:93 +#: src/commands.c:108 +msgid "Connecting to %s" +msgstr "" + +#: src/tabs.c:593 +msgid "Connection closed" +msgstr "" + +#: src/botlist.c:357 +msgid "_Connect" +msgstr "" + +#: src/setup.c:240 +msgid "Debug mode" +msgstr "" + +#: src/botlist.c:88 +msgid "Edit bot" +msgstr "" + +#: src/widgets.c:123 +msgid "_Eggdrop command mode" +msgstr "" + +#: src/widgets.c:267 +msgid "Exit BotCommander" +msgstr "" + +#: src/widgets.c:91 +msgid "E_xit" +msgstr "" + +#: src/setup.c:306 +msgid "Font" +msgstr "" + +#: src/botlist.c:494 +msgid "Handle" +msgstr "" + +#: src/tabs.c:323 +msgid "Handles" +msgstr "" + +#: src/widgets.c:237 +msgid "_Help" +msgstr "" + +#: src/botlist.c:486 +msgid "Host" +msgstr "" + +#: src/about.c:52 +msgid "licence" +msgstr "" + +#: src/widgets.c:131 +msgid "_Message mode" +msgstr "" + +#: src/commands.c:170 +msgid "Mode char can be one of B, E or M!" +msgstr "" + +#: src/callbacks.c:93 +#: src/callbacks.c:94 +#: src/main.c:45 +#: src/main.c:46 +#: src/tabs.c:362 +#: src/tabs.c:363 +#: src/tabs.c:460 +#: src/tabs.c:461 +#: src/widgets.c:291 +#: src/widgets.c:292 +#: src/widgets.c:139 +#: src/widgets.c:185 +msgid "Mode: %c" +msgstr "" + +#: src/widgets.c:268 +msgid "New tab" +msgstr "" + +#: src/commands.c:102 +#: src/commands.c:143 +msgid "No bot exists by that name" +msgstr "" + +#: src/commands.c:86 +msgid "No bot is assigned to this tab. Use ASSIGN to do that." +msgstr "" + +#: src/tabs.c:335 +#: src/tabs.c:360 +msgid "Not connected" +msgstr "" + +#: src/commands.c:124 +#: src/commands.c:261 +msgid "Not enough memory!" +msgstr "" + +#: src/commands.c:154 +#: src/commands.c:275 +msgid "Not enough parameters!" +msgstr "" + +#: src/commands.c:159 +msgid "Only one parameter required!" +msgstr "" + +#: src/botlist.c:490 +msgid "Port" +msgstr "" + +#: src/widgets.c:162 +msgid "_Preferences" +msgstr "" + +#: src/widgets.c:270 +msgid "Preferences" +msgstr "" + +#: src/tabs.c:107 +#: src/tabs.c:124 +#: src/tabs.c:141 +msgid "Properties" +msgstr "" + +#: src/setup.c:295 +msgid "Saturation" +msgstr "" + +#: src/setup.c:259 +msgid "Save preferences on exit" +msgstr "" + +#: src/setup.c:285 +msgid "Scroll on output" +msgstr "" + +#: src/commands.c:119 +msgid "Second parameter must be a port number!" +msgstr "" + +#: src/setup.c:228 +msgid "Setup" +msgstr "" + +#: src/widgets.c:177 +msgid "_Setup" +msgstr "" + +#: src/tabs.c:583 +msgid "Tab is not connected" +msgstr "" + +#: src/widgets.c:215 +msgid "_Tab" +msgstr "" + +#: src/setup.c:280 +msgid "Terminal" +msgstr "" + +#: src/commands.c:164 +msgid "The parameter must be one character!" +msgstr "" + +#: src/main.c:84 +msgid "There are connected tabs. Are you sure, you want to exit?" +msgstr "" + +#: src/bots.c:75 +msgid "There is already a bot named %s in the list.\n" +msgstr "" + +#: src/config.c:109 +msgid "There was an error accessing GConf2: %s" +msgstr "" + +#: src/commands.c:271 +msgid "This command cannot be abbreviated!" +msgstr "" + +#: src/commands.c:81 +msgid "This tab is already connected. Exit the bot with .quit, or use /DISCONNECT!" +msgstr "" + +#: src/tabs.c:431 +msgid "This tab is connected. Are you sure you want to close it?" +msgstr "" + +#: src/about.c:51 +msgid "translator_credits" +msgstr "" + +#: src/setup.c:290 +msgid "Transparent background" +msgstr "" + +#: src/commands.c:281 +msgid "Unknown command \"%s\"" +msgstr "" + +#: src/tabs.c:516 +msgid "Unknown error!" +msgstr "" + +#: src/callbacks.c:141 +msgid "Won't send an eggdrop command to a not connected tab" +msgstr "" + +#: src/callbacks.c:162 +msgid "Won't send message to a not connected tab" +msgstr "" + +#: data/botcommander.desktop.in.in +msgid "BotCommander" +msgstr "" + +#: data/botcommander.desktop.in.in +msgstr "BotCommander eggdrop client" +msgid "" + diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 0000000..ab3aea6 --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,221 @@ +# Makefile for program source directory in GNU NLS utilities package. +# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. +# +# - Modified by Owen Taylor to use GETTEXT_PACKAGE +# instead of PACKAGE and to look for po2tbl in ./ not in intl/ +# +# - Modified by jacob berkman to install +# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize +# +# - Modified by Rodney Dawes for use with intltool +# +# We have the following line for use by intltoolize: +# INTLTOOL_MAKEFILE + +include ../rules + +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_builddir = .. +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ +libdir = @libdir@ +DATADIRNAME = @DATADIRNAME@ +itlocaledir = $(prefix)/$(DATADIRNAME)/locale +subdir = po +install_sh = @INSTALL@ +# Automake >= 1.8 provides @mkdir_p@. +# Until it can be supposed, use the safe fallback: +mkdir_p = $(install_sh) -d + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +GMSGFMT = @GMSGFMT@ +MSGFMT = @MSGFMT@ +XGETTEXT = @XGETTEXT@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +MSGMERGE = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist +GENPOT = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot + +ALL_LINGUAS = @ALL_LINGUAS@ + +PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; fi) + +POFILES=$(shell if test -n "$(PO_LINGUAS)"; then LINGUAS="$(PO_LINGUAS)"; else LINGUAS="$(ALL_LINGUAS)"; fi; for lang in $$LINGUAS; do printf "$$lang.po "; done) + +DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(POFILES) +EXTRA_DISTFILES = POTFILES.skip Makevars LINGUAS + +POTFILES = \ +#This Gets Replace for some reason + +CATALOGS=$(shell if test -n "$(PO_LINGUAS)"; then LINGUAS="$(PO_LINGUAS)"; else LINGUAS="$(ALL_LINGUAS)"; fi; for lang in $$LINGUAS; do printf "$$lang.gmo "; done) + +.SUFFIXES: +.SUFFIXES: .po .pox .gmo .mo .msg .cat + +.po.pox: + $(MAKE) $(GETTEXT_PACKAGE).pot + $(MSGMERGE) $< $(GETTEXT_PACKAGE).pot -o $*.pox + +.po.mo: + $(MSGFMT) -o $@ $< + +.po.gmo: + file=`echo $* | sed 's,.*/,,'`.gmo \ + && rm -f $$file && $(GMSGFMT) -o $$file $< + +.po.cat: + sed -f ../intl/po2msg.sed < $< > $*.msg \ + && rm -f $@ && gencat $@ $*.msg + + +all: all-@USE_NLS@ + +all-yes: $(CATALOGS) +all-no: + +$(GETTEXT_PACKAGE).pot: $(POTFILES) + $(GENPOT) + +install: install-data +install-data: install-data-@USE_NLS@ +install-data-no: all +install-data-yes: all + $(mkdir_p) $(DESTDIR)$(itlocaledir) + if test -n "$(PO_LINGUAS)"; then \ + linguas="$(PO_LINGUAS)"; \ + else \ + linguas="$(ALL_LINGUAS)"; \ + fi; \ + for lang in $$linguas; do \ + dir=$(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $$dir; \ + if test -r $$lang.gmo; then \ + $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ + echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \ + else \ + $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ + echo "installing $(srcdir)/$$lang.gmo as" \ + "$$dir/$(GETTEXT_PACKAGE).mo"; \ + fi; \ + if test -r $$lang.gmo.m; then \ + $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \ + echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \ + else \ + if test -r $(srcdir)/$$lang.gmo.m ; then \ + $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \ + $$dir/$(GETTEXT_PACKAGE).mo.m; \ + echo "installing $(srcdir)/$$lang.gmo.m as" \ + "$$dir/$(GETTEXT_PACKAGE).mo.m"; \ + else \ + true; \ + fi; \ + fi; \ + done + +# Empty stubs to satisfy archaic automake needs +dvi info tags TAGS ID: + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: + if test -n "$(PO_LINGUAS)"; then \ + linguas="$(PO_LINGUAS)"; \ + else \ + linguas="$(ALL_LINGUAS)"; \ + fi; \ + for lang in $$linguas; do \ + rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \ + rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \ + done + +check: all $(GETTEXT_PACKAGE).pot + +mostlyclean: + rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp + rm -f .intltool-merge-cache + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES stamp-it + rm -f *.mo *.msg *.cat *.cat.m *.gmo + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f Makefile.in.in + +distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: $(DISTFILES) + dists="$(DISTFILES)"; \ + extra_dists="$(EXTRA_DISTFILES)"; \ + for file in $$extra_dists; do \ + test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \ + done; \ + for file in $$dists; do \ + test -f $$file || file="$(srcdir)/$$file"; \ + ln $$file $(distdir) 2> /dev/null \ + || cp -p $$file $(distdir); \ + done + +update-po: Makefile + $(MAKE) $(GETTEXT_PACKAGE).pot + tmpdir=`pwd`; \ + if test -n "$(PO_LINGUAS)"; then \ + linguas="$(PO_LINGUAS)"; \ + else \ + linguas="$(ALL_LINGUAS)"; \ + fi; \ + for lang in $$linguas; do \ + echo "$$lang:"; \ + result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \ + if $$result; then \ + if cmp $(srcdir)/$$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.gmo failed!"; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi; \ + done + +Makefile POTFILES: stamp-it + @if test ! -f $@; then \ + rm -f stamp-it; \ + $(MAKE) stamp-it; \ + fi + +stamp-it: Makefile.in.in ../config.status POTFILES.in + cd .. \ + && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \ + $(SHELL) ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..c0d8637 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,13 @@ +# List of source files containing translatable strings. +# Please keep this list in alphabetical order. +../src/about.c +../src/botlist.c +../src/bots.c +../src/callbacks.c +../src/commands.c +../src/config.c +../src/main.c +../src/networking.c +../src/setup.c +../src/tabs.c +../src/widgets.c diff --git a/po/hu.po b/po/hu.po new file mode 100644 index 0000000..d01f3bf --- /dev/null +++ b/po/hu.po @@ -0,0 +1,324 @@ +# Magyar translation of BotCommander. +# Copyright (C) 2006 Free Software Foundation, Inc. +# Gergely POLONKAI , 2006. +# +# +msgid "" +msgstr "" +"Project-Id-Version: BotCommander 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2006-09-08 11:43+0200\n" +"PO-Revision-Date: 2006-09-08 12:02+0200\n" +"Last-Translator: Gergely POLONKAI \n" +"Language-Team: Hungarian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: " + +# BotCommander gettext messages. +# Original file created by Gergely POLONKAI for BotCommander v1.0 +#: src/widgets.c:223 +msgid "_About" +msgstr "_Névjegy" + +#: src/tabs.c:103 +msgid "Activate" +msgstr "Aktiválás" + +#: src/botlist.c:180 +msgid "Add bot" +msgstr "Új bot" + +#: src/widgets.c:114 +msgid "_BotCommander command mode" +msgstr "_BotCommander parancs mód" + +#: src/botlist.c:351 +msgid "Bot list" +msgstr "Bot lista" + +#: src/widgets.c:147 +msgid "_Bot list" +msgstr "Bot _lista" + +#: src/botlist.c:384 +#: src/botlist.c:482 +msgid "Bot name" +msgstr "Bot neve" + +#: src/widgets.c:106 +msgid "_Bot" +msgstr "_Bot" + +#: src/tabs.c:510 +msgid "Can not connect to bot" +msgstr "Nem tudok csatlakozni a bothoz" + +#: src/tabs.c:504 +msgid "Can not get IP protocol" +msgstr "Nem találom az IP protokol adatait" + +#: src/tabs.c:507 +msgid "Can not resolv hostname %s" +msgstr "Nem lehet feloldani a nevet (%s)" + +#: src/setup.c:247 +msgid "Change to message mode after connect" +msgstr "Váltás üzenet-módba csatlakozás után" + +#: src/setup.c:253 +msgid "Change to newly created tab" +msgstr "Új fül nyitásakor váltás az új fülre" + +#: src/tabs.c:309 +msgid "Channels" +msgstr "Csatornák" + +#: src/widgets.c:269 +msgid "Close active tab" +msgstr "Aktív fül bezárása" + +#: src/widgets.c:200 +msgid "_Close tab" +msgstr "Fül be_zárása" + +#: src/setup.c:265 +msgid "Command line history length" +msgstr "Parancssor-megőrzés hossza" + +#: src/callbacks.c:357 +msgid "Connected" +msgstr "Csatlakozva" + +#: src/commands.c:131 +#: src/networking.c:53 +msgid "Connecting to %s:%d" +msgstr "Csatlakozás ide: %s:%d" + +#: src/commands.c:93 +#: src/commands.c:108 +msgid "Connecting to %s" +msgstr "Csatlakozás ehhez: %s" + +#: src/tabs.c:593 +msgid "Connection closed" +msgstr "Kapcsolat lezárva" + +#: src/botlist.c:357 +msgid "_Connect" +msgstr "_Csatlakozás" + +#: src/setup.c:240 +msgid "Debug mode" +msgstr "Debug mód" + +#: src/botlist.c:88 +msgid "Edit bot" +msgstr "Bot szerkesztése" + +#: src/widgets.c:123 +msgid "_Eggdrop command mode" +msgstr "_Eggdrop parancs mód" + +#: src/widgets.c:267 +msgid "Exit BotCommander" +msgstr "Kilépés a BotCommanderből" + +#: src/widgets.c:91 +msgid "E_xit" +msgstr "K_ilépés" + +#: src/setup.c:306 +msgid "Font" +msgstr "Betűtípus" + +#: src/botlist.c:494 +msgid "Handle" +msgstr "Felhasználónév" + +#: src/tabs.c:323 +msgid "Handles" +msgstr "Felhasználók" + +#: src/widgets.c:237 +msgid "_Help" +msgstr "_Súgó" + +#: src/botlist.c:486 +msgid "Host" +msgstr "Cím" + +#: src/about.c:52 +msgid "licence" +msgstr "A BotCommander a GNU General Public Licence alatt készült. Ennek egy másolata megtalálható a program forrás-fájljai között." + +#: src/widgets.c:131 +msgid "_Message mode" +msgstr "Üzenet _mód" + +#: src/commands.c:170 +msgid "Mode char can be one of B, E or M!" +msgstr "A mód karakter csak B, E vagy M lehet!" + +#: src/callbacks.c:93 +#: src/callbacks.c:94 +#: src/main.c:45 +#: src/main.c:46 +#: src/tabs.c:362 +#: src/tabs.c:363 +#: src/tabs.c:460 +#: src/tabs.c:461 +#: src/widgets.c:291 +#: src/widgets.c:292 +#: src/widgets.c:139 +#: src/widgets.c:185 +msgid "Mode: %c" +msgstr "Mód: %c" + +#: src/widgets.c:268 +msgid "New tab" +msgstr "Új fül" + +#: src/commands.c:102 +#: src/commands.c:143 +msgid "No bot exists by that name" +msgstr "Nem létezik ilyen nevű bot" + +#: src/commands.c:86 +msgid "No bot is assigned to this tab. Use ASSIGN to do that." +msgstr "Nincs bot rendelve ehhez a fülhöz. A hozzárendeléshez használd az ASSIGN parancsot." + +#: src/tabs.c:335 +#: src/tabs.c:360 +msgid "Not connected" +msgstr "Nincs csatlakoztatva" + +#: src/commands.c:124 +#: src/commands.c:261 +msgid "Not enough memory!" +msgstr "Nincs elég memória!" + +#: src/commands.c:154 +#: src/commands.c:275 +msgid "Not enough parameters!" +msgstr "Túl kevés paraméter!" + +#: src/commands.c:159 +msgid "Only one parameter required!" +msgstr "Csak egy paramétert kell megadni!" + +#: src/botlist.c:490 +msgid "Port" +msgstr "Port" + +#: src/widgets.c:162 +msgid "_Preferences" +msgstr "_Beállítás" + +#: src/widgets.c:270 +msgid "Preferences" +msgstr "Beállítások" + +#: src/tabs.c:107 +#: src/tabs.c:124 +#: src/tabs.c:141 +msgid "Properties" +msgstr "Tulajdonságok" + +#: src/setup.c:295 +msgid "Saturation" +msgstr "Áttetszőség" + +#: src/setup.c:259 +msgid "Save preferences on exit" +msgstr "Beállítások mentése kilépéskor" + +#: src/setup.c:285 +msgid "Scroll on output" +msgstr "Automatikus görgetés" + +#: src/commands.c:119 +msgid "Second parameter must be a port number!" +msgstr "A második paraméternek portszámnak kell lennie!" + +#: src/setup.c:228 +msgid "Setup" +msgstr "Beállítás" + +#: src/widgets.c:177 +msgid "_Setup" +msgstr "B_eállítás" + +#: src/tabs.c:583 +msgid "Tab is not connected" +msgstr "A fül nincs csatlakozva" + +#: src/widgets.c:215 +msgid "_Tab" +msgstr "_Fül" + +#: src/setup.c:280 +msgid "Terminal" +msgstr "Terminál" + +#: src/commands.c:164 +msgid "The parameter must be one character!" +msgstr "A paraméternek egy karakter hosszúnak kell lennie!" + +#: src/main.c:84 +msgid "There are connected tabs. Are you sure, you want to exit?" +msgstr "Még vannak csatlakozott fülek. Biztosan ki akarsz lépni?" + +#: src/bots.c:75 +msgid "There is already a bot named %s in the list.\n" +msgstr "Már van %s nevű bot a listában\n" + +#: src/config.c:109 +msgid "There was an error accessing GConf2: %s" +msgstr "Hiba történt a GConf2 elérése közben: %s" + +#: src/commands.c:271 +msgid "This command cannot be abbreviated!" +msgstr "Ezt a parancsot nem lehet rövidíteni!" + +#: src/commands.c:81 +msgid "This tab is already connected. Exit the bot with .quit, or use /DISCONNECT!" +msgstr "A fül csatlakoztatva van. Lépj ki a botból a .quit paranccsal, vagy használd a /DISCONNECT-et!" + +#: src/tabs.c:431 +msgid "This tab is connected. Are you sure you want to close it?" +msgstr "A fül csatlakoztatva van. Biztosan bezárod?" + +#: src/about.c:51 +msgid "translator_credits" +msgstr "Fordította: POLONKAI Gergely " + +#: src/setup.c:290 +msgid "Transparent background" +msgstr "Áttetsző háttér" + +#: src/commands.c:281 +msgid "Unknown command \"%s\"" +msgstr "Ismeretlen parancs: %s" + +#: src/tabs.c:516 +msgid "Unknown error!" +msgstr "Ismeretlen hiba!" + +#: src/callbacks.c:141 +msgid "Won't send an eggdrop command to a not connected tab" +msgstr "Nem küldhetek eggdrop parancsot egy nem csatlakoztatott fülön" + +#: src/callbacks.c:162 +msgid "Won't send message to a not connected tab" +msgstr "Nem küldhetek üzenetet egy nem csatlakoztatott fülön" + +#: data/botcommander.desktop.in.in +msgid "BotCommander" +msgstr "BotCommander" + +#: data/botcommander.desktop.in.in +msgid "BotCommander eggdrop client" +msgstr "BotCommander eggdrop kliens" + diff --git a/rules.in b/rules.in new file mode 100644 index 0000000..ccf39c0 --- /dev/null +++ b/rules.in @@ -0,0 +1,9 @@ +C_OBJECTS = main.@OBJEXT@ widgets.@OBJEXT@ callbacks.@OBJEXT@ tabs.@OBJEXT@ string.@OBJEXT@ bots.@OBJEXT@ commands.@OBJEXT@ config.@OBJEXT@ setup.@OBJEXT@ about.@OBJEXT@ networking.@OBJEXT@ history.@OBJEXT@ botlist.@OBJEXT@ debug.@OBJEXT@ chanprops.@OBJEXT@ +DOC_OBJECTS = botcommander.pdf +RM = rm -f +PIXMAPS_OBJECTS = bc48.png bc48_trans.png +INSTALL = @INSTALL@ +EXE = botcommander@EXEEXT@ +prefix = ${DESTDIR}@prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..49ac135 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,33 @@ +include ../rules + +top_srcdir = @top_srcdir@ + +CC = @CC@ +CPPFLAGS = @CPPFLAGS@ +CFLAGS = -I../include -I.. @BOTCOMMANDER_CFLAGS@ $(CPPFLAGS) @CFLAGS@ +LIBS = @BOTCOMMANDER_LIBS@ @LDFLAGS@ @LIBS@ + +all: $(C_OBJECTS) + $(CC) -o $(EXE) $(LIBS) $(C_OBJECTS) + +about.@OBJEXT@ botlist.@OBJEXT@ bots.@OBJEXT@ callbacks.@OBJEXT@ config.@OBJEXT@ networking.@OBJEXT@: ../config.h +about.@OBJEXT@ config.@OBJEXT@ main.@OBJEXT@ networking.@OBJEXT@ string.@OBJEXT@ tabs.@OBJEXT@ widgets.@OBJEXT@: ../include/defines.h +about.@OBJEXT@ botlist.@OBJEXT@ bots.@OBJEXT@ callbacks.@OBJEXT@ commands.@OBJEXT@ config.@OBJEXT@ main.@OBJEXT@ networking.@OBJEXT@ setup.@OBJEXT@ tabs.@OBJEXT@ widgets.@OBJEXT@ chanprops.@OBJEXT@: ../include/functions.h +$(C_OBJECTS): ../include/typedefs.h +botlist.@OBJEXT@ bots.@OBJEXT@ callbacks.@OBJEXT@ commands.@OBJEXT@ config.@OBJEXT@ history.@OBJEXT@ main.@OBJEXT@ networking.@OBJEXT@ setup.@OBJEXT@ tabs.@OBJEXT@ widgets.@OBJEXT@: ../include/variables.h + +.c.@OBJEXT@: + $(CC) $(CFLAGS) -o $@ -c $< + +clean: + $(RM) $(EXE) $(C_OBJECTS) + +install: all + $(top_srcdir)/mkinstalldirs $(bindir) + $(INSTALL) -m 0755 botcommander $(bindir) + +distclean: clean + $(RM) Makefile config.status config.cache config.log + +.PHONY: all clean + diff --git a/src/about.c b/src/about.c new file mode 100644 index 0000000..6abb4df --- /dev/null +++ b/src/about.c @@ -0,0 +1,91 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * about.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * The About dialog + }}} */ + +/* {{{ Includes */ +#include +#include + +#include "config.h" +#include "defines.h" +#include "functions.h" +/* }}} */ + +/* {{{ authors[] */ +const gchar *authors[] = { + "Gergely POLONKAI ", + "KrzychuG from #eggdrop@IRCNET as Beta Tester", + "Peter \"FaZy\" Erdosi as Beta Tester", + NULL, +}; +/* }}} */ + +/* {{{ documenters[] */ +const gchar *documenters[] = { + "Gergely POLONKAI ", + NULL, +}; +/* }}} */ + +/* {{{ display_about_box() */ +void +display_about_box(void) +{ + static GtkWidget *about_box = NULL; + GdkPixbuf *logo; + gchar *translator_credits = _("translator_credits"); + gchar *licence = _("licence"); + + if (!GTK_IS_WINDOW(about_box)) + { + char *buf = NULL; + + buf = g_locale_to_utf8(licence, -1, NULL, NULL, NULL); + logo = gdk_pixbuf_new_from_file(PACKAGE_PIXMAPS_DIR "/bc48_trans.png", NULL); + + about_box = gtk_about_dialog_new(); + gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(about_box), "BotCommander"); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about_box), "1.0"); + gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about_box), "\xc2\xa9 2005, Gergely POLONKAI"); + gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about_box), "Developer's Version"); + gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about_box), buf); + g_free(buf); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about_box), "http://botcommander.hu/"); + gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(about_box), authors); + gtk_about_dialog_set_documenters(GTK_ABOUT_DIALOG(about_box), documenters); + gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(about_box), translator_credits); + gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about_box), logo); + + if (logo) + g_object_unref(logo); + + g_signal_connect(G_OBJECT(about_box), "destroy", G_CALLBACK(gtk_widget_destroyed), &about_box); + gtk_widget_show(about_box); + } + else + gtk_window_present(GTK_WINDOW(about_box)); +} +/* }}} */ + diff --git a/src/botlist.c b/src/botlist.c new file mode 100644 index 0000000..81bd8f4 --- /dev/null +++ b/src/botlist.c @@ -0,0 +1,532 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * botlist.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * The Bot list dialog + }}} */ + +/* {{{ Includes */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#include "variables.h" +#include "functions.h" +/* }}} */ + +/* {{{ Variables */ +static GtkDialog *editor_window = NULL; +static GtkDialog *botlist_win = NULL; +GtkWidget *botlist_edit_button, + *botlist_connect_button, + *botlist_remove_button, + *botlist_editor_botname, + *botlist_editor_host, + *botlist_editor_port, + *botlist_editor_handle; +static GtkWidget *bot_list = NULL; +/* }}} */ + +/* {{{ add_this_data() */ +static void +add_this_data(gpointer data, gpointer user_data) +{ + GtkTreeIter iter; + GtkListStore *store = (GtkListStore *)user_data; + t_bot_data *bot = (t_bot_data *)data; + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, bot->botname, -1); +} +/* }}} */ + +/* {{{ refresh_botlist() */ +static void +refresh_botlist(void) +{ + GtkTreeModel *model; + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(bot_list)); + g_object_ref(model); + gtk_tree_view_set_model(GTK_TREE_VIEW(bot_list), NULL); + gtk_list_store_clear(GTK_LIST_STORE(model)); + + g_list_foreach(internal_bot_list, add_this_data, (gpointer)model); + + gtk_tree_view_set_model(GTK_TREE_VIEW(bot_list), model); + g_object_unref(model); +} +/* }}} */ + +/* {{{ edit_bot_dialog() */ +static void +edit_bot_dialog(GtkWidget *widget, gpointer data) +{ + /* Here we can be sure that we have a selected item */ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + gint response; + gboolean can_close = FALSE; + + if (!editor_window) + create_bot_editor(NULL); + gtk_window_set_title(GTK_WINDOW(editor_window), _("Edit bot")); + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(bot_list)); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + gchar *name; + t_bot_data *bot; + + gtk_tree_model_get(model, &iter, 0, &name, -1); + + if ((bot = get_bot_by_botname(name)) != NULL) + { + char *portnum; + + asprintf(&portnum, "%d", bot->port); + gtk_entry_set_text(GTK_ENTRY(botlist_editor_botname), bot->botname); + gtk_entry_set_text(GTK_ENTRY(botlist_editor_host), bot->host); + gtk_entry_set_text(GTK_ENTRY(botlist_editor_port), portnum); + gtk_entry_set_text(GTK_ENTRY(botlist_editor_handle), bot->handle); + + while (!can_close) + { + can_close = TRUE; + response = gtk_dialog_run(editor_window); + + if (response == GTK_RESPONSE_OK) + { + gint port_num; + char *endptr; + + gchar *botname = trim((char *)gtk_entry_get_text(GTK_ENTRY(botlist_editor_botname))); + gchar *host = trim((char *)gtk_entry_get_text(GTK_ENTRY(botlist_editor_host))); + gchar *port = trim((char *)gtk_entry_get_text(GTK_ENTRY(botlist_editor_port))); + gchar *handle = trim((char *)gtk_entry_get_text(GTK_ENTRY(botlist_editor_handle))); + if ((strcmp(botname, "") == 0) || (strcmp(host, "") == 0) || (strcmp(port, "") == 0)) + { + can_close = FALSE; +#ifdef DEBUG + if (config_data.debug) + fprintf(stderr, "All fields are mandatory except Handle\n"); +#endif /* DEBUG */ + // TODO: Here we have to notify the user + g_free(botname); + g_free(host); + g_free(port); + g_free(handle); + continue; + } + port_num = strtol(port, &endptr, 10); + if (*endptr) + { + can_close = FALSE; +#ifdef DEBUG + if (config_data.debug) + fprintf(stderr, "Port must be a number! (%s)\n", endptr); +#endif /* DEBUG */ + // TODO: Here we have to notify the user + g_free(botname); + g_free(host); + g_free(port); + g_free(handle); + continue; + } + (void)update_bot(bot, botname, host, port_num, handle); + refresh_botlist(); + + g_free(port); + g_free(botname); + g_free(host); + g_free(handle); + } + } + + gtk_widget_hide(GTK_WIDGET(editor_window)); + } + } +#ifdef DEBUG + else + if (config_data.debug) + printf("No bot selected, but signal caught??\n"); +#endif /* DEBUG */ +} +/* }}} */ + +/* {{{ add_bot_dialog() */ +/* This callback is called when the "Add" button is pressed in the Botlist dialog */ +static void +add_bot_dialog(GtkWidget *widget, gpointer data) +{ + gint response; + gboolean can_close = FALSE; + + if (!editor_window) + create_bot_editor(NULL); + gtk_window_set_title(GTK_WINDOW(editor_window), _("Add bot")); + + gtk_entry_set_text(GTK_ENTRY(botlist_editor_botname), ""); + gtk_entry_set_text(GTK_ENTRY(botlist_editor_host), ""); + gtk_entry_set_text(GTK_ENTRY(botlist_editor_port), ""); + gtk_entry_set_text(GTK_ENTRY(botlist_editor_handle), ""); + + while (!can_close) + { + can_close = TRUE; + response = gtk_dialog_run(editor_window); + + if (response == GTK_RESPONSE_OK) + { + gint port_num; + char *endptr; + + gchar *botname = trim((char *)gtk_entry_get_text(GTK_ENTRY(botlist_editor_botname))); + gchar *host = trim((char *)gtk_entry_get_text(GTK_ENTRY(botlist_editor_host))); + gchar *port = trim((char *)gtk_entry_get_text(GTK_ENTRY(botlist_editor_port))); + gchar *handle = trim((char *)gtk_entry_get_text(GTK_ENTRY(botlist_editor_handle))); + if ((strcmp(botname, "") == 0) || (strcmp(host, "") == 0) || (strcmp(port, "") == 0)) + { + can_close = FALSE; +#ifdef DEBUG + if (config_data.debug) + fprintf(stderr, "All fields are mandatory except Handle\n"); +#endif /* DEBUG */ + // TODO: Here we have to notify the user + g_free(botname); + g_free(host); + g_free(port); + g_free(handle); + continue; + } + port_num = strtol(port, &endptr, 10); + if (*endptr) + { + can_close = FALSE; +#ifdef DEBUG + if (config_data.debug) + fprintf(stderr, "Port must be a number! (%s)\n", endptr); +#endif /* DEBUG */ + // TODO: Here we have to notify the user + g_free(botname); + g_free(host); + g_free(port); + g_free(handle); + continue; + } + if (add_bot(botname, host, port_num, handle) != BCE_SUCCESS) + { +#ifdef DEBUG + if (config_data.debug) + fprintf(stderr, "Port must be a number! (%s)\n", endptr); +#endif /* DEBUG */ + // TODO: Here we have to notify the user + } + else + refresh_botlist(); + g_free(port); + g_free(botname); + g_free(host); + g_free(handle); + } + } + + gtk_widget_hide(GTK_WIDGET(editor_window)); +} +/* }}} */ + +/* {{{ cchange() */ +/* This callback is called, when I select a list item */ +void +static cchange(GtkWidget *widget, gpointer data) +{ + /* Here we can be sure that we have a selected item */ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + gtk_widget_set_sensitive(botlist_connect_button, TRUE); + gtk_widget_set_sensitive(botlist_edit_button, TRUE); + gtk_widget_set_sensitive(botlist_remove_button, TRUE); + } +#ifdef DEBUG + else + if (config_data.debug) + printf("No bot selected, but signal caught??\n"); +#endif /* DEBUG */ +} +/* }}} */ + +/* {{{ cactivate() */ +/* This callback is called when I double-click a list item, or when I navigate to an item and press Enter */ +static void +cactivate(GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + gtk_button_clicked(GTK_BUTTON(botlist_connect_button)); +#ifdef DEBUG + else + if (config_data.debug) + fprintf(stderr, "No bot selected, but signal caught??\n"); +#endif /* DEBUG */ +} +/* }}} */ + +/* {{{ toggle_cursor_row() */ +/* This callback is called when I select or deselect a list item (but not when I change selection!) */ +static gboolean +toggle_cursor_row(GtkTreeView *widget, gpointer data) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + gtk_widget_set_sensitive(botlist_connect_button, FALSE); + gtk_widget_set_sensitive(botlist_edit_button, FALSE); + gtk_widget_set_sensitive(botlist_remove_button, FALSE); + } + else + { + gtk_widget_set_sensitive(botlist_connect_button, TRUE); + gtk_widget_set_sensitive(botlist_edit_button, TRUE); + gtk_widget_set_sensitive(botlist_remove_button, TRUE); + } + + return TRUE; +} +/* }}} */ + +/* {{{ create_and_fill_model() */ +/* This function creates the tree model and fills it with data */ +static GtkTreeModel * +create_and_fill_model(void) +{ + GtkListStore *store; + + store = gtk_list_store_new(1, G_TYPE_STRING); + + g_list_foreach(internal_bot_list, add_this_data, (gpointer)store); + + return GTK_TREE_MODEL(store); +} +/* }}} */ + +/* {{{ display_botlist_window() */ +/* This one creates the bot list window if it doesn't exist, and displays it */ +void +display_botlist_window(void) +{ + gint response; + gboolean created_model = FALSE; + GtkTreeModel *model; + + if (!GTK_IS_WINDOW(botlist_win)) + { + GtkCellRenderer *renderer; + GtkWidget *hbox, + *vbox, + *button, + *scrollwin, + *image, + *bbox, + *blabel; + + created_model = TRUE; + + botlist_win = (GtkDialog *)gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(botlist_win), _("Bot list")); + gtk_window_set_transient_for(GTK_WINDOW(botlist_win), GTK_WINDOW(main_window)); + gtk_window_set_destroy_with_parent(GTK_WINDOW(botlist_win), TRUE); + gtk_window_set_modal(GTK_WINDOW(botlist_win), TRUE); + + image = gtk_image_new_from_stock(GTK_STOCK_CONNECT, GTK_ICON_SIZE_BUTTON); + blabel = gtk_label_new_with_mnemonic(_("_Connect")); + bbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(bbox), image, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(bbox), blabel, TRUE, TRUE, 0); + + botlist_connect_button = gtk_button_new(); + gtk_widget_set_sensitive(botlist_connect_button, FALSE); + gtk_container_add(GTK_CONTAINER(botlist_connect_button), bbox); + gtk_widget_show_all(botlist_connect_button); + gtk_dialog_add_action_widget(botlist_win, botlist_connect_button, GTK_RESPONSE_APPLY); + + button = gtk_button_new_from_stock(GTK_STOCK_SAVE); + gtk_widget_show(button); + gtk_dialog_add_action_widget(botlist_win, button, GTK_RESPONSE_OK); + + button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); + gtk_widget_show(button); + gtk_dialog_add_action_widget(botlist_win, button, GTK_RESPONSE_CANCEL); + + scrollwin = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_set_size_request(scrollwin, 150, 200); + + renderer = gtk_cell_renderer_text_new(); + bot_list = gtk_tree_view_new(); + gtk_signal_connect(GTK_OBJECT(bot_list), "cursor-changed", GTK_SIGNAL_FUNC(cchange), NULL); + gtk_signal_connect(GTK_OBJECT(bot_list), "row-activated", GTK_SIGNAL_FUNC(cactivate), NULL); + gtk_signal_connect(GTK_OBJECT(bot_list), "toggle-cursor-row", GTK_SIGNAL_FUNC(toggle_cursor_row), NULL); + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(bot_list), -1, _("Bot name"), renderer, "text", 0, NULL); + model = create_and_fill_model(); + gtk_tree_view_set_model(GTK_TREE_VIEW(bot_list), model); + g_object_unref(model); + + gtk_container_add(GTK_CONTAINER(scrollwin), bot_list); + + hbox = gtk_hbox_new(FALSE, 2); + + gtk_box_pack_start(GTK_BOX(hbox), scrollwin, TRUE, TRUE, 0); + + vbox = gtk_vbox_new(FALSE, 2); + + button = gtk_button_new_from_stock(GTK_STOCK_ADD); + gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(add_bot_dialog), NULL); + gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); + + botlist_edit_button = gtk_button_new_from_stock(GTK_STOCK_EDIT); + gtk_signal_connect(GTK_OBJECT(botlist_edit_button), "clicked", GTK_SIGNAL_FUNC(edit_bot_dialog), NULL); + gtk_widget_set_sensitive(botlist_edit_button, FALSE); + gtk_box_pack_start(GTK_BOX(vbox), botlist_edit_button, FALSE, FALSE, 0); + + botlist_remove_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); + gtk_widget_set_sensitive(botlist_remove_button, FALSE); + gtk_box_pack_start(GTK_BOX(vbox), botlist_remove_button, FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); + + gtk_widget_show_all(hbox); + + gtk_container_add(GTK_CONTAINER(botlist_win->vbox), hbox); + } + + if (!created_model) + refresh_botlist(); + + response = gtk_dialog_run(botlist_win); + + switch (response) + { + case GTK_RESPONSE_APPLY: + { + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + t_tab_data *tab = get_active_tab(); + + if (tab) + gtk_widget_grab_focus(tab->editbox); + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(bot_list)); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + gchar *name; + + if (!tab) + add_tab(&tab); + + if (tab->connected) + add_tab(&tab); + + gtk_tree_model_get(model, &iter, 0, &name, -1); + + assign_bot_to_tab_by_name(tab, name); + g_free(name); + connect_tab(tab); + } +#ifdef DEBUG + else + if (config_data.debug) + printf("No bot selected, but signal caught??\n"); +#endif /* DEBUG */ + } + break; + case GTK_RESPONSE_OK: + save_bot_list_to_config(); + break; + } + + gtk_widget_hide(GTK_WIDGET(botlist_win)); +} +/* }}} */ + +/* {{{ create_bot_editor */ +void +create_bot_editor(t_bot_data *bot) +{ + if (!editor_window) + { + GtkWidget *button, + *label; + GtkTable *table; + + editor_window = (GtkDialog *)gtk_dialog_new(); + gtk_window_set_transient_for(GTK_WINDOW(editor_window), GTK_WINDOW(botlist_win)); + gtk_window_set_destroy_with_parent(GTK_WINDOW(editor_window), TRUE); + gtk_window_set_modal(GTK_WINDOW(editor_window), TRUE); + + table = (GtkTable *)gtk_table_new(4, 2, FALSE); + + gtk_table_attach(table, (label = gtk_label_new(_("Bot name"))), 0, 1, 0, 1, GTK_FILL, 0, 2, 2); + gtk_table_attach(table, (botlist_editor_botname = gtk_entry_new()), 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 2, 2); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + + gtk_table_attach(table, (label = gtk_label_new(_("Host"))), 0, 1, 1, 2, GTK_FILL, 0, 2, 2); + gtk_table_attach(table, (botlist_editor_host = gtk_entry_new()), 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 2, 2); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + + gtk_table_attach(table, (label = gtk_label_new(_("Port"))), 0, 1, 2, 3, GTK_FILL, 0, 2, 2); + gtk_table_attach(table, (botlist_editor_port = gtk_entry_new()), 1, 2, 2, 3, GTK_FILL | GTK_EXPAND, 0, 2, 2); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + + gtk_table_attach(table, (label = gtk_label_new(_("Handle"))), 0, 1, 3, 4, GTK_FILL, 0, 2, 2); + gtk_table_attach(table, (botlist_editor_handle = gtk_entry_new()), 1, 2, 3, 4, GTK_FILL | GTK_EXPAND, 0, 2, 2); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + + gtk_container_add(GTK_CONTAINER(editor_window->vbox), GTK_WIDGET(table)); + + button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); + gtk_dialog_add_action_widget(editor_window, button, GTK_RESPONSE_CANCEL); + + button = gtk_button_new_from_stock(GTK_STOCK_SAVE); + gtk_dialog_add_action_widget(editor_window, button, GTK_RESPONSE_OK); + } + gtk_widget_show_all(GTK_WIDGET(editor_window)); +} +/* }}} */ + diff --git a/src/bots.c b/src/bots.c new file mode 100644 index 0000000..11286e4 --- /dev/null +++ b/src/bots.c @@ -0,0 +1,270 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * bots.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Bot list handling + }}} */ + +/* TODO: Put this into a Makefile */ +#define _GNU_SOURCE +/* {{{ Includes */ +#include +#include +#include +#include + +#include "config.h" + +#include "typedefs.h" +#include "functions.h" +#include "variables.h" +/* }}} */ + +/* {{{ Variables */ +GList *internal_bot_list; +/* }}} */ + +#ifdef DEBUG +/* {{{ print_this_bot() */ +void print_this_bot(gpointer data, gpointer user_data) +{ + t_bot_data *temp = (t_bot_data *)data; + + printf("%s:%s:%d:%s\n", temp->botname, temp->host, temp->port, temp->handle); +} +/* }}} */ + +/* {{{ list_bots() */ +void +list_bots(void) +{ + g_list_foreach(internal_bot_list, print_this_bot, NULL); +} +/* }}} */ +#endif + +/* {{{ search_function() */ +static gint +search_function(gconstpointer a, gconstpointer b) +{ + t_bot_data *bot = (t_bot_data *)a; + char *botname = (char *)b; + + return strcmp(bot->botname, botname); +} +/* }}} */ + +/* {{{ add_bot() */ +gint +add_bot(gchar *botname, gchar *host, guint port, gchar *handle) +{ + t_bot_data *temp; + + if (g_list_find_custom(internal_bot_list, botname, search_function)) + { + // TODO: Here we should notify the user that this bot already exists. +#ifdef DEBUG + if (config_data.debug) + fprintf(stderr, _("There is already a bot named %s in the list.\n"), botname); +#endif /* DEBUG */ + return BCE_BOT_EXISTS; + } + +#ifdef DEBUG + printf("Adding bot %s at %s:%d with user %s\n", botname, host, port, handle); +#endif + + temp = g_malloc(sizeof(t_bot_data)); + + temp->botname = g_strdup(botname); + temp->host = g_strdup(host); + temp->port = port; + temp->handle = g_strdup(handle); + + internal_bot_list = g_list_append(internal_bot_list, temp); + + return BCE_SUCCESS; +} +/* }}} */ + +/* {{{ del_bot() */ +gint +del_bot(gchar *botname) +{ + return BCE_SUCCESS; +} +/* }}} */ + +/* {{{ get_bot_by_botname() */ +t_bot_data * +get_bot_by_botname(gchar *name) +{ + GList *temp = g_list_find_custom(internal_bot_list, name, search_function); + + if (temp) + return (t_bot_data *)(temp->data); + + return NULL; +} +/* }}} */ + +/* {{{ create_bot_record() */ +gint +create_bot_record(gchar *host, gint port, t_bot_data **rec) +{ + t_bot_data *temp; + + if (rec == NULL) + return BCE_NOMEM; + + temp = g_malloc(sizeof(t_bot_data)); + + if (temp) + { + temp->botname = NULL; + temp->host = g_strdup(host); + temp->port = port; + temp->handle = NULL; + + *rec = temp; + return BCE_SUCCESS; + } + + return BCE_NOMEM; +} +/* }}} */ + +/* {{{ update_bot() */ +gint +update_bot(t_bot_data *bot, gchar *botname, gchar *host, guint port, gchar *handle) +{ + if (bot) + { + t_bot_data *temp = g_malloc(sizeof(t_bot_data)); + memset(temp, 0, sizeof(t_bot_data)); + + if (bot->botname) + { + temp->botname = g_strdup(bot->botname); + g_free(bot->botname); + } + if (bot->host) + { + temp->host = g_strdup(bot->host); + g_free(bot->host); + } + temp->port = bot->port; + if (bot->handle) + { + temp->handle = g_strdup(bot->handle); + g_free(bot->handle); + } + + bot->botname = g_strdup(botname); + bot->host = g_strdup(host); + bot->port = port; + bot->handle = g_strdup(handle); + + if (temp->botname) + g_free(temp->botname); + if (temp->host) + g_free(temp->host); + if (temp->handle) + g_free(temp->handle); + } + + return BCE_SUCCESS; +} +/* }}} */ + +/* {{{ get_bot_by_name() */ +gint +get_bot_by_name(gconstpointer a, gconstpointer b) +{ + GConfEntry *entry = (GConfEntry *)a; + gchar *name = (gchar *)b; + gchar *i; + GConfValue *value; + gchar *this_name; + gchar *key; + gint len = strlen(GCONF2_ROOT "/bots/"); + + /* TODO: Would be easier with regex? */ + key = (gchar *)gconf_entry_get_key(entry); + if (strncmp(key + len, "bot", 3) != 0) + return 1; + for (i = key + len + 3; *i && isdigit(*i); i++); + if (*i != '_') + return 1; + if (strcmp(++i, "name") != 0) + return 1; + value = gconf_entry_get_value(entry); + if (value->type != GCONF_VALUE_STRING) + return 1; + this_name = (char *)gconf_value_get_string(value); + return strcmp(this_name, name); +} +/* }}} */ + +/* {{{ free_bot_data() */ +void +free_bot_data(gpointer data, gpointer user_data) +{ + t_bot_data *bot = (t_bot_data *)data; + + if (bot) + { + if (bot->botname) + g_free(bot->botname); + if (bot->host) + g_free(bot->host); + if (bot->handle) + g_free(bot->handle); + g_free(bot); + } +} +/* }}} */ + +/* {{{ is_this_num_bot() */ +gint +is_this_num_bot(gconstpointer a, gconstpointer b) +{ + if (((t_bot_data *)a)->id == *((guint *)b)) + return 0; + + return 1; +} +/* }}} */ + +/* {{{ get_bot_by_conf_num() */ +t_bot_data * +get_bot_by_conf_num(guint num) +{ + GList *entry; + + entry = g_list_find_custom(internal_bot_list, &num, is_this_num_bot); + if (entry) + return entry->data; + return NULL; +} +/* }}} */ + diff --git a/src/callbacks.c b/src/callbacks.c new file mode 100644 index 0000000..0ee6aa0 --- /dev/null +++ b/src/callbacks.c @@ -0,0 +1,518 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * callbacks.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Various widget callbacks + }}} */ + +/* {{{ Includes */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#include "variables.h" +#include "functions.h" +/* }}} */ + +/* {{{ destroy_event() */ +void +destroy_event(GtkWidget *widget, gpointer data) +{ + if (widget == main_window) + gtk_main_quit(); +} +/* }}} */ + +/* {{{ delete_event() */ +gboolean +delete_event(GtkWidget * widget, GdkEvent *event, gpointer data) +{ + exit_cleanly(FALSE); + return FALSE; +} +/* }}} */ + +/* {{{ toolbar_quit() */ +void +toolbar_quit(GtkButton *button, gpointer data) +{ + exit_cleanly(FALSE); +} +/* }}} */ + +/* {{{ toolbar_add_tab() */ +void +toolbar_add_tab(GtkButton *button, gpointer data) +{ + add_tab(NULL); +} +/* }}} */ + +/* {{{ toolbar_close_active() */ +void toolbar_close_active(GtkButton *button, gpointer data) +{ + close_tab(get_active_tab()); +} +/* }}} */ + +/* {{{ toolbar_open_prefs() */ +void +toolbar_open_prefs(GtkButton *button, gpointer data) +{ + display_setup_window(); +} +/* }}} */ + +/* {{{ book_change_tab() */ +void +book_change_tab(GtkNotebook *book, GtkNotebookPage *newpage, guint pagenum, gpointer data) +{ + GList *list; + + list = g_list_find_custom(tab_list, &pagenum, find_tab_by_pagenum); + if (list) + { + t_tab_data *temp; + gchar *buf; + gboolean sidebar_visible; + gboolean menuitem_state; + GtkWidget *box = gtk_paned_get_child2(GTK_PANED(gtk_notebook_get_nth_page(GTK_NOTEBOOK(main_book), pagenum))); + + temp = list->data; + Context; + set_title(NULL, "BotCommander - %s", gtk_label_get_text(GTK_LABEL(temp->label))); + Context; + buf = g_malloc(strlen(_("Mode: %c")) + 1); + sprintf(buf, _("Mode: %c"), toupper(temp->mode)); + gtk_label_set_text(GTK_LABEL(main_statuslabel_mode), buf); + g_free(buf); + + menuitem_state = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(main_menu_show_sidebar)); + sidebar_visible = GTK_WIDGET_VISIBLE(box); + + if (menuitem_state != sidebar_visible) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(main_menu_show_sidebar), sidebar_visible); + } +} +/* }}} */ + +/* {{{ close_tab_cb() */ +void +close_tab_cb(GtkWidget *button, gpointer data) +{ + GList *to_remove = g_list_find(tab_list, data); + + if (to_remove) + close_tab((t_tab_data *)data); +} +/* }}} */ + +/* {{{ entry_activate() */ +gboolean +entry_activate(GtkWidget *widget, gpointer data) +{ + char this_mode; + t_tab_data *active_tab = (t_tab_data *)data; + gchar *text; + gboolean add_to_history = TRUE; + gboolean shift = FALSE; + gboolean want_change = TRUE; + + this_mode = active_tab->mode; + text = (gchar *)gtk_entry_get_text(GTK_ENTRY(widget)); + + if (*text == '/') + this_mode = 'b'; + else if (*text == '.') + this_mode = 'e'; + else if (*text == '@') + this_mode = 'm'; + + switch (tolower(this_mode)) + { + case 'b': + Context; + want_change = process_commandline((*text == '/') ? text + 1 : text, active_tab); + Context; + shift = (*text == '/'); + Context; + break; + case 'e': + if (!active_tab->connected) + { + feed_error_to_terminal(active_tab, TRUE, _("Won't send an eggdrop command to a not connected tab")); + add_to_history = FALSE; + break; + } + else + { + char *buf = NULL; + + buf = g_convert(text, -1, BOT_CHARSET, "UTF-8", NULL, NULL, NULL); + if (buf) + { + dprintf(active_tab->sock, "%s%s\n", (*buf != *EGG_CMD_CHAR) ? EGG_CMD_CHAR : "", buf); + g_free(buf); + } + } + shift = (*text == '.'); + break; + case 'm': + default: + if (!active_tab->connected) + { + feed_error_to_terminal(active_tab, TRUE, _("Won't send message to a not connected tab")); + add_to_history = FALSE; + break; + } + else + { + char *buf = NULL; + + buf = g_convert(text, -1, BOT_CHARSET, "UTF-8", NULL, NULL, NULL); + if (buf) + { + dprintf(active_tab->sock, "%s%s\n", (*buf == *EGG_CMD_CHAR) ? " " : "", buf); + g_free(buf); + } + } + shift = (*text == '@'); + } + + Context; + + if ((add_to_history) && (gtk_entry_get_visibility(GTK_ENTRY(widget)))) + history_add(active_tab, tolower(this_mode), (shift) ? text + 1 : text); + active_tab->history_position = -1; + Context; + + if (want_change) + gtk_entry_set_text(GTK_ENTRY(((t_tab_data *)data)->editbox), ""); + + Context; + + return TRUE; +} +/* }}} */ + +/* {{{ menu_exit() */ +void +menu_exit(GtkWidget *widget, gpointer data) +{ + exit_cleanly(FALSE); +} +/* }}} */ + +/* {{{ menu_mode_changed() */ +void +menu_mode_changed(GtkWidget *widget, gpointer data) +{ + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) + { + char m = 0; + + if (widget == main_menu_mode_b) + m = 'b'; + else + { + if (widget == main_menu_mode_e) + m = 'e'; + else + { + if (widget == main_menu_mode_m) + m = 'm'; + } + } + if (m) + change_mode(m, TRUE); + } +} +/* }}} */ + +/* {{{ menu_botlist_open() */ +void +menu_botlist_open(GtkWidget *widget, gpointer data) +{ + display_botlist_window(); +} +/* }}} */ + +/* {{{ menu_prefs_open() */ +void +menu_prefs_open(GtkWidget *widget, gpointer data) +{ + display_setup_window(); +} +/* }}} */ + +/* {{{ menu_new_tab() */ +void +menu_new_tab(GtkWidget *widget, gpointer data) +{ + add_tab(NULL); +} +/* }}} */ + +/* {{{ menu_close_tab() */ +void +menu_close_tab(GtkWidget *widget, gpointer data) +{ + close_tab(get_active_tab()); +} +/* }}} */ + +/* {{{ menu_about() */ +void +menu_about(GtkWidget *widget, gpointer data) +{ + display_about_box(); +} +/* }}} */ + +/* {{{ entry_keypress() */ +int +entry_keypress(GtkEntry *entry, GdkEventKey *event, gpointer data) +{ + if (data) + { + t_tab_data *tab = (t_tab_data *)data; + if (entry == (GtkEntry *)tab->editbox) + { + if (event->keyval == GDK_Up) + { + gint count = get_history_len(tab); + gint steps; + t_history_data *temp = tab->history; + + if (count == 0) + { + tab->history_position = -1; + return TRUE; + } + + if ((count > 0) && (count > tab->history_position + 1)) + tab->history_position++; + + steps = count - tab->history_position - 1; + while (steps) + { + if (!temp) + return TRUE; + temp = temp->next; + steps--; + } + gtk_entry_set_text(GTK_ENTRY(tab->editbox), temp->line); + gtk_entry_set_position(GTK_ENTRY(tab->editbox), -1); + return TRUE; + } + else if (event->keyval == GDK_Down) + { + gint count = get_history_len(tab); + + if (count == 0) + { + tab->history_position = -1; + return TRUE; + } + + if (tab->history_position > -1) + tab->history_position--; + + if (tab->history_position == -1) + gtk_entry_set_text(GTK_ENTRY(tab->editbox), ""); + else + { + t_history_data *temp = tab->history; + gint steps = count - tab->history_position - 1; + + while (steps) + { + if (!temp) + return TRUE; + temp = temp->next; + steps--; + } + gtk_entry_set_text(GTK_ENTRY(tab->editbox), temp->line); + gtk_entry_set_position(GTK_ENTRY(tab->editbox), -1); + } + return TRUE; + } + } + } + switch (event->keyval) + { + case GDK_0: + case GDK_1: + case GDK_2: + case GDK_3: + case GDK_4: + case GDK_5: + case GDK_6: + case GDK_7: + case GDK_8: + case GDK_9: + if (event->state & GDK_MOD1_MASK) + { + gint num = event->keyval - GDK_0; + if (num == 0) + num = 9; + else + num--; + + change_active_tab(num); + return TRUE; + } + break; + case GDK_Tab: + return TRUE; + break; + } + if (event->keyval == GDK_Tab) + return TRUE; + + return FALSE; +} +/* }}} */ + +/* {{{ socket_event() */ +void +socket_event(gpointer data, gint fd, GdkInputCondition cond) +{ + t_tab_data *tab = data; + ssize_t len; + char buf[MAX_READ_LINE_LEN]; + static char *current_line = NULL; + static int current_line_pointer = 0; + static char current_telnet_code[4]; + static int current_telnet_code_pointer = 0; + + memset(&buf, 0, MAX_READ_LINE_LEN); + memset(¤t_telnet_code, 0, 4); + + len = recv(tab->sock, &buf, MAX_READ_LINE_LEN - 1, 0); + + if (len == 0) + disconnect_tab(tab); + else if (len > 0) + { + char *obuf = NULL, *a; + + if (tab->data_arrived == FALSE) + { + if (config_data.change_to_message) + change_mode('M', FALSE); + tab->data_arrived = TRUE; + feed_info_to_terminal(tab, TRUE, _("Connected")); + } + + if (current_line == NULL) + { + current_line = g_malloc(MAX_READ_LINE_LEN + 1); + memset(current_line, 0, MAX_READ_LINE_LEN + 1); + } + + for (a = (char *)&buf; *a; a++) + { + if (*a == '\r') + continue; + if (*a == '\n') + { + process_incoming_data(tab, current_line); + memset(current_line, 0, MAX_READ_LINE_LEN + 1); + current_line_pointer = 0; + continue; + } + if ((*a == *TELNET_IAC) || (*a == *TELNET_WILL) || (*a == *TELNET_WONT) || (*a == *TELNET_ECHO)) + { + current_telnet_code[current_telnet_code_pointer++] = *a; + if (strlen((char *)¤t_telnet_code) == 3) + { + if (strcmp((char *)¤t_telnet_code, TELNET_WILL_ECHO) == 0) + gtk_entry_set_visibility(GTK_ENTRY(tab->editbox), FALSE); + else if (strcmp((char *)¤t_telnet_code, TELNET_WONT_ECHO) == 0) + gtk_entry_set_visibility(GTK_ENTRY(tab->editbox), TRUE); + memset(¤t_telnet_code, 0, 4); + current_telnet_code_pointer = 0; + } + continue; + } + current_line[current_line_pointer++] = *a; + } + + obuf = g_convert(buf, -1, "UTF-8", BOT_CHARSET, NULL, NULL, NULL); + g_free(obuf); + } +#ifdef DEBUG + else if (config_data.debug) + { + char *buf = NULL; + char *orig = strerror(errno); + + buf = g_locale_to_utf8(orig, -1, NULL, NULL, NULL); + feed_error_to_terminal(tab, TRUE, "%s", buf); + g_free(buf); + + disconnect_tab(tab); + } +#endif /* DEBUG */ +} +/* }}} */ + +/* {{{ menu_showhide_sidebar() */ +void +menu_showhide_sidebar(GtkWidget *menuitem, gpointer data) +{ + gint current_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(main_book)); + + if (current_page >= 0) + { + gboolean new_state, + current_state; + GtkWidget *box = gtk_paned_get_child2(GTK_PANED(gtk_notebook_get_nth_page(GTK_NOTEBOOK(main_book), current_page))); + + new_state = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)); + current_state = GTK_WIDGET_VISIBLE(box); + + feed_info_to_terminal(get_active_tab(), TRUE, "Current state: %s; new state: %s\n", (current_state) ? "active" : "not active", (new_state) ? "active" : "not active"); + + if (current_state != new_state) + { + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)) == TRUE) + gtk_widget_show_all(box); + else + gtk_widget_hide_all(box); + } + + } +} +/* }}} */ + diff --git a/src/chanprops.c b/src/chanprops.c new file mode 100644 index 0000000..2060486 --- /dev/null +++ b/src/chanprops.c @@ -0,0 +1,138 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * chanprops.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * This holds functions which belong to the Channel properties dialog + }}} */ + +/* {{{ Includes */ +#include +#include +#include + +#include "functions.h" +#include "typedefs.h" +/* }}} */ + +/* {{{ find_chan_in_list() */ +gint +find_chan_in_list(gconstpointer a, gconstpointer b) +{ + t_channel *chanrec = (t_channel *)a; + gchar *channame = (gchar *)b; + + if (streq(chanrec->name, channame, FALSE)) + return 0; + + return 1; +} +/* }}} */ + +/* {{{ find_chan_property() */ +gint +find_chan_property(gconstpointer a, gconstpointer b) +{ + t_chan_prop *prop = (t_chan_prop *)a; + gchar *propname = (gchar *)b; + + return strcmp(prop->name, propname); +} +/* }}} */ + +/* {{{ update_channel_property() */ +void +update_channel_property(t_tab_data *tab, gchar *chan, gchar *property) +{ + GList *this_chan; + + if ((this_chan = g_list_find_custom(tab->actual_channel_list, chan, find_chan_in_list))) + { + t_chan_prop *prop; + GList *this_prop; + t_channel *chanrec = this_chan->data; + + switch (tab->chanprops_list_num) + { + case 1: + /* Channel modes */ + break; + case 2: + /* idle-kick */ + break; + case 3: + /* stopnethack-mode */ + break; + case 4: + /* revenge-mode */ + break; + } + + prop = g_malloc0(sizeof(t_chan_prop)); + + prop->bool_prop = ((*property == '+') || (*property == '-')); + + Context; + + if (prop->bool_prop) + { + prop->name = g_strdup(property + 1); + prop->bool_value = (*property == '+') ? TRUE : FALSE; + prop->string_value = NULL; + } + else + { + gchar *a; + + Context; + + for (a = property; *a; a++) + if (isspace(*a)) + break; + + if (*a && (a - property > 0)) + { + prop->name = g_strndup(property, a - property); + for (; *a; a++) + if (!isspace(*a)) + break; + prop->string_value = g_strdup(a); + } + + Context; + } + + if (prop->name) + { + this_prop = g_list_find_custom(chanrec->properties, prop->name, find_chan_property); + if (this_prop) + { + printf("Updating %s property \"%s\" with value %s\n", (prop->bool_prop) ? "boolean" : "string", prop->name, (prop->bool_prop) ? ((prop->bool_value) ? "TRUE" : "FALSE") : prop->string_value); + } + else + { + printf("Adding %s property \"%s\" with value %s\n", (prop->bool_prop) ? "boolean" : "string", prop->name, (prop->bool_prop) ? ((prop->bool_value) ? "TRUE" : "FALSE") : prop->string_value); + } + } + } +} +/* }}} */ + diff --git a/src/commands.c b/src/commands.c new file mode 100644 index 0000000..b95761f --- /dev/null +++ b/src/commands.c @@ -0,0 +1,453 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * commands.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * BotCommander internal command definitions + }}} */ + +/* TODO: Put this into a Makefile */ +#define _GNU_SOURCE +/* {{{ Includes */ +#include +#include +#include +#include + +#include "typedefs.h" +#include "functions.h" +#include "variables.h" +/* }}} */ + +/* {{{ Prototypes */ +BC_COMMAND(command_exit); +BC_COMMAND(command_close); +BC_COMMAND(command_connect); +BC_COMMAND(command_assign); +BC_COMMAND(command_mode); +BC_COMMAND(command_histlist); +BC_COMMAND(command_botlist); +BC_COMMAND(command_preferences); +BC_COMMAND(command_disconnect); +/* }}} */ + +/* {{{ internal_command[] */ +t_command internal_command[] = { +/* verb, CT_INTERNAL, paramnum, can_abbrev, function */ + {"QUIT", CT_INTERNAL, 0, FALSE, command_exit}, + {"CLOSE", CT_INTERNAL, 0, TRUE, command_close}, + {"CONNECT", CT_INTERNAL, 0, TRUE, command_connect}, + {"ASSIGN", CT_INTERNAL, 1, TRUE, command_assign}, + {"MODE", CT_INTERNAL, 1, TRUE, command_mode}, + {"HISTLIST", CT_INTERNAL, 0, TRUE, command_histlist}, + {"BOTLIST", CT_INTERNAL, 0, TRUE, command_botlist}, + {"PREFERENCES", CT_INTERNAL, 0, TRUE, command_preferences}, + {"DISCONNECT", CT_INTERNAL, 0, TRUE, command_disconnect}, + {NULL, CT_INTERNAL, 0, FALSE, NULL}, +}; +/* }}} */ + +#define num_commands (sizeof(command) / sizeof(t_command)) + +/* {{{ command_exit */ +BC_COMMAND(command_exit) +{ + exit_cleanly(FALSE); + return FALSE; +} +/* }}} */ + +/* {{{ command_close */ +BC_COMMAND(command_close) +{ + Context; + close_tab(tab); + Context; + return FALSE; +} +/* }}} */ + +/* {{{ command_connect */ +BC_COMMAND(command_connect) +{ + if (tab->connected) + { + feed_error_to_terminal(tab, TRUE, _("This tab is already connected. Exit the bot with .quit, or use /DISCONNECT!")); + return TRUE; + } + if ((paramnum == 0) && (tab->bot == NULL)) + { + feed_error_to_terminal(tab, TRUE, _("No bot is assigned to this tab. Use ASSIGN to do that.")); + return TRUE; + } + if (paramnum == 0) + { +#ifdef DEBUG /* {{{ */ + if (config_data.debug) + feed_message_to_terminal(tab, TRUE, _("Connecting to %s"), tab->bot->botname); +#endif /* DEBUG }}} */ + } + if (paramnum == 1) + { + t_bot_data *bot; + + if ((bot = get_bot_by_botname(param[1])) == NULL) + { + feed_error_to_terminal(tab, TRUE, _("No bot exists by that name")); + return TRUE; + } + assign_bot_to_tab(tab, bot); +#ifdef DEBUG /* {{{ */ + if (config_data.debug) + feed_message_to_terminal(tab, TRUE, _("Connecting to %s"), bot->botname); +#endif /* DEBUG }}} */ + } + if (paramnum > 1) + { + gchar *host = param[1]; + gint port; + t_bot_data *bot; + + if (!is_numeric(param[2], &port)) + { + feed_error_to_terminal(tab, TRUE, _("Second parameter must be a port number!")); + return TRUE; + } + if (create_bot_record(host, port, &bot) != BCE_SUCCESS) + { + feed_error_to_terminal(tab, TRUE, _("Not enough memory!")); + return TRUE; + } + tab->bot = bot; + set_title(tab, "%s:%d", host, port); +#ifdef DEBUG /* {{{ */ + if (config_data.debug) + feed_message_to_terminal(tab, TRUE, _("Connecting to %s:%d"), host, port); +#endif /* DEBUG }}} */ + } + + connect_tab(tab); + return TRUE; +} +/* }}} */ + +/* {{{ command_assign */ +BC_COMMAND(command_assign) +{ + if (!assign_bot_to_tab_by_name(tab, param[1])) + { + feed_error_to_terminal(tab, TRUE, _("No bot exists by this name")); + return TRUE; + } + return TRUE; +} +/* }}} */ + +/* {{{ command_mode */ +BC_COMMAND(command_mode) +{ + char newmode; + if (paramnum < 1) + { + feed_error_to_terminal(tab, TRUE, _("Not enough parameters!")); + return TRUE; + } + if (paramnum > 1) + { + feed_error_to_terminal(tab, TRUE, _("Only one parameter required!")); + return TRUE; + } + if (strlen(param[1]) > 1) + { + feed_error_to_terminal(tab, TRUE, _("The parameter must be one character!")); + return TRUE; + } + newmode = *param[1]; + if (!strchr("bem", tolower(newmode))) + { + feed_error_to_terminal(tab, TRUE, _("Mode char can be one of B, E or M!")); + return TRUE; + } + + change_mode(newmode, FALSE); + return TRUE; +} +/* }}} */ + +/* {{{ command_histlist */ +BC_COMMAND(command_histlist) +{ + t_history_data *temp = tab->history; + + while (temp) + { + feed_info_to_terminal(tab, TRUE, temp->line); + temp = temp->next; + } + + return TRUE; +} +/* }}} */ + +/* {{{ command_botlist */ +BC_COMMAND(command_botlist) +{ +#ifdef DEBUG + list_bots(); +#endif + + display_botlist_window(); + + return TRUE; +} +/* }}} */ + +/* {{{ command_preferences */ +BC_COMMAND(command_preferences) +{ + display_setup_window(); + + return TRUE; +} +/* }}} */ + +/* {{{ command_disconnect */ +BC_COMMAND(command_disconnect) +{ + disconnect_tab(tab); + + return TRUE; +} +/* }}} */ + +/* {{{ get_command_from_abbrev() */ +/* Returning rules: + * If the given abbreviation is a whole command, that command will be returned + * If there are more commands matching the pattern, and only one of them can be abbreviated, that command will be returned + * If there are multiple commands matching the pattern, and more of them can be abbreviated, nothing is returned + */ +t_command * +get_command_from_abbrev(gchar *abbrev) +{ + t_command *temp, *found_command = NULL; + gchar *a; + + for (temp = internal_command; temp->command_verb; temp++) + { + gboolean found = TRUE; + + if (streq(temp->command_verb, abbrev, FALSE)) + return temp; + if (strlen(abbrev) > strlen(temp->command_verb)) + continue; + for (a = abbrev; *a; a++) + { + if (tolower(*a) != tolower(*(temp->command_verb + (a - abbrev)))) + { + found = FALSE; + break; + } + } + if ((found) && (temp->can_abbrev == TRUE)) + { + if (found_command) + return NULL; + found_command = temp; + } + } + + return found_command; +} +/* }}} */ + +/* {{{ process_commandline() */ +gboolean +process_commandline(gchar *cmdline, t_tab_data *tab) +{ + gchar **wl; + gint wnum; + t_command *this_command; + gboolean want_change = TRUE; + + Context; + + if (wordwrap(cmdline, " \t", &wl, &wnum) != BCE_SUCCESS) + { + feed_error_to_terminal(tab, TRUE, _("Not enough memory!")); + } + + Context; + + if (!wnum) + return TRUE; + + this_command = get_command_from_abbrev(wl[0]); + if (this_command) + { + if (!this_command->can_abbrev && (strlen(wl[0]) != strlen(this_command->command_verb))) + feed_error_to_terminal(tab, TRUE, _("This command cannot be abbreviated!")); + else + { + if (this_command->min_paramnum > wnum - 1) + feed_error_to_terminal(tab, TRUE, _("Not enough parameters!")); + else + want_change = this_command->func(tab, wnum - 1, wl); + } + } + else + feed_error_to_terminal(tab, TRUE, _("Unknown command \"%s\""), wl[0]); + + Context; + + wl_free(&wl, wnum); + + Context; + + return want_change; +} +/* }}} */ + +/* {{{ process_botcommander_script_commands() */ +/* This function processes the messages sent by the botcommander.tcl script. */ +void +process_botcommander_script_commands(t_tab_data *tab, char *string) +{ + /* Here the script command is already in UTF-8 */ + + Context; + + switch (*(string + 2)) + { + case '+': + if (strlen(string) > 4) + { + char *command = (string + 4); + + Context; + if (strcmp(command, "ABILITY") == 0) + { + dprintf(tab->sock, ".botcomm_chanlist\n"); + dprintf(tab->sock, ".botcomm_userlist\n"); + } + else if (strcmp(command, "CHANLIST_START") == 0) + { + tab->chanlist_process = TRUE; + if (tab->actual_channel_list != NULL) + g_list_free(tab->actual_channel_list); + tab->actual_channel_list = NULL; + } + else if (strcmp(command, "CHANLIST_END") == 0) + { + tab->actual_channel_list = g_list_reverse(tab->actual_channel_list); + tab->chanlist_process = FALSE; + update_channel_list(tab); + } + else if ((strncmp(command, "CHAN ", 5) == 0) && (tab->chanlist_process)) + { + t_channel *chan = g_malloc(sizeof(t_channel)); + + chan->active = (*(command + 5) == '1') ? TRUE : FALSE; + chan->name = g_strdup((command + 7)); + chan->properties = NULL; + tab->actual_channel_list = g_list_prepend(tab->actual_channel_list, chan); + } + else if (strcmp(command, "USERLIST_START") == 0) + { + tab->userlist_process = TRUE; + if (tab->actual_user_list != NULL) + g_list_free(tab->actual_user_list); + tab->actual_user_list = NULL; + } + else if (strcmp(command, "USERLIST_END") == 0) + { + tab->actual_user_list = g_list_reverse(tab->actual_user_list); + tab->userlist_process = FALSE; + update_user_list(tab); + } + else if ((strncmp(command, "USER ", 5) == 0) && (tab->userlist_process)) + { + t_user *user = g_malloc(sizeof(t_user)); + + user->name = g_strdup((command + 5)); + tab->actual_user_list = g_list_prepend(tab->actual_user_list, user); + } + else if (strncmp(command, "CHANPROPS_START ", 16) == 0) + { + tab->chanprops_process = g_strdup(command + 16); + tab->chanprops_list_num = 0; + } + else if (strncmp(command, "CHANPROPS_END ", 14) == 0) + { + if (tab->chanprops_process != NULL) + { + g_free(tab->chanprops_process); + tab->chanprops_process = NULL; + } + tab->chanprops_list_num = 0; + } + else if (strncmp(command, "CHANPROP ", 9) == 0) + { + gchar *chan = command + 9; + gchar *property; + + for (property = chan; *property; property++) + if (isspace(*property)) + break; + if (*property) + { + *property = 0; + if (streq(chan, tab->chanprops_process, FALSE)) + { + property++; + for (; *property; property++) + if (!isspace(*property)) + break; + tab->chanprops_list_num++; + update_channel_property(tab, chan, property); + } + } + } +#ifdef DEBUG + else if (config_data.debug) + printf("Unknown script command: %s\n", command); +#endif /* DEBUG */ + Context; + } + break; + case '-': + feed_error_to_terminal(tab, FALSE, "%s", string); + break; + default: + return; + } + + Context; + +#ifdef DEBUG + if (config_data.debug) + { + feed_message_to_terminal(tab, TRUE, string); + printf("%s\n", string); + } +#endif /* DEBUG */ +} +/* }}} */ + diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..19608c8 --- /dev/null +++ b/src/config.c @@ -0,0 +1,611 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * config.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Configuration backend handlers + }}} */ + +/* {{{ Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "defines.h" +#include "typedefs.h" +#include "variables.h" +#include "functions.h" +/* }}} */ + +/* {{{ Defines */ +#define TA_NAME 1 +#define TA_HOST 2 +#define TA_PORT 3 +#define TA_HANDLE 4 +/* }}} */ + +/* {{{ Variables */ +GConfClient *gconf_client; +t_config_data config_data; + +static gboolean gconf_inited = FALSE; +static int internal_value; +/* }}} */ + +/* {{{ set_gconf_values() */ +gboolean +set_gconf_values(GConfClient *client) +{ + int err = 0; + GError *error = NULL; + + error = NULL; + gconf_client_set_float(client, GCONF2_ROOT "/background_saturation", DEFAULT_BACKGROUND_SATURATION, &error); + if (error) err = 1; + + error = NULL; + gconf_client_set_bool(client, GCONF2_ROOT "/change_to_message", DEFAULT_CHANGE_TO_MESSAGE, &error); + if (error) err = 1; + + error = NULL; + gconf_client_set_bool(client, GCONF2_ROOT "/debug", DEFAULT_DEBUG, &error); + if (error) err = 1; + + error = NULL; + gconf_client_set_string(client, GCONF2_ROOT "/default_mode", DEFAULT_DEFAULT_MODE, &error); + if (error) err = 1; + + error = NULL; + gconf_client_set_string(client, GCONF2_ROOT "/sanity", "Needed for gconf sanity check, please don't remove!", &error); + if (error) err = 1; + + error = NULL; + gconf_client_set_bool(client, GCONF2_ROOT "/scroll_on_output", DEFAULT_SCROLL_ON_OUTPUT, &error); + if (error) err = 1; + + error = NULL; + gconf_client_set_bool(client, GCONF2_ROOT "/transparent_background", DEFAULT_TRANSPARENT_BACKGROUND, &error); + if (error) err = 1; + + error = NULL; + gconf_client_set_string(client, GCONF2_ROOT "/vte_font", DEFAULT_VTE_FONT, &error); + if (error) err = 1; + + error = NULL; + gconf_client_set_bool(client, GCONF2_ROOT "/change_to_new_tab", DEFAULT_CHANGE_TO_NEW_TAB, &error); + if (error) err = 1; + + error = NULL; + gconf_client_set_int(client, GCONF2_ROOT "/history_length", DEFAULT_HISTORY_LENGTH, &error); + if (error) err = 1; + + if (err) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("There was an error accessing GConf2: %s"), error->message); + gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); + gtk_dialog_run(GTK_DIALOG(dialog)); + + return FALSE; + } + + return TRUE; +} +/* }}} */ + +/* {{{ gconf_sanity_check_string() */ +gboolean +gconf_sanity_check_string(GConfClient *client, const gchar *key) +{ + gchar *string; + GError *error = NULL; + + string = gconf_client_get_string(client, key, &error); + + if (error) + { + gboolean temp = set_gconf_values(client); + if (temp == FALSE) + return FALSE; + } + + if (!string) + { + gboolean temp = set_gconf_values(client); + if (temp == FALSE) + return FALSE; + } else + g_free(string); + + return TRUE; +} +/* }}} */ + +/* {{{ init_config() */ +gboolean +init_config(void) +{ + GError *error = NULL; + + gconf_client = gconf_client_get_default(); + if (!gconf_sanity_check_string(gconf_client, GCONF2_ROOT "/sanity")) + return FALSE; + gconf_client_add_dir(gconf_client, GCONF2_ROOT, GCONF_CLIENT_PRELOAD_RECURSIVE, &error); + + return TRUE; +} +/* }}} */ + +/* {{{ get_boolean_conf_value() */ +gboolean +get_boolean_conf_value(gchar *key, gboolean *retval) +{ + GError *error = NULL;; + GConfValue *value = NULL; + gchar *full_key; + + if ((full_key = g_malloc(strlen(GCONF2_ROOT) + strlen(key) + 2)) == NULL) + return FALSE; + + memset(full_key, 0, strlen(GCONF2_ROOT) + strlen(key) + 2); + + strcpy(full_key, GCONF2_ROOT); + strcat(full_key, "/"); + strcat(full_key, key); + + value = gconf_client_get(gconf_client, full_key, &error); + if (error && !value) + { + g_free(full_key); + return FALSE; + } + if (value) + { + if (value->type == GCONF_VALUE_BOOL) + { + if (retval) + *retval = gconf_client_get_bool(gconf_client, full_key, &error); + g_free(full_key); + return TRUE; + } + } + return FALSE; +} +/* }}} */ + +/* {{{ get_float_conf_value() */ +gboolean +get_float_conf_value(gchar *key, gfloat *retval) +{ + GError *error = NULL; + GConfValue *value = NULL; + gchar *full_key; + + if ((full_key = g_malloc(strlen(GCONF2_ROOT) + strlen(key) + 2)) == NULL) + return FALSE; + + memset(full_key, 0, strlen(GCONF2_ROOT) + strlen(key) + 2); + + strcpy(full_key, GCONF2_ROOT); + strcat(full_key, "/"); + strcat(full_key, key); + + value = gconf_client_get(gconf_client, full_key, &error); + + if ((error != NULL) || (value == NULL)) { + g_free(full_key); + return FALSE; + } + + if (value) { + if (value->type == GCONF_VALUE_FLOAT) { + if (retval) + *retval = gconf_client_get_float(gconf_client, full_key, &error); + g_free(full_key); + return TRUE; + } + } + g_free(full_key); + return FALSE; +} +/* }}} */ + +/* {{{ get_int_conf_value() */ +gboolean +get_int_conf_value(gchar *key, gint *retval) +{ + GError *error = NULL; + GConfValue *value = NULL; + gchar *full_key; + + if ((full_key = g_malloc(strlen(GCONF2_ROOT) + strlen(key) + 2)) == NULL) + return FALSE; + + memset(full_key, 0, strlen(GCONF2_ROOT) + strlen(key) + 2); + + strcpy(full_key, GCONF2_ROOT); + strcat(full_key, "/"); + strcat(full_key, key); + + value = gconf_client_get(gconf_client, full_key, &error); + + if ((error != NULL) || (value == NULL)) { + g_free(full_key); + return FALSE; + } + + if (value) { + if (value->type == GCONF_VALUE_INT) { + if (retval) + *retval = gconf_client_get_int(gconf_client, full_key, &error); + g_free(full_key); + return TRUE; + } + } + g_free(full_key); + return FALSE; +} +/* }}} */ + +/* {{{ get_string_conf_value() */ +gboolean +get_string_conf_value(gchar *key, gchar **retval) +{ + GError *error = NULL; + GConfValue *value = NULL; + gchar *full_key; + + if ((full_key = g_malloc(strlen(GCONF2_ROOT) + strlen(key) + 2)) == NULL) + return FALSE; + + memset(full_key, 0, strlen(GCONF2_ROOT) + strlen(key) + 2); + + strcpy(full_key, GCONF2_ROOT); + strcat(full_key, "/"); + strcat(full_key, key); + + value = gconf_client_get(gconf_client, full_key, &error); + + if (error || !value) { + g_free(full_key); + return FALSE; + } + + if (value) { + if (value->type == GCONF_VALUE_STRING) { + if (retval) + *retval = g_strdup(gconf_client_get_string(gconf_client, full_key, &error)); + g_free(full_key); + return TRUE; + } + } + g_free(full_key); + return FALSE; +} +/* }}} */ + +/* {{{ set_boolean_conf_value() */ +gboolean +set_boolean_conf_value(gchar *key, gboolean value) +{ + GError *error = NULL; + gchar *full_key; + + if ((full_key = g_malloc(strlen(GCONF2_ROOT) + strlen(key) + 2)) == NULL) + return FALSE; + + memset(full_key, 0, strlen(GCONF2_ROOT) + strlen(key) + 2); + + strcpy(full_key, GCONF2_ROOT); + strcat(full_key, "/"); + strcat(full_key, key); + + gconf_client_set_bool(gconf_client, full_key, value, &error); + if (error) + { + g_free(full_key); + return FALSE; + } + + return TRUE; +} +/* }}} */ + +/* {{{ set_float_conf_value() */ +gboolean +set_float_conf_value(gchar *key, gdouble value) +{ + GError *error = NULL; + gchar *full_key; + + if ((full_key = g_malloc(strlen(GCONF2_ROOT) + strlen(key) + 2)) == NULL) + return FALSE; + + memset(full_key, 0, strlen(GCONF2_ROOT) + strlen(key) + 2); + + strcpy(full_key, GCONF2_ROOT); + strcat(full_key, "/"); + strcat(full_key, key); + + gconf_client_set_float(gconf_client, full_key, value, &error); + if (error) + { + g_free(full_key); + return FALSE; + } + + return TRUE; +} +/* }}} */ + +/* {{{ set_int_conf_value() */ +gboolean +set_int_conf_value(gchar *key, gint value) +{ + GError *error = NULL; + gchar *full_key; + + if ((full_key = g_malloc(strlen(GCONF2_ROOT) + strlen(key) + 2)) == NULL) + return FALSE; + + memset(full_key, 0, strlen(GCONF2_ROOT) + strlen(key) + 2); + + strcpy(full_key, GCONF2_ROOT); + strcat(full_key, "/"); + strcat(full_key, key); + + gconf_client_set_int(gconf_client, full_key, value, &error); + if (error) + { + g_free(full_key); + return FALSE; + } + + return TRUE; +} +/* }}} */ + +/* {{{ set_string_conf_value() */ +gboolean +set_string_conf_value(gchar *key, gchar *value) +{ + GError *error = NULL; + gchar *full_key; + + if ((full_key = g_malloc(strlen(GCONF2_ROOT) + strlen(key) + 2)) == NULL) + return FALSE; + + memset(full_key, 0, strlen(GCONF2_ROOT) + strlen(key) + 2); + + strcpy(full_key, GCONF2_ROOT); + strcat(full_key, "/"); + strcat(full_key, key); + + gconf_client_set_string(gconf_client, full_key, value, &error); + if (error) + { + printf("%s\n", error->message); + g_free(full_key); + return FALSE; + } + + return TRUE; +} +/* }}} */ + +/* {{{ read_config_data() */ +void +read_config_data(void) +{ + gboolean setting_b; + gfloat setting_f; + gchar *setting_s; + gint setting_i; + + if (get_boolean_conf_value("scroll_on_output", &setting_b)) + config_data.scroll_on_output = setting_b; + else + config_data.scroll_on_output = DEFAULT_SCROLL_ON_OUTPUT; + + if (get_boolean_conf_value("change_to_message", &setting_b)) + config_data.change_to_message = setting_b; + else + config_data.change_to_message = DEFAULT_CHANGE_TO_MESSAGE; + +#ifdef DEBUG + if (get_boolean_conf_value("debug", &setting_b)) + config_data.debug = setting_b; + else + config_data.debug = DEFAULT_DEBUG; +#endif /* DEBUG */ + + if (get_boolean_conf_value("transparent_background", &setting_b)) + config_data.transparent_background = setting_b; + else + config_data.transparent_background = DEFAULT_TRANSPARENT_BACKGROUND; + + if (get_float_conf_value("background_saturation", &setting_f)) + config_data.background_saturation = setting_f; + else + config_data.background_saturation = DEFAULT_BACKGROUND_SATURATION; + + if (get_string_conf_value("default_mode", &setting_s)) + config_data.default_mode = *setting_s; + else + config_data.default_mode = *DEFAULT_DEFAULT_MODE; + + if (get_string_conf_value("vte_font", &setting_s)) + config_data.vte_font = setting_s; + else + config_data.vte_font = DEFAULT_VTE_FONT; + + if (get_boolean_conf_value("change_to_new_tab", &setting_b)) + config_data.change_to_new_tab = setting_b; + else + config_data.change_to_new_tab = DEFAULT_CHANGE_TO_NEW_TAB; + + if (get_int_conf_value("history_length", &setting_i)) + config_data.history_len = setting_i; + else + config_data.history_len = DEFAULT_HISTORY_LENGTH; +} +/* }}} */ + +/* {{{ set_bot_data_from_conf() */ +void +set_bot_data_from_conf(gpointer data, gpointer discard) +{ + GConfEntry *entry = (GConfEntry *)data; + gint len = strlen(GCONF2_ROOT "/bots/"); + gchar *key = (char *)gconf_entry_get_key(entry); + gchar *num = NULL; + gchar *i; + gint bot_id; + t_bot_data *bot; + int to_add = 0; + GConfValue *value; + gchar *string_value = NULL; + gint int_value = 0; + + if (strncmp(key + len, "bot", 3)) + return; + num = key + len + 3; + for (i = num; *i && isdigit(*i); i++); + if (*i != '_') + return; + *i = 0; + i++; + bot_id = atoi((const char *)num); + if (bot_id == 0) + return; + if (strcmp(i, "name") == 0) + to_add = TA_NAME; + else if (strcmp(i, "host") == 0) + to_add = TA_HOST; + else if (strcmp(i, "port") == 0) + to_add = TA_PORT; + else if (strcmp(i, "handle") == 0) + to_add = TA_HANDLE; + + if (to_add == 0) + return; + + value = gconf_entry_get_value(entry); + if (to_add == TA_PORT) + int_value = gconf_value_get_int((const GConfValue *)value); + else + string_value = (gchar *)gconf_value_get_string((const GConfValue *)value); + + if ((bot = get_bot_by_conf_num(bot_id)) == NULL) + { + create_bot_record(NULL, 0, &bot); + bot->id = bot_id; + internal_bot_list = g_list_append(internal_bot_list, bot); + } + + switch (to_add) + { + case TA_NAME: + bot->botname = g_strdup(string_value); + break; + case TA_HOST: + bot->host = g_strdup(string_value); + break; + case TA_PORT: + bot->port = int_value; + break; + case TA_HANDLE: + bot->handle = g_strdup(string_value); + break; + } +} +/* }}} */ + +/* {{{ read_bot_list_from_config() */ +void +read_bot_list_from_config(void) +{ + GSList *entries; + + if (internal_bot_list) + { + g_list_foreach(internal_bot_list, free_bot_data, NULL); + g_list_free(internal_bot_list); + internal_bot_list = NULL; + } + entries = gconf_client_all_entries(gconf_client, GCONF2_ROOT "/bots", NULL); + if (entries) + { + g_slist_foreach(entries, set_bot_data_from_conf, NULL); + } +} +/* }}} */ + +/* {{{ save_this_bot() */ +void +save_this_bot(gpointer data, gpointer user_data) +{ + /* NEVER CHANGE THIS, or change the code below, either! */ + static char *config_keynames[] = { "name", "host", "port", "handle", NULL }; + gchar *key; + gint len; + char **a; + + internal_value++; + + for (a = config_keynames; *a; a++) + { + len = (int)log10((double)internal_value) + 11 + strlen(*a); + key = g_malloc(len); + + sprintf(key, "bots/bot%d_%s", internal_value, *a); + + if (strcmp(*a, "name") == 0) + set_string_conf_value(key, ((t_bot_data *)data)->botname); + else if (strcmp(*a, "host") == 0) + set_string_conf_value(key, ((t_bot_data *)data)->host); + else if (strcmp(*a, "port") == 0) + set_int_conf_value(key, ((t_bot_data *)data)->port); + else if (strcmp(*a, "handle") == 0) + set_string_conf_value(key, ((t_bot_data *)data)->handle); + g_free(key); + } +} +/* }}} */ + +/* {{{ save_bot_list_to_config() */ +void +save_bot_list_to_config(void) +{ + gconf_client_recursive_unset(gconf_client, GCONF2_ROOT "/bots", GCONF_UNSET_INCLUDING_SCHEMA_NAMES, NULL); + + internal_value = 0; + g_list_foreach(internal_bot_list, save_this_bot, NULL); +} +/* }}} */ + diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000..5132f4b --- /dev/null +++ b/src/debug.c @@ -0,0 +1,69 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * debug.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Debugging functions + }}} */ + +#ifdef DEBUG + +/* {{{ Includes */ +# include +# include +# include +/* }}} */ + +/* {{{ Variables */ +char *last_file = NULL; +int last_line = 0; +/* }}} */ + +/* {{{ fatal_signal() */ +void fatal_signal_handler(int sig) +{ + if (last_file) + fprintf(stderr, "Fatal signal cought (%d). Last context was at %s:%d\n", sig, last_file, last_line); + exit(1); +} +/* }}} */ + +/* {{{ debug_init() */ +void +debug_init() +{ + signal(SIGSEGV, fatal_signal_handler); +} +/* }}} */ + +/* {{{ set_context() */ +void +set_context(char *file, int line) +{ + if (last_file) + g_free(last_file); + last_file = g_strdup(file); + last_line = line; +} +/* }}} */ + +#endif + diff --git a/src/history.c b/src/history.c new file mode 100644 index 0000000..a8fb366 --- /dev/null +++ b/src/history.c @@ -0,0 +1,123 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * history.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Handles tabs' command line history + }}} */ + +/* {{{ Includes */ +#include +#include +#include + +#include "typedefs.h" +#include "variables.h" +/* }}} */ + +/* {{{ history_add() */ +void +history_add(t_tab_data *tab, gchar mode, gchar *line) +{ + t_history_data *temp; + + if (config_data.history_len == 0) + return; + + if (tab) + { + gint count = 0; + char modechar = 0; + + switch (tolower(mode)) + { + case 'b': + modechar = '/'; + break; + case 'e': + modechar = '.'; + break; + case 'm': + modechar = '@'; + break; + } + + if (modechar == 0) + return; + + temp = tab->history; + while (temp) + { + count++; + temp = temp->next; + } + + if (count == config_data.history_len) + { + temp = tab->history; + tab->history = temp->next; + g_free(temp->line); + g_free(temp); + } + + temp = g_malloc(sizeof(t_history_data)); + temp->line = g_malloc(strlen(line) + 2); + sprintf(temp->line, "%c%s", modechar, line); + temp->next = NULL; + + if (tab->history == NULL) + tab->history = temp; + else + { + t_history_data *t = tab->history; + while (t->next) + t = t->next; + t->next = temp; + } + } +} +/* }}} */ + +/* {{{ get_history_len() */ +gint +get_history_len(t_tab_data *tab) +{ + + if (tab) + { + t_history_data *temp = tab->history; + gint count = 0; + + if (tab->history == NULL) + return 0; + while (temp) + { + count++; + temp = temp->next; + } + + return count; + } + + return 0; +} +/* }}} */ + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..424cd1d --- /dev/null +++ b/src/main.c @@ -0,0 +1,143 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * main.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Very common functions + }}} */ + +/* {{{ Includes */ +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#include "functions.h" +#include "variables.h" +#include "defines.h" +/* }}} */ + +/* {{{ change_mode() */ +void +change_mode(char newmode, gboolean from_menu) +{ + char *buf; + + t_tab_data *active_tab = get_active_tab(); + + buf = g_malloc(strlen(_("Mode: %c")) + 1); + sprintf(buf, _("Mode: %c"), toupper(newmode)); + + active_tab->mode = toupper(newmode); + gtk_label_set_text(GTK_LABEL(main_statuslabel_mode), buf); + g_free(buf); + + if (!from_menu) + { + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(main_menu_mode_b), (toupper(newmode) == 'B') ? TRUE : FALSE); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(main_menu_mode_e), (toupper(newmode) == 'E') ? TRUE : FALSE); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(main_menu_mode_m), (toupper(newmode) == 'M') ? TRUE : FALSE); + } +} +/* }}} */ + +/* {{{ find_connected_tab() */ +gint +find_connected_tab(gconstpointer a, gconstpointer b) +{ + if (((t_tab_data *)a)->connected) + return 0; + + return 1; +} +/* }}} */ + +/* {{{ exit_cleanly() */ +void +exit_cleanly(gboolean force) +{ + gboolean ask = FALSE; + + save_bot_list_to_config(); + + if (g_list_find_custom(tab_list, NULL, find_connected_tab)) + ask = TRUE; + + if (ask) + { + GtkWidget *dialog; + gint result; + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("There are connected tabs. Are you sure, you want to exit?")); + result = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + if (result == GTK_RESPONSE_NO) + return; + } + +#ifdef DEBUG + printf("exit_cleanly(%d)\n", force); +#endif /* DEBUG */ + gtk_main_quit(); +} +/* }}} */ + +/* {{{ main() */ +int +main(int argc, char **argv) +{ +#ifdef DEBUG + debug_init(); +#endif /* DEBUG */ + + Context; + setlocale(LC_ALL, ""); + bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); + textdomain(GETTEXT_PACKAGE); + + Context; + + gtk_init(&argc, &argv); + + if (!init_config()) + return 1; + + read_config_data(); + read_bot_list_from_config(); + + tab_list = NULL; + + g_set_prgname("BotCommander"); + g_set_application_name("BotCommander"); + + create_main_window(); + + add_tab(NULL); + + gtk_main(); + return 0; +} +/* }}} */ + diff --git a/src/networking.c b/src/networking.c new file mode 100644 index 0000000..4acb31b --- /dev/null +++ b/src/networking.c @@ -0,0 +1,116 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * networking.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Network-handling functions + }}} */ + +/* {{{ Includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#include "defines.h" +#include "typedefs.h" +#include "functions.h" +#include "variables.h" +/* }}} */ + +/* {{{ connect_to_host() */ +gint +connect_to_host(gchar *host, guint port, int *fd, gint *tag, t_tab_data *tab) +{ + int desc; + static struct protoent *p = NULL; + struct hostent *h = NULL; + struct sockaddr_in dest; + + if (tab) + feed_info_to_terminal(tab, TRUE, _("Connecting to %s:%d"), host, port); + + if (!p) + { + if ((p = getprotobyname("IP")) == NULL) + return BCE_NOPROTO; + } + desc = socket(PF_INET, SOCK_STREAM, p->p_proto); + fcntl(desc, F_SETFL, O_NONBLOCK); + + if ((h = gethostbyname(host)) == NULL) + return BCE_CANTRESOLV; + + memset(&dest, 0, sizeof(struct sockaddr_in)); + dest.sin_family = AF_INET; + dest.sin_addr = *((struct in_addr *)h->h_addr); + dest.sin_port = htons(port); + + if (connect(desc, (struct sockaddr *)&dest, sizeof(struct sockaddr)) < 0) + { + if (errno != EINPROGRESS) + { + if (tab) + { + char *buf = NULL; + char *orig = strerror(errno); + + buf = g_locale_to_utf8(orig, -1, NULL, NULL, NULL); + feed_error_to_terminal(tab, TRUE, "%s", buf); + g_free(buf); + } +#ifdef DEBUG + perror("BotCommander: connect"); +#endif /* DEBUG */ + return BCE_CANTCONNECT; + } + } + + if (fd) + *fd = desc; + if (tag) + *tag = gdk_input_add(desc, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, socket_event, tab); + + return BCE_SUCCESS; +} +/* }}} */ + +/* {{{ process_incoming_data() */ +void +process_incoming_data(t_tab_data *tab, char *string) +{ + char *obuf; + + obuf = g_convert(string, -1, "UTF-8", BOT_CHARSET, NULL, NULL, NULL); + if (strncmp(obuf, "BC", 2) == 0) + process_botcommander_script_commands(tab, obuf); + else + feed_message_to_terminal(tab, TRUE, obuf); +} +/* }}} */ + diff --git a/src/setup.c b/src/setup.c new file mode 100644 index 0000000..bda28d8 --- /dev/null +++ b/src/setup.c @@ -0,0 +1,366 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * setup.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Preferences dialog + }}} */ + +/* {{{ Defines */ +#define CB_ALL 0 +#define CB_SCROLL 1 +#define CB_TRANSBG 2 +#define CB_BGSAT 3 +#define CB_FONT 4 +#define CB_RESET 5 +/* }}} */ + +/* {{{ Includes */ +#include +#include +#include +#include + +#include "variables.h" +#include "functions.h" +/* }}} */ + +/* {{{ Typedefs */ +typedef struct _t_which { + gint which; + gboolean bool_value; + gfloat float_value; + gchar *string_value; +} t_which; +/* }}} */ + +/* {{{ Variables */ +#ifdef DEBUG +GtkWidget *debug_cb; +#endif /* DEBUG */ +GtkWidget *cmode_cb; +GtkWidget *prefsave_cb; +GtkWidget *scroll_cb; +GtkWidget *transbg_cb; +GtkWidget *font_button; +GtkWidget *historylen_spin; +GtkWidget *satur_scale; +GtkWidget *changetab_cb; +t_config_data backup_data; +/* }}} */ + +/* {{{ debug_cb_toggled() */ +#ifdef DEBUG +static void +debug_cb_toggled(GtkWidget *widget, gpointer data) +{ + backup_data.debug = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} +#endif /* DEBUG */ +/* }}} */ + +/* {{{ cmode_cb_toggled() */ +static void +cmode_cb_toggled(GtkWidget *widget, gpointer data) +{ + backup_data.change_to_message = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} +/* }}} */ + +/* {{{ prefsave_cb_toggled() */ +static void +prefsave_cb_toggled(GtkWidget *widget, gpointer data) +{ + backup_data.save_prefs = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} +/* }}} */ + +/* {{{ changetab_cb_toggled() */ +static void +changetab_cb_toggled(GtkWidget *widget, gpointer data) +{ + backup_data.change_to_new_tab = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} +/* }}} */ + +/* {{{ set_tab_vt_prefs() */ +static void +set_tab_vt_prefs(gpointer data, gpointer user_data) +{ + t_tab_data *tab = (t_tab_data *)data; + t_which *which = (t_which *)user_data; + + if ((which->which == CB_SCROLL) || (which->which == CB_ALL)) + vte_terminal_set_scroll_on_output(VTE_TERMINAL(tab->vt), which->bool_value); + if ((which->which == CB_TRANSBG) || (which->which == CB_ALL)) + vte_terminal_set_background_transparent(VTE_TERMINAL(tab->vt), which->bool_value); + if ((which->which == CB_BGSAT) || (which->which == CB_ALL)) + vte_terminal_set_background_saturation(VTE_TERMINAL(tab->vt), which->float_value / 100.0); + if ((which->which == CB_FONT) || (which->which == CB_ALL)) + vte_terminal_set_font_from_string(VTE_TERMINAL(tab->vt), which->string_value); + if (which->which == CB_RESET) + { + vte_terminal_set_scroll_on_output(VTE_TERMINAL(tab->vt), config_data.scroll_on_output); + vte_terminal_set_background_transparent(VTE_TERMINAL(tab->vt), config_data.transparent_background); + vte_terminal_set_background_saturation(VTE_TERMINAL(tab->vt), config_data.background_saturation); + vte_terminal_set_font_from_string(VTE_TERMINAL(tab->vt), config_data.vte_font); + } +} +/* }}} */ + +/* {{{ scroll_cb_toggled() */ +static void +scroll_cb_toggled(GtkWidget *widget, gpointer data) +{ + t_which which; + + backup_data.scroll_on_output = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + + which.which = CB_SCROLL; + which.bool_value = backup_data.scroll_on_output; + + g_list_foreach(tab_list, set_tab_vt_prefs, &which); +} +/* }}} */ + +/* {{{ transbg_cb_toggled() */ +static void +transbg_cb_toggled(GtkWidget *widget, gpointer data) +{ + t_which which; + + backup_data.transparent_background = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + + which.which = CB_TRANSBG; + which.bool_value = backup_data.transparent_background; + + g_list_foreach(tab_list, set_tab_vt_prefs, &which); +} +/* }}} */ + +/* {{{ satur_bar_changed() */ +static void +satur_bar_changed(GtkWidget *widget, gpointer data) +{ + t_which which; + + backup_data.background_saturation = gtk_range_get_value(GTK_RANGE(widget)); + + which.which = CB_BGSAT; + which.float_value = backup_data.background_saturation; + + g_list_foreach(tab_list, set_tab_vt_prefs, &which); +} +/* }}} */ + +/* {{{ historylen_spin_changed() */ +static void +historylen_spin_changed(GtkWidget *widget, gpointer data) +{ + backup_data.history_len = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); +} +/* }}} */ + +/* {{{ font_changed() */ +static void +font_changed(GtkWidget *widget, gpointer data) +{ + t_which which; + + if (backup_data.vte_font) + g_free(backup_data.vte_font); + backup_data.vte_font = g_strdup(gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget))); + + which.which = CB_FONT; + which.string_value = backup_data.vte_font; + + g_list_foreach(tab_list, set_tab_vt_prefs, &which); +} +/* }}} */ + +/* {{{ setup_response() */ +static void +setup_response(GtkDialog *dialog, int id, gpointer data) +{ + switch (id) + { + case GTK_RESPONSE_OK: + g_free(config_data.vte_font); + memcpy(&config_data, &backup_data, sizeof(t_config_data)); + config_data.vte_font = g_strdup(backup_data.vte_font); + /* TODO: Change the command line history buffer's size!! */ + gtk_widget_hide(GTK_WIDGET(dialog)); + break; + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_DELETE_EVENT: + { + t_which which; + + which.which = CB_RESET; + g_list_foreach(tab_list, set_tab_vt_prefs, &which); + gtk_widget_hide(GTK_WIDGET(dialog)); + } + break; + case GTK_RESPONSE_YES: + /* Itt minden pref beallitast el kell menteni az aktualis backendbe */ + break; + default: +#ifdef DEBUG + if (config_data.debug) + fprintf(stderr, "Unknown response!\n"); +#endif /* DEBUG */ + break; + } +} +/* }}} */ + +/* {{{ display_setup_window() */ +void +display_setup_window(void) +{ + static GtkWidget *setup_window = NULL; + + memcpy(&backup_data, &config_data, sizeof(t_config_data)); + backup_data.vte_font = g_strdup(config_data.vte_font); + + if (!GTK_IS_WINDOW(setup_window)) + { + GtkWidget *frame; + GtkWidget *content; + GtkWidget *satur_label; + GtkWidget *font_label; + GtkWidget *historylen_label; + gint row; +#ifdef DEBUG +# define CONTENT_ROW_NUMBER 5 +#else +# define CONTENT_ROW_NUMBER 4 +#endif + + setup_window = gtk_dialog_new_with_buttons((const gchar *)_("Setup"), GTK_WINDOW(main_window), GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_SAVE, GTK_RESPONSE_YES, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); + gtk_dialog_set_response_sensitive(GTK_DIALOG(setup_window), GTK_RESPONSE_OK, TRUE); + + gtk_signal_connect(GTK_OBJECT(setup_window), "response", GTK_SIGNAL_FUNC(setup_response), NULL); + + frame = gtk_frame_new("BotCommander"); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); + + content = gtk_table_new(CONTENT_ROW_NUMBER, 2, TRUE); + + row = 0; +#ifdef DEBUG + debug_cb = gtk_check_button_new_with_label(_("Debug mode")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(debug_cb), config_data.debug); + gtk_table_attach_defaults(GTK_TABLE(content), debug_cb, 0, 2, row, row + 1); + gtk_signal_connect(GTK_OBJECT(debug_cb), "toggled", GTK_SIGNAL_FUNC(debug_cb_toggled), NULL); + row++; +#endif + + cmode_cb = gtk_check_button_new_with_label(_("Change to message mode after connect")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cmode_cb), config_data.change_to_message); + gtk_table_attach_defaults(GTK_TABLE(content), cmode_cb, 0, 2, row, row + 1); + gtk_signal_connect(GTK_OBJECT(cmode_cb), "toggled", GTK_SIGNAL_FUNC(cmode_cb_toggled), NULL); + row++; + + changetab_cb = gtk_check_button_new_with_label(_("Change to newly created tab")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(changetab_cb), config_data.change_to_new_tab); + gtk_table_attach_defaults(GTK_TABLE(content), changetab_cb, 0, 2, row, row + 1); + gtk_signal_connect(GTK_OBJECT(changetab_cb), "toggled", GTK_SIGNAL_FUNC(changetab_cb_toggled), NULL); + row++; + + prefsave_cb = gtk_check_button_new_with_label(_("Save preferences on exit")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(prefsave_cb), config_data.save_prefs); + gtk_table_attach_defaults(GTK_TABLE(content), prefsave_cb, 0, 2, row, row + 1); + gtk_signal_connect(GTK_OBJECT(prefsave_cb), "toggled", GTK_SIGNAL_FUNC(prefsave_cb_toggled), NULL); + row++; + + historylen_label = gtk_label_new(_("Command line history length")); + gtk_table_attach(GTK_TABLE(content), historylen_label, 0, 1, row, row + 1, GTK_FILL, 0, 4, 0); + + historylen_spin = gtk_spin_button_new_with_range(0, 5000, 1); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(historylen_spin), config_data.history_len); + gtk_table_attach_defaults(GTK_TABLE(content), historylen_spin, 1, 2, row, row + 1); + gtk_signal_connect(GTK_OBJECT(historylen_spin), "value-changed", GTK_SIGNAL_FUNC(historylen_spin_changed), NULL); + row++; + + gtk_container_add(GTK_CONTAINER(frame), content); + + gtk_widget_show_all(frame); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(setup_window)->vbox), frame, TRUE, TRUE, 0); + + frame = gtk_frame_new(_("Terminal")); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); + + content = gtk_table_new(5, 3, TRUE); + + scroll_cb = gtk_check_button_new_with_label(_("Scroll on output")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(scroll_cb), config_data.scroll_on_output); + gtk_table_attach_defaults(GTK_TABLE(content), scroll_cb, 0, 3, 0, 1); + gtk_signal_connect(GTK_OBJECT(scroll_cb), "toggled", GTK_SIGNAL_FUNC(scroll_cb_toggled), NULL); + + transbg_cb = gtk_check_button_new_with_label(_("Transparent background")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(transbg_cb), config_data.transparent_background); + gtk_table_attach_defaults(GTK_TABLE(content), transbg_cb, 0, 3, 1, 2); + gtk_signal_connect(GTK_OBJECT(transbg_cb), "toggled", GTK_SIGNAL_FUNC(transbg_cb_toggled), NULL); + + satur_label = gtk_label_new(_("Saturation")); + gtk_table_attach(GTK_TABLE(content), satur_label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0); + + satur_scale = gtk_hscale_new_with_range(0, 100, 1); + gtk_scale_set_digits(GTK_SCALE(satur_scale), 0); + gtk_scale_set_draw_value(GTK_SCALE(satur_scale), TRUE); + gtk_scale_set_value_pos(GTK_SCALE(satur_scale), GTK_POS_RIGHT); + gtk_range_set_value(GTK_RANGE(satur_scale), config_data.background_saturation * 100); + gtk_signal_connect(GTK_OBJECT(satur_scale), "value-changed", GTK_SIGNAL_FUNC(satur_bar_changed), NULL); + gtk_table_attach_defaults(GTK_TABLE(content), satur_scale, 0, 3, 3, 4); + + font_label = gtk_label_new(_("Font")); + gtk_table_attach(GTK_TABLE(content), font_label, 0, 1, 4, 5, GTK_FILL, 0, 0, 0); + + font_button = gtk_font_button_new_with_font(config_data.vte_font); + gtk_table_attach_defaults(GTK_TABLE(content), font_button, 1, 3, 4, 5); + gtk_signal_connect(GTK_OBJECT(font_button), "font-set", GTK_SIGNAL_FUNC(font_changed), NULL); + + gtk_container_add(GTK_CONTAINER(frame), content); + + gtk_widget_show_all(frame); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(setup_window)->vbox), frame, TRUE, TRUE, 0); + } + else + { +#ifdef DEBUG + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(debug_cb), config_data.debug); +#endif /* DEBUG */ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cmode_cb), config_data.change_to_message); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(prefsave_cb), config_data.save_prefs); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(scroll_cb), config_data.scroll_on_output); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(transbg_cb), config_data.transparent_background); + gtk_font_button_set_font_name(GTK_FONT_BUTTON(font_button), config_data.vte_font); + gtk_range_set_value(GTK_RANGE(satur_scale), config_data.background_saturation * 100); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(historylen_spin), config_data.history_len); + } + + gtk_dialog_run(GTK_DIALOG(setup_window)); +} +/* }}} */ + diff --git a/src/string.c b/src/string.c new file mode 100644 index 0000000..b97aaad --- /dev/null +++ b/src/string.c @@ -0,0 +1,244 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ Author and file info + * string.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * String manipulation functions + }}} */ + +/* TODO: Insert this into one of the makefiles, perhaps in rules? */ +#define _GNU_SOURCE +/* {{{ Includes */ +#include +#include +#include +#include +#include +#include +#include + +#include "defines.h" +/* }}} */ + +/* {{{ streq() */ +gboolean +streq(gchar *s1, gchar *s2, gboolean cs) +{ + gchar *a; + + if (!s1 && !s2) + return TRUE; + if (!s1 || !s2) + return FALSE; + if (strlen(s1) != strlen(s2)) + return FALSE; + if (cs) + return strcmp(s1, s2) == 0 ? TRUE : FALSE; + for (a = s1; *a; a++) + if (tolower(*a) != tolower(*(s2 + (a - s1)))) + return FALSE; + + return TRUE; +} +/* }}} */ + +/* {{{ wordwrap() */ +int +wordwrap(gchar *sentence, gchar *delim, gchar ***retval, gint *wnum) +{ + gboolean prev_delim = TRUE; + gchar *a; + gint words = 0; + gchar **starts; + gchar **newstarts; + gint *lens; + signed int cword = -1; + int i; + + for (a = sentence; *a; a++) + { + gboolean is_delim = (strchr(delim, *a)) ? TRUE : FALSE; + + if (!is_delim && prev_delim) + words++; + prev_delim = is_delim; + } + + if (wnum) + *wnum = words; + + if (words == 0) + { + if (retval) + *retval = NULL; + return BCE_SUCCESS; + } + + if (!retval) + return BCE_SUCCESS; + + if ((starts = (gchar **)g_malloc(sizeof(gchar *))) == NULL) + return BCE_NOMEM; + if ((lens = (gint *)g_malloc(sizeof(gint))) == NULL) + { + g_free(starts); + return BCE_NOMEM; + } + if ((newstarts = (gchar **)g_malloc(sizeof(gchar *))) == NULL) + { + g_free(starts); + g_free(lens); + return BCE_NOMEM; + } + + prev_delim = TRUE; + + for (a = sentence; *a; a++) + { + gboolean is_delim = (strchr(delim, *a)) ? TRUE : FALSE; + + if (!is_delim) + { + if (prev_delim) + { + cword++; + starts[cword] = a; + lens[cword] = 0; + } + else + lens[cword]++; + } + prev_delim = is_delim; + } + + for (i = 0; i < words; i++) + { + if ((newstarts[i] = g_malloc((sizeof(gchar) * (lens[i] + 2)))) == NULL) + { + int j; + + for (j = 0; j < i; j++) + g_free(newstarts[i]); + g_free(starts); + g_free(lens); + g_free(newstarts); + return BCE_NOMEM; + } + memset(newstarts[i], 0, (sizeof(gchar) * (lens[i] + 2))); + strncpy(newstarts[i], starts[i], lens[i] + 1); + } + g_free(lens); + g_free(starts); + + *retval = newstarts; + + return BCE_SUCCESS; +} +/* }}} */ + +/* {{{ wl_free() */ +void +wl_free(gchar ***owl, gint wnum) +{ + gint i; + + if (*owl) + { + for (i = 0; i < wnum; i++) + g_free((*owl)[i]); + g_free(*owl); + } +} +/* }}} */ + +/* {{{ is_numeric() */ +gboolean +is_numeric(gchar *s, gint *retval) +{ + gchar *a; + + if (!s) + return FALSE; + for (a = s; *a; a++) + if (!isdigit(*a)) + return FALSE; + + if (retval) + *retval = atoi(s); + + return TRUE; +} +/* }}} */ + +/* {{{ trim() */ +gchar * +trim(gchar *s) +{ + gchar *start; + gchar *end; + gchar *ret; + + if (s == NULL) + return NULL; + if (*s == 0) + return ""; + + for (start = s; *start; start++) + if (!isspace(*start)) + break; + + if (!*start) + return ""; + + for (end = s + strlen(s) - 1; end >= s; end--) + if (!isspace(*end)) + break; + + ret = g_malloc((end - start) + 2); + memset(ret, 0, (end - start) + 2); + strncpy(ret, start, (end - start) + 1); + + return ret; +} +/* }}} */ + +// Under FreeBSD, dprintf doesn't exist :( +#ifndef dprintf +/* {{{ dprintf() */ +int +dprintf(int fd, const char *format, ...) +{ + va_list ap; + char *buf; + int len; + + va_start(ap, format); + vasprintf(&buf, format, ap); + len = strlen(buf); + write(fd, buf, len); + g_free(buf); + va_end(ap); + + return len; +} +/* }}} */ +#endif + diff --git a/src/tabs.c b/src/tabs.c new file mode 100644 index 0000000..c0a8b95 --- /dev/null +++ b/src/tabs.c @@ -0,0 +1,677 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ + * tabs.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Tab handling functions + }}} */ + +/* TODO: Put this into a Makefile */ +#define _GNU_SOURCE + +/* {{{ Includes */ +#include +#include +#include +#include +#include +#include +#include + +#include "typedefs.h" +#include "variables.h" +#include "functions.h" +#include "defines.h" +/* }}} */ + +/* {{{ Variables */ +GList *tab_list; +/* }}} */ + +/* {{{ find_tab_by_pagenum() */ +gint +find_tab_by_pagenum(gconstpointer a, gconstpointer b) +{ + if (((t_tab_data *)a)->num == (gint)*((gint *)b)) + return 0; + + return 1; +} +/* }}} */ + +/* {{{ open_channel_properties() */ +void +open_channel_properties(GtkWidget *menuitem, gpointer data) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + t_tab_data *tab = (t_tab_data *)data; + GtkTreeIter iter; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tab->channel_list)); + model = gtk_tree_view_get_model(GTK_TREE_VIEW(tab->channel_list)); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + char *name; + + gtk_tree_model_get(model, &iter, 0, &name, -1); + dprintf(tab->sock, ".botcomm_chanprop %s\r\n", name); + } +} +/* }}} */ + +/* {{{ open_user_properties() */ +void +open_user_properties(GtkWidget *menuitem, gpointer data) +{ +} +/* }}} */ + +/* {{{ change_channel_status() */ +void +change_channel_status(GtkWidget *menuitem, gpointer data) +{ +} +/* }}} */ + +/* {{{ view_channel_popup() */ +void +view_channel_popup(GtkWidget *treeview, GdkEventButton *event, gpointer tab) +{ + GtkWidget *menu = NULL; + GtkWidget *menuitem; + + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(((t_tab_data *)tab)->channel_list)); + model = gtk_tree_view_get_model(GTK_TREE_VIEW(((t_tab_data *)tab)->channel_list)); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + menu = gtk_menu_new(); + + // TODO: If the channel is active, the label should say Deactivate + menuitem = gtk_menu_item_new_with_label(_("Activate")); + g_signal_connect(menuitem, "activate", G_CALLBACK(change_channel_status), tab); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + + menuitem = gtk_menu_item_new_with_label(_("Properties")); + g_signal_connect(menuitem, "activate", G_CALLBACK(open_channel_properties), tab); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + + gtk_widget_show_all(menu); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent *)event)); + } +} +/* }}} */ + +/* {{{ view_user_popup() */ +void +view_user_popup(GtkWidget *treeview, GdkEventButton *event, gpointer tab) +{ + GtkWidget *menu; + GtkWidget *menuitem; + + menu = gtk_menu_new(); + + menuitem = gtk_menu_item_new_with_label(_("Properties")); + g_signal_connect(menuitem, "activate", G_CALLBACK(open_user_properties), tab); + + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + + gtk_widget_show_all(menu); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent *)event)); +} +/* }}} */ + +/* {{{ view_terminal_popup() */ +void +view_terminal_popup(GtkWidget *terminal, GdkEventButton *event, gpointer tab) +{ + GtkWidget *menu; + GtkWidget *menuitem; + + menu = gtk_menu_new(); + + menuitem = gtk_menu_item_new_with_label(_("Properties")); + g_signal_connect(menuitem, "activate", G_CALLBACK(open_user_properties), tab); + + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + + gtk_widget_show_all(menu); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent *)event)); +} +/* }}} */ + +/* {{{ channel_popupmenu_button() */ +gboolean +channel_popupmenu_button(GtkWidget *treeview, GdkEventButton *event, gpointer userdata) +{ + if ((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) + { + GtkTreeSelection *selection; + GtkTreePath *path; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); + if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview), (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL)) + { + gtk_tree_selection_unselect_all(selection); + gtk_tree_selection_select_path(selection, path); + gtk_tree_path_free(path); + } + else + return FALSE; + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); + if (gtk_tree_selection_count_selected_rows(selection) > 0) + view_channel_popup(treeview, event, userdata); + + return TRUE; + } + + return FALSE; +} +/* }}} */ + +/* {{{ user_popupmenu_button() */ +gboolean +user_popupmenu_button(GtkWidget *treeview, GdkEventButton *event, gpointer userdata) +{ + if ((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) + { + GtkTreeSelection *selection; + GtkTreePath *path; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); + if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview), (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL)) + { + gtk_tree_selection_unselect_all(selection); + gtk_tree_selection_select_path(selection, path); + gtk_tree_path_free(path); + } + else + return FALSE; + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); + if (gtk_tree_selection_count_selected_rows(selection) > 0) + view_user_popup(treeview, event, userdata); + + return TRUE; + } + + return FALSE; +} +/* }}} */ + +/* {{{ terminal_popupmenu_button() */ +gboolean +terminal_popupmenu_button(GtkWidget *terminal, GdkEventButton *event, gpointer userdata) +{ + if ((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) + { + view_terminal_popup(terminal, event, userdata); + + return TRUE; + } + + return FALSE; +} +/* }}} */ + +/* {{{ channel_popupmenu_popup() */ +gboolean +channel_popupmenu_popup(GtkWidget *treeview, gpointer userdata) +{ + view_channel_popup(treeview, NULL, userdata); + + return TRUE; +} +/* }}} */ + +/* {{{ user_popupmenu_popup() */ +gboolean +user_popupmenu_popup(GtkWidget *treeview, gpointer userdata) +{ + view_user_popup(treeview, NULL, userdata); + + return TRUE; +} +/* }}} */ + +/* {{{ terminal_popupmenu_popup() */ +gboolean +terminal_popupmenu_popup(GtkWidget *terminal, gpointer userdata) +{ + view_terminal_popup(terminal, NULL, userdata); + + return TRUE; +} +/* }}} */ + +/* {{{ add_tab() */ +int +add_tab(t_tab_data **newtab) +{ + t_tab_data *temp; + GtkWidget *img; + gint w, h; + gboolean change_title = config_data.change_to_new_tab, + first_tab = FALSE; + char *buf; + GtkWidget *paned; + GtkWidget *scroll; + GtkWidget *box; + t_tab_data *active; + GtkWidget *hbox; + + GtkCellRenderer *renderer; + + if (newtab) + *newtab = NULL; + + if (tab_list == NULL) + { + change_title = TRUE; + first_tab = TRUE; + } + + temp = (t_tab_data *)malloc(sizeof(t_tab_data)); + + temp->mode = config_data.default_mode; + temp->connected = FALSE; + temp->history = NULL; + temp->history_position = -1; + temp->chanlist_process = FALSE; + temp->userlist_process = FALSE; + temp->chanprops_process = NULL; + temp->actual_channel_list = NULL; + temp->actual_user_list = NULL; + temp->data_arrived = FALSE; + + paned = gtk_hpaned_new(); + + hbox = gtk_hbox_new(FALSE, 0); + temp->vt = vte_terminal_new(); + vte_terminal_set_encoding(VTE_TERMINAL(temp->vt), "UTF-8"); + vte_terminal_set_allow_bold(VTE_TERMINAL(temp->vt), TRUE); + vte_terminal_set_audible_bell(VTE_TERMINAL(temp->vt), TRUE); + vte_terminal_set_visible_bell(VTE_TERMINAL(temp->vt), FALSE); + vte_terminal_set_scroll_on_output(VTE_TERMINAL(temp->vt), config_data.scroll_on_output); + vte_terminal_set_background_transparent(VTE_TERMINAL(temp->vt), config_data.transparent_background); + vte_terminal_set_background_saturation(VTE_TERMINAL(temp->vt), (double)config_data.background_saturation); + vte_terminal_set_font_from_string(VTE_TERMINAL(temp->vt), (const char *)config_data.vte_font); + GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(temp->vt), GTK_CAN_FOCUS); + g_signal_connect(temp->vt, "button-press-event", G_CALLBACK(terminal_popupmenu_button), temp); + g_signal_connect(temp->vt, "popup-menu", G_CALLBACK(terminal_popupmenu_popup), temp); + gtk_box_pack_start(GTK_BOX(hbox), temp->vt, TRUE, TRUE, 0); + + scroll = gtk_vscrollbar_new(vte_terminal_get_adjustment(VTE_TERMINAL(temp->vt))); + gtk_box_pack_start(GTK_BOX(hbox), scroll, FALSE, TRUE, 0); + + box = gtk_vbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 0); + + temp->editbox = gtk_entry_new(); + gtk_signal_connect(GTK_OBJECT(temp->editbox), "activate", GTK_SIGNAL_FUNC(entry_activate), temp); + gtk_signal_connect(GTK_OBJECT(temp->editbox), "key_press_event", GTK_SIGNAL_FUNC(entry_keypress), temp); + gtk_box_pack_start(GTK_BOX(box), temp->editbox, FALSE, TRUE, 0); + + gtk_paned_add1(GTK_PANED(paned), box); + + box = gtk_vbox_new(TRUE, 2); + + Context; + scroll = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_set_size_request(scroll, 150, -1); + gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0); + + temp->channel_store = gtk_list_store_new(1, G_TYPE_STRING); + renderer = gtk_cell_renderer_text_new(); + temp->channel_list = gtk_tree_view_new(); + g_signal_connect(temp->channel_list, "button-press-event", G_CALLBACK(channel_popupmenu_button), temp); + g_signal_connect(temp->channel_list, "popup-menu", G_CALLBACK(channel_popupmenu_popup), temp); + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(temp->channel_list), -1, _("Channels"), renderer, "text", 0, NULL); + gtk_tree_view_set_model(GTK_TREE_VIEW(temp->channel_list), GTK_TREE_MODEL(temp->channel_store)); + gtk_container_add(GTK_CONTAINER(scroll), temp->channel_list); + + Context; + scroll = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_set_size_request(scroll, 150, -1); + gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0); + + renderer = gtk_cell_renderer_text_new(); + temp->user_store = gtk_list_store_new(1, G_TYPE_STRING); + temp->user_list = gtk_tree_view_new(); + g_signal_connect(temp->user_list, "button-press-event", G_CALLBACK(user_popupmenu_button), temp); + g_signal_connect(temp->user_list, "popup-menu", G_CALLBACK(user_popupmenu_popup), temp); + gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(temp->user_list), -1, _("Handles"), renderer, "text", 0, NULL); + gtk_tree_view_set_model(GTK_TREE_VIEW(temp->user_list), GTK_TREE_MODEL(temp->user_store)); + gtk_container_add(GTK_CONTAINER(scroll), temp->user_list); + Context; + + gtk_paned_add2(GTK_PANED(paned), box); + + img = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); + gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &w, &h); + + temp->labelbox = gtk_hbox_new(FALSE, 0); + + temp->label = gtk_label_new(_("Not connected")); + temp->closebutton = gtk_button_new(); + gtk_signal_connect(GTK_OBJECT(temp->closebutton), "clicked", GTK_SIGNAL_FUNC(close_tab_cb), temp); + gtk_container_add(GTK_CONTAINER(temp->closebutton), img); + gtk_button_set_relief(GTK_BUTTON(temp->closebutton), GTK_RELIEF_NONE); + gtk_widget_set_size_request(temp->closebutton, w, h); + Context; + + gtk_box_pack_start(GTK_BOX(temp->labelbox), temp->label, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(temp->labelbox), temp->closebutton, FALSE, TRUE, 0); + gtk_widget_show_all(temp->labelbox); + + Context; + + gtk_widget_show_all(paned); + Context; + + temp->num = gtk_notebook_append_page(GTK_NOTEBOOK(main_book), paned, temp->labelbox); + + gtk_widget_set_sensitive(main_menu_show_sidebar, TRUE); + +#ifdef DEBUG + feed_info_to_terminal(temp, TRUE, "Opened as %d\n", temp->num); +#endif + + if (change_title) + { + set_title(NULL, "BotCommander - %s", _("Not connected")); + gtk_notebook_set_current_page(GTK_NOTEBOOK(main_book), temp->num); + buf = g_malloc(strlen(_("Mode: %c")) + 1); + sprintf(buf, _("Mode: %c"), toupper(temp->mode)); + gtk_label_set_text(GTK_LABEL(main_statuslabel_mode), buf); + g_free(buf); + } + + tab_list = g_list_append(tab_list, temp); + + Context; + + active = get_active_tab(); + if (active) + gtk_widget_grab_focus((get_active_tab())->editbox); + + Context; + + temp->sock = 0; + temp->socktag = 0; + temp->bot = NULL; + + if (newtab) + *newtab = temp; + + Context; + + return temp->num; +} +/* }}} */ + +/* {{{ get_active_tab() */ +t_tab_data * +get_active_tab(void) +{ + GList *temp; + gint current = gtk_notebook_get_current_page(GTK_NOTEBOOK(main_book)); + + Context; + + temp = g_list_find_custom(tab_list, ¤t, find_tab_by_pagenum); + + if (temp) + return (t_tab_data *)(temp->data); + + Context; + + return NULL; +} +/* }}} */ + +/* {{{ set_tab_numbers() */ +void +set_tab_numbers(gpointer data, gpointer user_data) +{ + t_tab_data *tab = (t_tab_data *)data; + gint num = *((gint *)user_data); + + if (tab->num > num) + tab->num--; +} +/* }}} */ + +/* {{{ close_tab() */ +gboolean +close_tab(t_tab_data *to_close) +{ + Context; + + if (!to_close) + return TRUE; + + if (to_close->connected) + { + GtkWidget *dialog; + gint result; + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("This tab is connected. Are you sure you want to close it?")); + result = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + switch (result) + { + case GTK_RESPONSE_YES: + gdk_input_remove(to_close->socktag); + close(to_close->sock); + break; + default: + return TRUE; + } + } + + Context; + + g_list_foreach(tab_list, set_tab_numbers, &(to_close->num)); + + Context; + + gtk_notebook_remove_page(GTK_NOTEBOOK(main_book), to_close->num); + tab_list = g_list_remove(tab_list, to_close); + + Context; + + if (!tab_list) + { + char *buf; + + buf = g_malloc(strlen(_("Mode: %c")) + 1); + sprintf(buf, _("Mode: %c"), 0); + gtk_label_set_text(GTK_LABEL(main_statuslabel_mode), buf); + g_free(buf); + + gtk_widget_set_sensitive(main_menu_show_sidebar, FALSE); + } + + Context; + + return TRUE; +} +/* }}} */ + +/* {{{ assign_bot_to_tab_by_name() */ +gboolean +assign_bot_to_tab_by_name(t_tab_data *tab, gchar *name) +{ + t_bot_data *temp = get_bot_by_botname(name); + + if (temp) + { + tab->bot = get_bot_by_botname(name); + set_title(tab, name); + return TRUE; + } + + return FALSE; +} +/* }}} */ + +/* {{{ assign_bot_to_tab() */ +void +assign_bot_to_tab(t_tab_data *tab, t_bot_data *bot) +{ + tab->bot = bot; + set_title(tab, bot->botname); +} +/* }}} */ + +/* {{{ connect_tab() */ +gint +connect_tab(t_tab_data *tab) +{ + gint t = BCE_NOBOT; + + if (tab->bot) + { + t = connect_to_host(tab->bot->host, tab->bot->port, &(tab->sock), &(tab->socktag), tab); + switch (t) + { + case BCE_NOPROTO: + feed_error_to_terminal(tab, TRUE, _("Can not get IP protocol")); + break; + case BCE_CANTRESOLV: + feed_error_to_terminal(tab, TRUE, _("Can not resolv hostname %s"), tab->bot->host); + break; + case BCE_CANTCONNECT: + feed_error_to_terminal(tab, TRUE, _("Can not connect to bot")); + break; + case BCE_SUCCESS: + tab->connected = TRUE; + break; + default: + feed_error_to_terminal(tab, TRUE, _("Unknown error!")); + break; + } + } + + return t; +} +/* }}} */ + +/* {{{ channel_store_updater() */ +void +channel_store_updater(gpointer item, gpointer store) +{ + GtkListStore *model = (GtkListStore *)store; + GtkTreeIter iter; + + gtk_list_store_append(model, &iter); + gtk_list_store_set(model, &iter, 0, ((t_channel *)item)->name, -1); +} +/* }}} */ + +/* {{{ update_channel_list() */ +void +update_channel_list(t_tab_data *tab) +{ + GtkTreeModel *model; + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(tab->channel_list)); + g_object_ref(model); + gtk_tree_view_set_model(GTK_TREE_VIEW(tab->channel_list), NULL); + + gtk_list_store_clear(GTK_LIST_STORE(model)); + + g_list_foreach(tab->actual_channel_list, channel_store_updater, model); + + gtk_tree_view_set_model(GTK_TREE_VIEW(tab->channel_list), model); + g_object_unref(model); +} +/* }}} */ + +/* {{{ user_store_updater() */ +void +user_store_updater(gpointer item, gpointer store) +{ + GtkListStore *model = (GtkListStore *)store; + GtkTreeIter iter; + + gtk_list_store_append(model, &iter); + gtk_list_store_set(model, &iter, 0, ((t_user *)item)->name, -1); +} +/* }}} */ + +/* {{{ update_user_list() */ +void +update_user_list(t_tab_data *tab) +{ + GtkTreeModel *model; + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(tab->user_list)); + g_object_ref(model); + gtk_tree_view_set_model(GTK_TREE_VIEW(tab->user_list), NULL); + + gtk_list_store_clear(GTK_LIST_STORE(model)); + + g_list_foreach(tab->actual_user_list, user_store_updater, model); + + gtk_tree_view_set_model(GTK_TREE_VIEW(tab->user_list), model); + g_object_unref(model); +} +/* }}} */ + +/* {{{ disconnect_tab() */ +void +disconnect_tab(t_tab_data *tab) +{ + if (tab->connected == FALSE) + { + feed_error_to_terminal(tab, TRUE, _("Tab is not connected")); + return; + } + shutdown(tab->sock, SHUT_RDWR); + close(tab->sock); + gdk_input_remove(tab->socktag); + tab->connected = FALSE; + tab->socktag = 0; + tab->sock = 0; + if (tab->data_arrived) + feed_info_to_terminal(tab, TRUE, _("Connection closed")); + set_title(tab, "Not connected"); + change_mode('B', FALSE); + tab->data_arrived = FALSE; + /* If the connection is closed while we enter the password (e.g + * you mistype the password), the entry would be masked + * forever, so I unmask it now */ + gtk_entry_set_visibility(GTK_ENTRY(tab->editbox), TRUE); +} +/* }}} */ + +/* {{{ change_active_tab() */ +void +change_active_tab(gint num) +{ + gtk_notebook_set_current_page(GTK_NOTEBOOK(main_book), num); +} +/* }}} */ diff --git a/src/widgets.c b/src/widgets.c new file mode 100644 index 0000000..adcb3f3 --- /dev/null +++ b/src/widgets.c @@ -0,0 +1,412 @@ +/* vim: set foldmethod=marker : */ +/* {{{ Legal info + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + }}} */ +/* {{{ + * widgets.c + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + * + * Widget creation + }}} */ + +// TODO: Insert this in one of the Makefiles +#define _GNU_SOURCE +/* {{{ Includes */ +#include +#include +#include +#include +#include +#include +#include + +#include "functions.h" +#include "typedefs.h" +#include "defines.h" +#include "config.h" + +/* }}} */ + +/* {{{ Variables */ +GtkWidget *main_window; +GtkWidget *main_vbox; +GtkWidget *main_menu; +GtkWidget *main_toolbar; +GtkWidget *main_book; +GtkWidget *main_statusbox; +GtkWidget *main_statuslabel_message; +GtkWidget *main_statuslabel_mode; +GtkWidget *main_menu_mode_b; +GtkWidget *main_menu_mode_e; +GtkWidget *main_menu_mode_m; +GtkAccelGroup *accel_group; +GtkWidget *main_menu_show_sidebar; +/* }}} */ + +/* {{{ set_title() */ +void +set_title(t_tab_data *what, char *format, ...) +{ + gchar *ptbuf; + va_list args; + + Context; + va_start(args, format); + vasprintf(&ptbuf, format, args); + va_end(args); + Context; + + if (!what) + gtk_window_set_title(GTK_WINDOW(main_window), (const gchar *)ptbuf); + else + { + gtk_label_set_text(GTK_LABEL(what->label), ptbuf); + if (get_active_tab() == what) + set_title(NULL, "BotCommander - %s", ptbuf); + } +} +/* }}} */ + +/* {{{ create_menu() */ +GtkWidget * +create_menu(void) +{ + GtkWidget *menubar; + GtkWidget *submenu; + GtkWidget *menuitem; + GtkWidget *image; + GtkWidget *hbox; + GtkWidget *child; + GSList *group = NULL; + + menubar = gtk_menu_bar_new(); + + /* Bot submenu */ + submenu = gtk_menu_new(); + + /* Exit menu item */ + menuitem = gtk_menu_item_new_with_mnemonic(_("E_xit")); + hbox = gtk_hbox_new(FALSE, 0); + image = gtk_image_new_from_stock(GTK_STOCK_QUIT, GTK_ICON_SIZE_MENU); + child = gtk_bin_get_child(GTK_BIN(menuitem)); + g_object_ref(child); + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); + gtk_container_remove(GTK_CONTAINER(menuitem), child); + gtk_box_pack_start(GTK_BOX(hbox), child, TRUE, TRUE, 2); + g_object_unref(child); + gtk_container_add(GTK_CONTAINER(menuitem), hbox); + gtk_signal_connect(GTK_OBJECT(menuitem), "activate", GTK_SIGNAL_FUNC(menu_exit), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); + gtk_widget_add_accelerator(menuitem, "activate", accel_group, GDK_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + + /* Append the submenu to the menu bar */ + menuitem = gtk_menu_item_new_with_mnemonic(_("_Bot")); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); + gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem); + + /* Mode submenu */ + submenu = gtk_menu_new(); + + /* BotCommander Command Mode menu item */ + menuitem = gtk_radio_menu_item_new_with_mnemonic(group, _("_BotCommander command mode")); + gtk_signal_connect(GTK_OBJECT(menuitem), "toggled", GTK_SIGNAL_FUNC(menu_mode_changed), NULL); + group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem)); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); + main_menu_mode_b = menuitem; + gtk_widget_add_accelerator(menuitem, "activate", accel_group, GDK_b, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + + /* Eggdrop Command Mode menu item */ + menuitem = gtk_radio_menu_item_new_with_mnemonic(group, _("_Eggdrop command mode")); + gtk_signal_connect(GTK_OBJECT(menuitem), "toggled", GTK_SIGNAL_FUNC(menu_mode_changed), NULL); + group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem)); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); + main_menu_mode_e = menuitem; + gtk_widget_add_accelerator(menuitem, "activate", accel_group, GDK_e, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + + /* Message Mode menu item */ + menuitem = gtk_radio_menu_item_new_with_mnemonic(group, _("_Message mode")); + gtk_signal_connect(GTK_OBJECT(menuitem), "toggled", GTK_SIGNAL_FUNC(menu_mode_changed), NULL); + group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem)); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); + main_menu_mode_m = menuitem; + gtk_widget_add_accelerator(menuitem, "activate", accel_group, GDK_m, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + + /* Append the submenu to the menu bar */ + menuitem = gtk_menu_item_new_with_mnemonic(_("_Mode")); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); + gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem); + + /* Setup submenu */ + submenu = gtk_menu_new(); + + /* Bot List menu item */ + menuitem = gtk_menu_item_new_with_mnemonic(_("_Bot list")); + hbox = gtk_hbox_new(FALSE, 0); + image = gtk_image_new_from_stock(GTK_STOCK_PROPERTIES, GTK_ICON_SIZE_MENU); + child = gtk_bin_get_child(GTK_BIN(menuitem)); + g_object_ref(child); + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); + gtk_container_remove(GTK_CONTAINER(menuitem), child); + gtk_box_pack_start(GTK_BOX(hbox), child, TRUE, TRUE, 2); + g_object_unref(child); + gtk_container_add(GTK_CONTAINER(menuitem), hbox); + gtk_signal_connect(GTK_OBJECT(menuitem), "activate", GTK_SIGNAL_FUNC(menu_botlist_open), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); + gtk_widget_add_accelerator(menuitem, "activate", accel_group, GDK_l, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + + /* Preferences menu item */ + menuitem = gtk_menu_item_new_with_mnemonic(_("_Preferences")); + hbox = gtk_hbox_new(FALSE, 0); + image = gtk_image_new_from_stock(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU); + child = gtk_bin_get_child(GTK_BIN(menuitem)); + g_object_ref(child); + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); + gtk_container_remove(GTK_CONTAINER(menuitem), child); + gtk_box_pack_start(GTK_BOX(hbox), child, TRUE, TRUE, 2); + g_object_unref(child); + gtk_container_add(GTK_CONTAINER(menuitem), hbox); + gtk_signal_connect(GTK_OBJECT(menuitem), "activate", GTK_SIGNAL_FUNC(menu_prefs_open), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); + gtk_widget_add_accelerator(menuitem, "activate", accel_group, GDK_p, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + + /* Append the submenu to the menu bar */ + menuitem = gtk_menu_item_new_with_mnemonic(_("_Setup")); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); + gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem); + + /* Tab submenu */ + submenu = gtk_menu_new(); + + /* New Tab menu item */ + menuitem = gtk_menu_item_new_with_mnemonic(_("_New tab")); + hbox = gtk_hbox_new(FALSE, 0); + image = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU); + child = gtk_bin_get_child(GTK_BIN(menuitem)); + g_object_ref(child); + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); + gtk_container_remove(GTK_CONTAINER(menuitem), child); + gtk_box_pack_start(GTK_BOX(hbox), child, TRUE, TRUE, 2); + g_object_unref(child); + gtk_container_add(GTK_CONTAINER(menuitem), hbox); + gtk_signal_connect(GTK_OBJECT(menuitem), "activate", GTK_SIGNAL_FUNC(menu_new_tab), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); + gtk_widget_add_accelerator(menuitem, "activate", accel_group, GDK_t, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + + /* Close Tab menu item */ + menuitem = gtk_menu_item_new_with_mnemonic(_("_Close tab")); + hbox = gtk_hbox_new(FALSE, 0); + image = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); + child = gtk_bin_get_child(GTK_BIN(menuitem)); + g_object_ref(child); + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); + gtk_container_remove(GTK_CONTAINER(menuitem), child); + gtk_box_pack_start(GTK_BOX(hbox), child, TRUE, TRUE, 2); + g_object_unref(child); + gtk_container_add(GTK_CONTAINER(menuitem), hbox); + gtk_signal_connect(GTK_OBJECT(menuitem), "activate", GTK_SIGNAL_FUNC(menu_close_tab), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); + gtk_widget_add_accelerator(menuitem, "activate", accel_group, GDK_w, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + + /* Show/hide the channel and handle list */ + main_menu_show_sidebar = gtk_check_menu_item_new_with_mnemonic(_("Show sidebar")); + hbox = gtk_hbox_new(FALSE, 0); + image = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_MENU); + child = gtk_bin_get_child(GTK_BIN(main_menu_show_sidebar)); + g_object_ref(child); + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); + gtk_container_remove(GTK_CONTAINER(main_menu_show_sidebar), child); + gtk_box_pack_start(GTK_BOX(hbox), child, TRUE, TRUE, 2); + g_object_unref(child); + gtk_container_add(GTK_CONTAINER(main_menu_show_sidebar), hbox); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(main_menu_show_sidebar), TRUE); + gtk_signal_connect(GTK_OBJECT(main_menu_show_sidebar), "toggled", GTK_SIGNAL_FUNC(menu_showhide_sidebar), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), main_menu_show_sidebar); + gtk_widget_add_accelerator(main_menu_show_sidebar, "activate", accel_group, GDK_h, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + gtk_widget_set_sensitive(main_menu_show_sidebar, FALSE); + + /* Append the submenu to the menu bar */ + menuitem = gtk_menu_item_new_with_mnemonic(_("_Tab")); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); + gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem); + + /* Help submenu */ + submenu = gtk_menu_new(); + + /* About menu item */ + menuitem = gtk_menu_item_new_with_mnemonic(_("_About")); + hbox = gtk_hbox_new(FALSE, 0); + image = gtk_image_new_from_stock(GTK_STOCK_ABOUT, GTK_ICON_SIZE_MENU); + child = gtk_bin_get_child(GTK_BIN(menuitem)); + g_object_ref(child); + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); + gtk_container_remove(GTK_CONTAINER(menuitem), child); + gtk_box_pack_start(GTK_BOX(hbox), child, TRUE, TRUE, 2); + g_object_unref(child); + gtk_container_add(GTK_CONTAINER(menuitem), hbox); + gtk_signal_connect(GTK_OBJECT(menuitem), "activate", GTK_SIGNAL_FUNC(menu_about), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); + + /* Append the submenu to the menu bar */ + menuitem = gtk_menu_item_new_with_mnemonic(_("_Help")); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); + gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem); + gtk_menu_item_set_right_justified(GTK_MENU_ITEM(menuitem), TRUE); + + return menubar; +} +/* }}} */ + +/* {{{ create_main_window() */ +int +create_main_window(void) +{ + GtkWidget *frame; + gchar *buf; + + main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + g_signal_connect(G_OBJECT(main_window), "destroy", G_CALLBACK(destroy_event), NULL); + g_signal_connect(G_OBJECT(main_window), "delete_event", G_CALLBACK(delete_event), NULL); + set_title(NULL, "BotCommander"); + gtk_window_set_default_icon_from_file(PACKAGE_PIXMAPS_DIR "/bc48_trans.png", NULL); + + accel_group = gtk_accel_group_new(); + gtk_window_add_accel_group(GTK_WINDOW(main_window), accel_group); + + main_vbox = gtk_vbox_new(FALSE, 0); + + main_menu = create_menu(); + gtk_signal_connect(GTK_OBJECT(main_window), "key_press_event", GTK_SIGNAL_FUNC(entry_keypress), NULL); + gtk_box_pack_start(GTK_BOX(main_vbox), main_menu, FALSE, TRUE, 0); + + main_toolbar = gtk_toolbar_new(); + gtk_toolbar_insert_stock(GTK_TOOLBAR(main_toolbar), GTK_STOCK_QUIT, _("Exit BotCommander"), NULL, G_CALLBACK(toolbar_quit), NULL, -1); + gtk_toolbar_insert_stock(GTK_TOOLBAR(main_toolbar), GTK_STOCK_ADD, _("New tab"), NULL, G_CALLBACK(toolbar_add_tab), NULL, -1); + gtk_toolbar_insert_stock(GTK_TOOLBAR(main_toolbar), GTK_STOCK_CLOSE, _("Close active tab"), NULL, G_CALLBACK(toolbar_close_active), NULL, -1); + gtk_toolbar_insert_stock(GTK_TOOLBAR(main_toolbar), GTK_STOCK_PREFERENCES, _("Preferences"), NULL, G_CALLBACK(toolbar_open_prefs), NULL, -1); + gtk_toolbar_set_style(GTK_TOOLBAR(main_toolbar), GTK_TOOLBAR_ICONS); + gtk_box_pack_start(GTK_BOX(main_vbox), main_toolbar, FALSE, TRUE, 0); + + main_book = gtk_notebook_new(); + gtk_notebook_set_tab_pos(GTK_NOTEBOOK(main_book), GTK_POS_TOP); + gtk_notebook_set_show_tabs(GTK_NOTEBOOK(main_book), TRUE); + gtk_notebook_set_show_border(GTK_NOTEBOOK(main_book), TRUE); + gtk_notebook_set_scrollable(GTK_NOTEBOOK(main_book), TRUE); + gtk_signal_connect(GTK_OBJECT(main_book), "switch-page", GTK_SIGNAL_FUNC(book_change_tab), NULL); + gtk_box_pack_start(GTK_BOX(main_vbox), main_book, TRUE, TRUE, 0); + + main_statusbox = gtk_hbox_new(FALSE, 0); + + frame = gtk_frame_new(NULL); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN); + main_statuslabel_message = gtk_label_new("BotCommander"); + gtk_label_set_justify(GTK_LABEL(main_statuslabel_message), GTK_JUSTIFY_RIGHT); + gtk_container_add(GTK_CONTAINER(frame), main_statuslabel_message); + gtk_box_pack_start(GTK_BOX(main_statusbox), frame, TRUE, TRUE, 0); + + buf = g_malloc(strlen(_("Mode: %c")) + 1); + sprintf(buf, _("Mode: %c"), 0); + frame = gtk_frame_new(NULL); + main_statuslabel_mode = gtk_label_new(buf); + g_free(buf); + gtk_label_set_justify(GTK_LABEL(main_statuslabel_mode), GTK_JUSTIFY_LEFT); + gtk_container_add(GTK_CONTAINER(frame), main_statuslabel_mode); + gtk_box_pack_end(GTK_BOX(main_statusbox), frame, FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(main_vbox), main_statusbox, FALSE, FALSE, 0); + + gtk_container_add(GTK_CONTAINER(main_window), main_vbox); + + gtk_widget_show_all(main_window); + + return TRUE; +} +/* }}} */ + +/* {{{ feed_line_to_terminal() */ +/* Feeds some text to the terminal widget. */ +static void +feed_line_to_terminal(t_tab_data *tab, gboolean need_crlf, gchar *line, va_list list) +{ + gchar *string; + gint len; + + len = vasprintf(&string, line, list); + + vte_terminal_feed((VteTerminal *)tab->vt, string, strlen(string)); + if (need_crlf) + vte_terminal_feed((VteTerminal *)tab->vt, "\r\n", 2); +} +/* }}} */ + +/* {{{ feed_crlf_to_terminal() */ +/* Feeds a CD LF pair to the terminal, if needed. */ +static void +feed_crlf_to_terminal(t_tab_data *tab, gboolean need_it) +{ + if (need_it) + vte_terminal_feed((VteTerminal *)tab->vt, "\r\n", 2); +} +/* }}} */ + +/* {{{ feed_message_to_terminal() */ +/* Feeds some informational (un-coloured) text to the terminal, always appending a line-feed. */ +void +feed_message_to_terminal(t_tab_data *tab, gboolean need_crlf, gchar *line, ...) +{ + va_list pl; + + va_start(pl, line); + feed_line_to_terminal(tab, FALSE, line, pl); + va_end(pl); + feed_crlf_to_terminal(tab, need_crlf); +} +/* }}} */ + +/* {{{ feed_error_to_terminal() */ +/* Feeds some error (red) text to the terminal, always appending a line-feed */ +void +feed_error_to_terminal(t_tab_data *tab, gboolean need_crlf, gchar *line, ...) +{ + va_list pl; + + va_start(pl, line); + feed_message_to_terminal(tab, FALSE, "\033[1;31m"); + feed_line_to_terminal(tab, FALSE, line, pl); + va_end(pl); + feed_message_to_terminal(tab, need_crlf, "\033[0m"); +} +/* }}} */ + +/* {{{ feed_info_to_terminal() */ +/* Feeds some informational (green) text to the terminal, always appending a line-feed. */ +void +feed_info_to_terminal(t_tab_data *tab, gboolean need_crlf, gchar *line, ...) +{ + va_list pl; + + feed_message_to_terminal(tab, FALSE, "\033[1;32m"); + + va_start(pl, line); + feed_line_to_terminal(tab, FALSE, line, pl); + va_end(pl); + + feed_message_to_terminal(tab, need_crlf, "\033[0m"); +} +/* }}} */ + diff --git a/template b/template new file mode 100644 index 0000000..ded3ee0 --- /dev/null +++ b/template @@ -0,0 +1,26 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +/*************************************************************************** + * #FILE# + * + * Wed Nov 09 22:16:59 2005 + * Copyright (C) 2005 Gergely POLONKAI + * polesz@techinfo.hu + ***************************************************************************/ +/*************************************************************************** + * #DESCRIPTION# + ***************************************************************************/ +