1
0
mirror of https://github.com/moparisthebest/hexchat synced 2024-11-28 04:02:16 -05:00

add xchat r1489

This commit is contained in:
berkeviktor@aol.com 2011-02-24 04:14:30 +01:00
parent f16af8be94
commit 4a6ceffb98
245 changed files with 324678 additions and 0 deletions

0
AUTHORS Normal file
View File

340
COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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 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
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

2251
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

51
HACKING Normal file
View File

@ -0,0 +1,51 @@
Just some tips if you're going to help with xchat code (patches etc):
* Use tabs, not spaces, to indent code.
* Use a tab size of 3 (most editors will let you choose this).
Type :set ts=3 in vim/gvim.
* Try to stick to the same consistant coding style:
void
routine (void)
{
if (function (a, b, c))
{
x = a + 1;
}
}
(vertically aligned braces, a space after if, while, functions etc).
* Don't use "//" C++ style comments, some compilers don't like them.
* When opening a file with unix level functions (open, read/write, close)
as opposed to the C-level functions (fopen, fwrite/fread, fclose), use
the OFLAGS macro. This makes sure it'll work on Win32 aswell as unix e.g:
fh = open ("file", OFLAGS | O_RDONLY);
* Use closesocket() for sockets, and close() for normal files.
* Don't read() from sockets, instead use recv().
* Please provide unified format diffs (run diff -u).
* Call your patch something more meaningfull than xchat.diff (I get a
million of these files!).
* To make a really nice and clean patch, do something like this:
Have two directories, unpacked from the original archive:
xchat-2.0.0/
xchat-2.0.0p1/
Then edit/compile the xchat-2.0.0p1 directory. When you're done, make
a patch with:
cd xchat-2.0.0p1
make distclean
cd ..
diff -urN xchat-2.0.0 xchat-2.0.0p1 > xchat-something.diff
If using nmake (Windows) replace "make distclean" with "nmake -f makefile.msc clean"

49
INSTALL Normal file
View File

@ -0,0 +1,49 @@
X-Chat Requirements:
~~~~~~~~~~~~~~~~~~~~
- GTK 2.6+ (it comes with your Linux)
Optional:
- Perl (http://www.perl.org)
- Python (http://www.python.org)
- TCL (http://tcl.activestate.com)
- OpenSSL (http://www.openssl.org)
X-Chat Compiling and Installation:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Type this:
./configure
make
Become root and type:
make install
Other Options
~~~~~~~~~~~~~
To get a full list of compile options, type:
./configure --help
If you do not have GNU Gettext installed, instead use:
./configure --disable-nls
If you want to disable Perl you can do:
./configure --disable-perl
If you want to install a smaller stripped binary (without debug) do:
make install-strip

117
INSTALL.w32 Normal file
View File

@ -0,0 +1,117 @@
COMPILING ON WIN32
~~~~~~~~~~~~~~~~~~
It is not easy! Be warned! You need either one of these compilers:
* Mingw (http://www.mingw.org)
* MS Visual C
Note: This source code is meant for Linux/Unix like systems. Compiling this for
Windows will produce a below-par quality product. The official XChat for Windows
is not built with this unix source code.
Getting GTK
~~~~~~~~~~~
You also need GTK+ 2.10 for win32. Altough the GTK packages from the GIMP
website are larger and harder to install they work very well.
1) Get the following packages from:
http://www.gimp.org/~tml/gimp/win32/downloads.html
- gtk+-2.4.3.tar.gz
- gtk+-dev-2.4.3.tar.gz
- dirent.zip
- gettext-runtime-0.13.1.zip
- gettext-tools-0.13.1.zip
- atk-1.6.0.zip
- atk-dev-1.6.0.zip
- pango-1.4.0.zip
- pango-dev-1.4.0.zip
- libpng (http://gnuwin32.sourceforge.net/packages/libpng.htm) Binaries & Developer files.
- GNU libiconv (Not source files)
- glib-2.4.2.zip
- glib-dev-2.4.2.zip
- pkgconfig-0.15.zip
- Zlib121-dll.zip
2) Extract all files to a suitable place such as c:\devtools
3) Windows 2000, XP & 2003 users:
- Start->(Settings->)Control Panel->System Applet
- Advanced Tab->Environment Variables
- Under "User variables for <user>" append ";C:\devtools" to the end of the PATH Variable
- Click Ok twice and close the Control Panel
For Windows 9x users your basicly on your own for now.
Mingw
~~~~~
I havn't tried this yet, but ./configure --disable-xlib would be a start.
MS Visual C
~~~~~~~~~~~
1) Edit src\makeinc.msc
You need to change the variables GLIB, GTK and LIBS to point
the correct paths for your harddrive. Use the program pkg-config
to find this information.
a) paste the output of `pkg-config glib-2.0 --msvc-syntax --cflags`
to the GLIB = ... line.
b) paste the output of `pkg-config gtk+-2.0 --msvc-syntax --cflags`
to the GTK = ... line.
c) paste the output of `pkg-config gtk+-2.0 --msvc-syntax --libs`
to the LIBS = ... line.
2) In MSVC's includes directory, copy io.h to unistd.h.
MS VC++ 6
~~~~~~~~~
3) Download Platform SDK from http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
(you only need Core SDK) - ~200 MB Download (Be warned).
4) Open the build enviroment.
a) If your planning on developing modifications to the xchat code go:
Start->Programs->Microsoft Platform SDK...->Open Build Enviroment...->(Choose OS)->... (Debug)
b) If your compiling just to use xchat and wish to no recieve debug messages:
Start->Programs->Microsoft Platform SDK...->Open Build Enviroment...->(Choose OS)->... (Retail)
5) Change directory into where you have download the xchat source to and type this:
cd src
nmake -f makefile.msc clean
nmake -f makefile.msc
6) Copy fe-gtk\xchat.exe to another place.
MS VC++ 7 (.NET)
~~~~~~~~~~~~~~~~
3) Open the Visual Studio .NET Command Prompt
4) Change directory into where you have download the xchat source to and type this:
cd src
nmake -f makefile.msc clean
nmake -f makefile.msc
5) Copy fe-gtk\xchat.exe to another place.
Common problems:
~~~~~~~~~~~~~~~~
* gdk-pixbuf-csource must be in PATH.
FIX: See step 3 for setting up GTK
* You might need to install dirent.zip manually.
FIX: Copy C:\devtools\include\dirent.h to C:\devtools\include\glib-2.0\dirent.h
* Include path to libintl.h should be in GLIB= (makeinc.msc).
FIX: Copy C:\devtools\include\libintl.h to C:\devtools\include\glib-2.0\libintl.h

12
Makefile.am Normal file
View File

@ -0,0 +1,12 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = po intl src plugins
EXTRA_DIST = autogen.sh HACKING INSTALL.w32 faq.html xchat.png \
xchat.desktop xchat.spec config.h.w32 xchat.ico
icon_DATA = xchat.png
icondir = $(datadir)/pixmaps
util_DATA = xchat.desktop
utildir = $(datadir)/applications

103
README Normal file
View File

@ -0,0 +1,103 @@
X-Chat README
~~~~~~~~~~~~~
X-Chat ("xchat") Copyright (c) 1998-2010 By Peter Zelezny.
This program is released under the GPL v2 with the additional exemption
that compiling, linking, and/or using OpenSSL is allowed. You may
provide binary packages linked to the OpenSSL libraries, provided that
all other requirements of the GPL are met.
See file COPYING for details.
What is it?
~~~~~~~~~~~
X-Chat is an IRC client for UNIX operating systems. I.R.C. is Internet
Relay Chat, see http://irchelp.org for more information about IRC in
general. Xchat runs on most BSD and POSIX compliant operating systems.
Requirements:
~~~~~~~~~~~~~
* GTK+ 2.10 (this is available at http://www.gtk.org).
X-Chat is known to work on, at least:
* Linux
* FreeBSD
* OpenBSD
* NetBSD
* Solaris
* AIX
* IRIX
* DEC/Compaq Tru64 UNIX
* HP-UX 10.20 and 11
* MacOS X
* Windows XP/2000/Vista/7
Notes for packagers:
~~~~~~~~~~~~~~~~~~~~
If you need your packages to work on i386, you don't need to compile with
--disable-mmx, because it's also checked at run-time.
Python Scripts:
~~~~~~~~~~~~~~~
Scripts for 1.8.x are not compatible, and a brand new interface has be
written. Documentation can be found here: http://xchat.org/docs/.
Consider using the Python interface for your scripts, it's a very nice
API, allows for loading/unloading individual scripts, and gives you
almost all the features of the C-Plugin API.
Perl Scripts:
~~~~~~~~~~~~~
Scripts for 1.8.x are compatible with the following exceptions:
* IRC::command will not interpret %C, %B, %U etc.
* user_list and user_list_short:
If a user has both op and voice, only the op flag will be 1.
* add_user_list/sub_user_list/clear_user_list
These functions do nothing.
* notify_list
Not implemented. Always returns an empty list.
* server_list
Lists servers that are not connected aswell.
* Some print events may have new names and some were added.
* Text printed by scripts must now be UTF8.
* Text passed to scripts (via add_message_handler) will be encoded in UTF8.
Autoloading Perl Scripts and Plugins
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* X-Chat automatically loads, at startup:
~/.xchat2/*.pl Perl scripts
~/.xchat2/*.py Python scripts
~/.xchat2/*.so Plugins
$(libdir)/xchat/plugins/*.so plugins
(this usually translates to /usr/lib/xchat/plugins/*.so)
Control Codes:
~~~~~~~~~~~~~~
%% - A single percentage sign
%C - Control-C (mIRC color code)
%B - Bold Text
%U - Underline Text
%R - Reverse Text
%O - Reset all Text attributes
%XXX - ASCII XXX (where XXX is a decimal 3 digit number)
(Eg: %007 sends a BEEP)
%Cforeground,background will produce a color code, eg: %C03,10
These are now disabled by default (see Settings > Prefs > Input Box).
Instead you can insert the real codes via ctrl-k, ctrl-b and ctrl-o.

40
acinclude.m4 Normal file
View File

@ -0,0 +1,40 @@
dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
dnl
dnl example
dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
AC_DEFUN([AS_AC_EXPAND],
[
EXP_VAR=[$1]
FROM_VAR=[$2]
dnl first expand prefix and exec_prefix if necessary
prefix_save=$prefix
exec_prefix_save=$exec_prefix
dnl if no prefix given, then use /usr/local, the default prefix
if test "x$prefix" = "xNONE"; then
prefix=$ac_default_prefix
fi
dnl if no exec_prefix given, then use prefix
if test "x$exec_prefix" = "xNONE"; then
exec_prefix=$prefix
fi
full_var="$FROM_VAR"
dnl loop until it doesn't change anymore
while true; do
new_full_var="`eval echo $full_var`"
if test "x$new_full_var"="x$full_var"; then break; fi
full_var=$new_full_var
done
dnl clean up
full_var=$new_full_var
AC_SUBST([$1], "$full_var")
dnl restore prefix and exec_prefix
prefix=$prefix_save
exec_prefix=$exec_prefix_save
])

113
autogen.sh Normal file
View File

@ -0,0 +1,113 @@
#!/bin/bash
have_automake=false
if automake --version < /dev/null > /dev/null 2>&1 ; then
automake_version=`automake --version | grep 'automake (GNU automake)' | sed 's/^[^0-9]*\(.*\)/\1/'`
case $automake_version in
1.2*|1.3*|1.4|1.4*|1.5*|1.6*|1.7*|1.8*)
;;
*)
have_automake=true
;;
esac
fi
if $have_automake ; then
AUTOMAKE="automake"
ACLOCAL="aclocal"
else
if automake-1.9 --version < /dev/null > /dev/null 2>&1 ; then
AUTOMAKE="automake-1.9"
ACLOCAL="aclocal-1.9"
else
echo "automake missing or too old. This requires atleast automake 1.9"
exit 1
fi
fi
# ------ START GETTEXT ------
echo searching for GNU gettext intl directory...
dirs="/usr/share /usr/local/share /opt/share /usr /usr/local /opt /usr/gnu/share /opt/local /opt/local/share"
found=0
for try in $dirs; do
echo -n " -> $try/gettext/intl... "
if test -d $try/gettext/intl; then
echo found it
found=1
break
fi
echo no
done
if test "$found" != 1; then
echo ERROR: Cannot find gettext/intl directory.
echo ERROR: Install GNU gettext in /usr or /usr/local prefix.
exit 7
fi;
echo copying gettext intl files...
if test -f $try/gettext/mkinstalldirs; then
ln -s $try/gettext/mkinstalldirs mkinstalldirs
fi
intldir="$try/gettext/intl"
if test ! -d intl; then
mkdir intl
fi
olddir=`pwd`
cd $intldir
for file in *; do
if test $file != COPYING.LIB-2.0 && test $file != COPYING.LIB-2.1; then
rm -f $olddir/intl/$file
cp $intldir/$file $olddir/intl/
fi
done
cp -f $try/gettext/po/Makefile.in.in $olddir/po/
cd $olddir
if test -f intl/plural.c; then
sleep 2
touch intl/plural.c
fi
# ------ END GETTEXT ------
echo running $ACLOCAL...
$ACLOCAL $ACLOCAL_FLAGS
if test "$?" != "0"; then
echo aclocal failed, stopping.
exit 2
fi
echo running libtoolize...
libtoolize --force
if test "$?" != "0"; then
echo libtoolize failed, stopping.
exit 3
fi
echo running autoheader...
autoheader
if test "$?" != "0"; then
echo autoheader failed, stopping.
exit 4
fi
echo running $AUTOMAKE...
$AUTOMAKE -a --foreign
if test "$?" != "0"; then
echo automake failed, stopping.
exit 5
fi
echo running autoconf...
autoconf
if test "$?" != "0"; then
echo autoconf failed, stopping.
exit 6
fi
echo if no errors occured, run ./configure --enable-maintainer-mode
exit 0
#autogen.sh generates:
# aclocal.m4 Makefile.in config.guess config.sub ltmain.sh
# configure install-sh missing mkinstalldirs depcomp
#
#configure generates:
# config.status libtool Makefile.in

12
config.h.w32 Normal file
View File

@ -0,0 +1,12 @@
#define LOCALEDIR "./locale"
#define ENABLE_NLS
#define USE_GMODULE
#define USE_PLUGIN
#define PACKAGE_NAME "xchat"
#define PACKAGE_VERSION "2.8.8-Unofficial"
#define XCHATLIBDIR "."
#define XCHATSHAREDIR "."
#define OLD_PERL
#ifndef USE_IPV6
#define socklen_t int
#endif

571
config.rpath Normal file
View File

@ -0,0 +1,571 @@
#! /bin/sh
# Output a system dependent set of variables, describing how to set the
# run time search path of shared libraries in an executable.
#
# Copyright 1996-2005 Free Software Foundation, Inc.
# Taken from GNU libtool, 2001
# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# The first argument passed to this file is the canonical host specification,
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
# should be set by the caller.
#
# The set of defined variables is at the end of this script.
# Known limitations:
# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
# than 256 bytes, otherwise the compiler driver will dump core. The only
# known workaround is to choose shorter directory names for the build
# directory and/or the installation directory.
# All known linkers require a `.a' archive for static linking (except M$VC,
# which needs '.lib').
libext=a
shrext=.so
host="$1"
host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
cc_basename=`echo "$CC" | sed -e 's%^.*/%%'`
# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC.
wl=
if test "$GCC" = yes; then
wl='-Wl,'
else
case "$host_os" in
aix*)
wl='-Wl,'
;;
darwin*)
case "$cc_basename" in
xlc*)
wl='-Wl,'
;;
esac
;;
mingw* | pw32* | os2*)
;;
hpux9* | hpux10* | hpux11*)
wl='-Wl,'
;;
irix5* | irix6* | nonstopux*)
wl='-Wl,'
;;
newsos6)
;;
linux*)
case $cc_basename in
icc* | ecc*)
wl='-Wl,'
;;
pgcc | pgf77 | pgf90)
wl='-Wl,'
;;
ccc*)
wl='-Wl,'
;;
como)
wl='-lopt='
;;
esac
;;
osf3* | osf4* | osf5*)
wl='-Wl,'
;;
sco3.2v5*)
;;
solaris*)
wl='-Wl,'
;;
sunos4*)
wl='-Qoption ld '
;;
sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
wl='-Wl,'
;;
sysv4*MP*)
;;
unicos*)
wl='-Wl,'
;;
uts4*)
;;
esac
fi
# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS.
hardcode_libdir_flag_spec=
hardcode_libdir_separator=
hardcode_direct=no
hardcode_minus_L=no
case "$host_os" in
cygwin* | mingw* | pw32*)
# FIXME: the MSVC++ port hasn't been tested in a loooong time
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++.
if test "$GCC" != yes; then
with_gnu_ld=no
fi
;;
openbsd*)
with_gnu_ld=no
;;
esac
ld_shlibs=yes
if test "$with_gnu_ld" = yes; then
case "$host_os" in
aix3* | aix4* | aix5*)
# On AIX/PPC, the GNU linker is very broken
if test "$host_cpu" != ia64; then
ld_shlibs=no
fi
;;
amigaos*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
# Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
# that the semantics of dynamic libraries on AmigaOS, at least up
# to version 4, is to share data among multiple programs linked
# with the same dynamic library. Since this doesn't match the
# behavior of shared libraries on other platforms, we cannot use
# them.
ld_shlibs=no
;;
beos*)
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
cygwin* | mingw* | pw32*)
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
hardcode_libdir_flag_spec='-L$libdir'
if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
netbsd*)
;;
solaris* | sysv5*)
if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
ld_shlibs=no
elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
sunos4*)
hardcode_direct=yes
;;
linux*)
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
*)
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
esac
if test "$ld_shlibs" = yes; then
# Unlike libtool, we use -rpath here, not --rpath, since the documented
# option of GNU ld is called -rpath, not --rpath.
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
fi
else
case "$host_os" in
aix3*)
# Note: this linker hardcodes the directories in LIBPATH if there
# are no directories specified by -L.
hardcode_minus_L=yes
if test "$GCC" = yes; then
# Neither direct hardcoding nor static linking is supported with a
# broken collect2.
hardcode_direct=unsupported
fi
;;
aix4* | aix5*)
if test "$host_cpu" = ia64; then
# On IA64, the linker does run time linking by default, so we don't
# have to do anything special.
aix_use_runtimelinking=no
else
aix_use_runtimelinking=no
# Test if we are trying to use run time linking or normal
# AIX style linking. If -brtl is somewhere in LDFLAGS, we
# need to do runtime linking.
case $host_os in aix4.[23]|aix4.[23].*|aix5*)
for ld_flag in $LDFLAGS; do
if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
aix_use_runtimelinking=yes
break
fi
done
esac
fi
hardcode_direct=yes
hardcode_libdir_separator=':'
if test "$GCC" = yes; then
case $host_os in aix4.[012]|aix4.[012].*)
collect2name=`${CC} -print-prog-name=collect2`
if test -f "$collect2name" && \
strings "$collect2name" | grep resolve_lib_name >/dev/null
then
# We have reworked collect2
hardcode_direct=yes
else
# We have old collect2
hardcode_direct=unsupported
hardcode_minus_L=yes
hardcode_libdir_flag_spec='-L$libdir'
hardcode_libdir_separator=
fi
esac
fi
# Begin _LT_AC_SYS_LIBPATH_AIX.
echo 'int main () { return 0; }' > conftest.c
${CC} ${LDFLAGS} conftest.c -o conftest
aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
}'`
if test -z "$aix_libpath"; then
aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
}'`
fi
if test -z "$aix_libpath"; then
aix_libpath="/usr/lib:/lib"
fi
rm -f conftest.c conftest
# End _LT_AC_SYS_LIBPATH_AIX.
if test "$aix_use_runtimelinking" = yes; then
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
else
if test "$host_cpu" = ia64; then
hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
else
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
fi
fi
;;
amigaos*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
# see comment about different semantics on the GNU ld section
ld_shlibs=no
;;
bsdi[45]*)
;;
cygwin* | mingw* | pw32*)
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++.
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
hardcode_libdir_flag_spec=' '
libext=lib
;;
darwin* | rhapsody*)
hardcode_direct=no
if test "$GCC" = yes ; then
:
else
case "$cc_basename" in
xlc*)
;;
*)
ld_shlibs=no
;;
esac
fi
;;
dgux*)
hardcode_libdir_flag_spec='-L$libdir'
;;
freebsd1*)
ld_shlibs=no
;;
freebsd2.2*)
hardcode_libdir_flag_spec='-R$libdir'
hardcode_direct=yes
;;
freebsd2*)
hardcode_direct=yes
hardcode_minus_L=yes
;;
freebsd* | kfreebsd*-gnu | dragonfly*)
hardcode_libdir_flag_spec='-R$libdir'
hardcode_direct=yes
;;
hpux9*)
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
hardcode_libdir_separator=:
hardcode_direct=yes
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
hardcode_minus_L=yes
;;
hpux10* | hpux11*)
if test "$with_gnu_ld" = no; then
case "$host_cpu" in
hppa*64*)
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
hardcode_libdir_separator=:
hardcode_direct=no
;;
ia64*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_direct=no
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
hardcode_minus_L=yes
;;
*)
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
hardcode_libdir_separator=:
hardcode_direct=yes
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
hardcode_minus_L=yes
;;
esac
fi
;;
irix5* | irix6* | nonstopux*)
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
hardcode_libdir_separator=:
;;
netbsd*)
hardcode_libdir_flag_spec='-R$libdir'
hardcode_direct=yes
;;
newsos6)
hardcode_direct=yes
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
hardcode_libdir_separator=:
;;
openbsd*)
hardcode_direct=yes
if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
else
case "$host_os" in
openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
hardcode_libdir_flag_spec='-R$libdir'
;;
*)
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
;;
esac
fi
;;
os2*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
;;
osf3*)
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
hardcode_libdir_separator=:
;;
osf4* | osf5*)
if test "$GCC" = yes; then
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
else
# Both cc and cxx compiler support -rpath directly
hardcode_libdir_flag_spec='-rpath $libdir'
fi
hardcode_libdir_separator=:
;;
sco3.2v5*)
;;
solaris*)
hardcode_libdir_flag_spec='-R$libdir'
;;
sunos4*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_direct=yes
hardcode_minus_L=yes
;;
sysv4)
case $host_vendor in
sni)
hardcode_direct=yes # is this really true???
;;
siemens)
hardcode_direct=no
;;
motorola)
hardcode_direct=no #Motorola manual says yes, but my tests say they lie
;;
esac
;;
sysv4.3*)
;;
sysv4*MP*)
if test -d /usr/nec; then
ld_shlibs=yes
fi
;;
sysv4.2uw2*)
hardcode_direct=yes
hardcode_minus_L=no
;;
sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*)
;;
sysv5*)
hardcode_libdir_flag_spec=
;;
uts4*)
hardcode_libdir_flag_spec='-L$libdir'
;;
*)
ld_shlibs=no
;;
esac
fi
# Check dynamic linker characteristics
# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER.
libname_spec='lib$name'
case "$host_os" in
aix3*)
;;
aix4* | aix5*)
;;
amigaos*)
;;
beos*)
;;
bsdi[45]*)
;;
cygwin* | mingw* | pw32*)
shrext=.dll
;;
darwin* | rhapsody*)
shrext=.dylib
;;
dgux*)
;;
freebsd1*)
;;
kfreebsd*-gnu)
;;
freebsd*)
;;
gnu*)
;;
hpux9* | hpux10* | hpux11*)
case "$host_cpu" in
ia64*)
shrext=.so
;;
hppa*64*)
shrext=.sl
;;
*)
shrext=.sl
;;
esac
;;
irix5* | irix6* | nonstopux*)
case "$host_os" in
irix5* | nonstopux*)
libsuff= shlibsuff=
;;
*)
case $LD in
*-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
*-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
*-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
*) libsuff= shlibsuff= ;;
esac
;;
esac
;;
linux*oldld* | linux*aout* | linux*coff*)
;;
linux*)
;;
knetbsd*-gnu)
;;
netbsd*)
;;
newsos6)
;;
nto-qnx*)
;;
openbsd*)
;;
os2*)
libname_spec='$name'
shrext=.dll
;;
osf3* | osf4* | osf5*)
;;
sco3.2v5*)
;;
solaris*)
;;
sunos4*)
;;
sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
;;
sysv4*MP*)
;;
uts4*)
;;
esac
sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
# How to pass a linker flag through the compiler.
wl="$escaped_wl"
# Static library suffix (normally "a").
libext="$libext"
# Shared library suffix (normally "so").
shlibext="$shlibext"
# Flag to hardcode \$libdir into a binary during linking.
# This must work even if \$libdir does not exist.
hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
# Whether we need a single -rpath flag with a separated argument.
hardcode_libdir_separator="$hardcode_libdir_separator"
# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
# resulting binary.
hardcode_direct="$hardcode_direct"
# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
# resulting binary.
hardcode_minus_L="$hardcode_minus_L"
EOF

837
configure.in Normal file
View File

@ -0,0 +1,837 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT([XChat],[2.8.8],[http://www.xchat.org/],[xchat])
AC_PREREQ([2.59])
AC_COPYRIGHT([Copyright (C) 1998-2010 Peter Zelezny])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([configure.in])
AM_INIT_AUTOMAKE([1.9 dist-bzip2 subdir-objects no-define])
AM_MAINTAINER_MODE
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CPP
AM_PROG_AS
AM_DISABLE_STATIC
AC_PROG_LIBTOOL
dnl -----------------------------------------------------------
dnl Language Support
dnl -----------------------------------------------------------
GETTEXT_PACKAGE=xchat
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Gettext package name])
ALL_LINGUAS="be ca cs de el es fi fr gl hu it ja kn ko lt mk nl pa pl pt ru sq sr sv th uk vi zh_CN zh_TW"
AM_GNU_GETTEXT
dnl displaced from acconfig.h
AH_VERBATIM([OLD_PERL],[#undef OLD_PERL])
AH_VERBATIM([PREFIX],[#undef PREFIX])
AH_VERBATIM([XCHATLIBDIR],[#undef XCHATLIBDIR])
AH_VERBATIM([XCHATSHAREDIR],[#undef XCHATSHAREDIR])
AH_VERBATIM([SOCKS],[#undef SOCKS])
AH_VERBATIM([USE_MSPROXY],[#undef USE_MSPROXY])
dnl AH_VERBATIM([USE_GNOME],[#undef USE_GNOME])
AH_VERBATIM([USE_SHM],[#undef USE_SHM])
AH_VERBATIM([USE_GTKSPELL],[#undef USE_GTKSPELL])
AH_VERBATIM([USE_LIBSEXY],[#undef USE_LIBSEXY])
AH_VERBATIM([USE_IPV6],[#undef USE_IPV6])
AH_VERBATIM([USE_MMX],[#undef USE_MMX])
AH_VERBATIM([USE_OPENSSL],[#undef USE_OPENSSL])
AH_VERBATIM([USE_PLUGIN],[#undef USE_PLUGIN])
AH_VERBATIM([USE_XFT],[#undef USE_XFT])
AH_VERBATIM([USE_XLIB],[#undef USE_XLIB])
AH_VERBATIM([USE_SIGACTION],[#undef USE_SIGACTION])
AH_VERBATIM([USING_FREEBSD],[#undef USING_FREEBSD])
AH_VERBATIM([USING_LINUX],[#undef USING_LINUX])
AH_VERBATIM([socklen_t],[#undef socklen_t])
AH_VERBATIM([USE_DBUS],[#undef USE_DBUS])
AC_PATH_PROG(sedpath, sed)
if test "_$sedpath" = _; then
AC_MSG_ERROR("Cannot find sed: I need it\!")
fi
AC_PATH_PROG(unamepath, uname)
if test "_$unamepath" = _; then
system="unknown"
else
AC_MSG_CHECKING(system type)
system=`$unamepath -s`
AC_MSG_RESULT($system)
if test "$system" = "Linux"; then
AC_DEFINE(USING_LINUX)
fi
if test "$system" = "FreeBSD"; then
AC_DEFINE(USING_FREEBSD)
fi
fi
dnl *********************************************************************
dnl ** configure switches ***********************************************
dnl *********************************************************************
AC_ARG_ENABLE(socks,
[ --enable-socks link with SOCKS5 library (default: no)],
socks=$enableval, socks=no)
AC_ARG_ENABLE(ipv6,
[ --enable-ipv6 enable IPv6 (default: no)],
ipv6=$enableval, ipv6=no)
AC_ARG_ENABLE(xft,
[ --enable-xft enable use of Xft directly (default: no)],
xft=$enableval, xft=no)
AC_ARG_ENABLE(openssl,
[ --enable-openssl[=PATH] enable use of openSSL],
openssl=$enableval, openssl=yes)
AC_ARG_ENABLE(gtkfe,
[ --disable-gtkfe disable building gtk frontend],
gtkfe=$enableval, gtkfe=yes)
AC_ARG_ENABLE(textfe,
[ --enable-textfe build the text frontend (default: no)],
textfe=$enableval, textfe=no)
dnl AC_ARG_ENABLE(gnome,
dnl [ --disable-gnome disable use of gnome],
dnl gnome=$enableval, gnome=yes)
AC_ARG_ENABLE(xlib,
[ --disable-xlib disable use of xlib (for non X11 systems)],
xlib=$enableval, xlib=yes)
AC_ARG_ENABLE(python,
[ --disable-python don't build the python plugin],
python=$enableval, python=yes)
AC_ARG_ENABLE(perl,
[ --disable-perl don't build the perl plugin],
perl=$enableval, perl=yes)
AC_ARG_ENABLE(perl_old,
[ --disable-perl_old no backwards compatibility for perl plugin],
perl_old=$enableval, perl_old=yes)
AC_ARG_ENABLE(tcl,
[ --enable-tcl[=PATH] directory with Tcl config file: tclConfig.sh],
tcl=$enableval, tcl=yes)
AC_ARG_ENABLE(plugin,
[ --disable-plugin disable plugin support],
plugin=$enableval, plugin=yes)
AC_ARG_ENABLE(dbus,
[ --disable-dbus disable DBUS support],
dbus=$enableval, dbus=yes)
AC_ARG_ENABLE(mmx,
[ --disable-mmx disable MMX assembly routines],
mmx=$enableval, mmx=yes)
AC_ARG_ENABLE(shm,
[ --enable-shm enable use of XShm for fast tinting (default: no)],
shm=$enableval, shm=no)
AC_ARG_ENABLE(spell,
[ --enable-spell=type enable spelling type: none static libsexy gtkspell],
spell=$enableval, spell=libsexy)
AC_ARG_ENABLE(ntlm,
[ --enable-ntlm enable Microsoft's NTLM auth (libntlm) library support (default: no)],
ntlm=$enableval, ntlm=no)
dnl *********************************************************************
dnl ** GLIB *************************************************************
dnl *********************************************************************
AM_PATH_GLIB_2_0(2.0.3, glib=yes, glib=no)
if test "$glib" = no; then
AC_MSG_ERROR("Cannot find glib")
fi
COMMON_CFLAGS="$GLIB_CFLAGS"
COMMON_LIBS="$GLIB_LIBS"
dnl *********************************************************************
dnl ** GTK **************************************************************
dnl *********************************************************************
AM_PATH_GTK_2_0(2.10.0, havegtk=yes, havegtk=no)
if test "$havegtk" = no; then
gtkfe=no
echo
echo Cannot find GTK\! Not building GTK FrontEnd.
echo
fi
if test "$gtkfe" != yes; then
gnome=no
COMMON_LIBS="$GLIB_LIBS"
COMMON_CFLAGS="$GLIB_CFLAGS"
fi
dnl *********************************************************************
dnl ** GNOME ************************************************************
dnl *********************************************************************
GUI_LIBS="$GUI_LIBS $GTK_LIBS"
GUI_CFLAGS="$GUI_CFLAGS $GTK_CFLAGS"
gnome=no
#if test "$gnome" = yes; then
# AC_PATH_PROG(pkgconfigpath, pkg-config)
# AC_MSG_CHECKING(Gnome2 compile flags)
# GNOME_CFLAGS="`$pkgconfigpath libgnome-2.0 --cflags 2>/dev/null`"
# if test "_$GNOME_CFLAGS" = _ ; then
# gnome=no
# AC_MSG_RESULT([Gnome not found, building without it.])
# else
# GNOME_VER="`$pkgconfigpath libgnome-2.0 --modversion`"
# GUI_LIBS="$GUI_LIBS `$pkgconfigpath libgnome-2.0 --libs`"
# GUI_CFLAGS="$GUI_CFLAGS $GNOME_CFLAGS"
# AC_DEFINE(USE_GNOME)
# AC_MSG_RESULT(ok)
# fi
#fi
# GConf
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
dnl *********************************************************************
dnl ** XFT **************************************************************
dnl *********************************************************************
if test "$xft" = yes; then
AC_PATH_PROG(pkgconfigpath, pkg-config)
if $pkgconfigpath xft --exists; then
GUI_CFLAGS="$GUI_CFLAGS `$pkgconfigpath xft --cflags`"
GUI_LIBS="$GUI_LIBS `$pkgconfigpath xft --libs`"
else
xft=no
oldCPPFLAGS=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $GTK_CFLAGS"
AC_CHECK_HEADERS(X11/Xft/Xft.h, xft=yes)
CPPFLAGS=$oldCPPFLAGS
fi
if test "$xft" = yes; then
AC_DEFINE(USE_XFT)
fi
fi
dnl *********************************************************************
dnl ** XLIB *************************************************************
dnl *********************************************************************
if test "$xlib" = yes; then
AC_DEFINE(USE_XLIB)
if test "$system" = "SunOS"; then
LIBS="$LIBS -L/usr/openwin/lib -lX11"
else
AC_CHECK_LIB(X11, XSetWMHints)
fi
else
shm=no
fi
dnl *********************************************************************
dnl ** PERL *************************************************************
dnl *********************************************************************
if test "$perl" = yes; then
AC_PATH_PROG(perlpath, perl)
AC_MSG_CHECKING(for Perl compile flags)
PERL_CFLAGS=`$perlpath -MExtUtils::Embed -e ccopts 2>/dev/null`
if test "_$PERL_CFLAGS" = _ ; then
AC_MSG_RESULT([not found, building without perl.])
perl=no
else
PERL_LDFLAGS=`$perlpath -MExtUtils::Embed -e ldopts |$sedpath 's/-lgdbm //'`
PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-ldb //'`
PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lndbm //'`
if test "$system" = "Linux"; then
PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lnsl //'`
PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lposix //'`
fi
PERL_LDFLAGS=`echo $PERL_LDFLAGS |$sedpath 's/-lc //'`
AC_MSG_RESULT(ok)
# oldLIBS=$LIBS
# LIBS="$LIBS $PERL_LDFLAGS"
# AC_CHECK_FUNC(eval_pv)
# AC_CHECK_FUNC(call_pv)
# LIBS=$oldLIBS
AC_MSG_CHECKING(for perl >= 5.8.0)
PERL_VER=`$perlpath -e 'print $]>= 5.008?"yes":"no"'`
if test "$PERL_VER" = "yes"; then
AC_MSG_RESULT(yes)
AC_MSG_CHECKING(if perl plugin will be backward compatible)
if test "$perl_old" = "yes"; then
AC_MSG_RESULT(yes)
AC_DEFINE(OLD_PERL)
else
AC_MSG_RESULT(no)
fi
else
AC_MSG_RESULT(no)
echo "perl version too old, building without perl."
perl=no
fi
fi
fi
dnl *********************************************************************
dnl ** PYTHON ***********************************************************
dnl *********************************************************************
if test "$python" = yes; then
AC_PATH_PROG(pythonpath, python2)
if test "_$pythonpath" = _ ; then
AC_PATH_PROG(pythonpath, python)
fi
if test "_$pythonpath" = _ ; then
python=no
else
AC_MSG_CHECKING(Python version)
changequote(<<, >>)dnl
PY_VER=`$pythonpath -c 'import distutils.sysconfig; print distutils.sysconfig.get_config_vars("VERSION")[0];'`
PY_LIB=`$pythonpath -c 'import distutils.sysconfig; print distutils.sysconfig.get_python_lib(standard_lib=1);'`
PY_INC=`$pythonpath -c 'import distutils.sysconfig; print distutils.sysconfig.get_config_vars("INCLUDEPY")[0];'`
$pythonpath -c "import sys; map(int,sys.version[:3].split('.')) >= [2,2] or sys.exit(1)"
changequote([, ])dnl
AC_MSG_RESULT($PY_VER)
if test "$?" != "1"; then
AC_MSG_CHECKING(Python compile flags)
PY_PREFIX=`$pythonpath -c 'import sys; print sys.prefix'`
PY_EXEC_PREFIX=`$pythonpath -c 'import sys; print sys.exec_prefix'`
if test -f $PY_INC/Python.h; then
PY_LIBS="-L$PY_LIB/config -lpython$PY_VER -lpthread -lutil"
PY_CFLAGS="-I$PY_INC"
AC_MSG_RESULT(ok)
else
python=no
AC_MSG_RESULT([Can't find Python.h])
fi
else
echo "Python too old. Only 2.2 or above is supported."
python=no
fi
fi
fi
dnl *********************************************************************
dnl ** TCL **************************************************************
dnl *********************************************************************
AC_MSG_CHECKING(for location of tclConfig.sh)
dirs="$tcl /lib /usr/lib /usr/tcl/lib /usr/lib/tcl8.4 /usr/local/lib /usr/local/tcl-8.4/lib /usr/local/tcl/lib /opt/lib /usr/lib/tcl8.3"
found=0
if test "$tcl" != "no"; then
tcl=no
for try in $dirs; do
if test -f $try/tclConfig.sh; then
found=1
. $try/tclConfig.sh
TCL_LIBS="$TCL_LIB_SPEC $TCL_LIBS"
TCL_CFLAGS="-I${TCL_PREFIX}/include $TCL_INCLUDE_SPEC"
tcl=yes
AC_MSG_RESULT($try/tclConfig.sh)
break
fi
done
if test "$found" -eq 0 ; then
AC_MSG_RESULT([tclConfig.sh not found - use the --enable-tcl option])
fi
fi
dnl *********************************************************************
dnl ** IPv6 *************************************************************
dnl *********************************************************************
dnl purely for Solaris
AC_CHECK_FUNC(select, ,
AC_CHECK_LIB(socket, select, ,
AC_CHECK_LIB(nsl, select, ,
AC_CHECK_LIB(inet, select, ,
AC_CHECK_LIB(cposix, select, ,
AC_CHECK_LIB(net, select, ,
AC_MSG_WARN(i can not find select. you might need to help me)))))))
AC_CHECK_LIB(socket, select)
if test "$ipv6" = yes; then
AC_CHECK_FUNCS(getaddrinfo, have_getaddrinfo=yes)
AC_MSG_CHECKING(whether to enable IPv6 support)
if test "$have_getaddrinfo" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE(USE_IPV6)
else
ipv6=no
AC_MSG_RESULT(no)
fi
fi
dnl *********************************************************************
dnl ** OPENSSL **********************************************************
dnl *********************************************************************
retry=no
if test "$openssl" != no; then
AC_PATH_PROG(pkgconfigpath, pkg-config)
AC_MSG_CHECKING(for openssl through pkg-config)
if $pkgconfigpath openssl --exists; then
CPPFLAGS="$CPPFLAGS `$pkgconfigpath openssl --cflags`"
LIBS="$LIBS `$pkgconfigpath openssl --libs`"
AC_DEFINE(USE_OPENSSL)
AC_MSG_RESULT(yes)
openssl=yes
else
AC_MSG_RESULT(no)
retry=yes
fi
fi
if test "$retry" = "yes"; then
unset openssl_path ac_cv_lib_ssl_SSL_new ac_cv_header_openssl_ssl_h
if test "$openssl" != yes; then
openssl_path=$openssl
fi
openssl=no
SAVED_LIBS=$LIBS
LIBS="$LIBS -lcrypto"
if test -n "$openssl_path"; then
LIBS="-L$openssl_path/lib $LIBS"
fi
AC_CHECK_LIB(ssl, SSL_new, have_openssl=yes)
LIBS=$SAVED_LIBS
if test "$have_openssl" = yes; then
SAVED_CPPFLAGS=$CPPFLAGS
if test -n "$openssl_path"; then
CPPFLAGS="-I$openssl_path/include $CPPFLAGS"
fi
AC_CHECK_HEADERS(openssl/ssl.h, have_openssl_h=yes)
if test "$have_openssl_h" = yes; then
openssl=yes
AC_DEFINE(USE_OPENSSL)
LIBS="$LIBS -lssl -lcrypto"
if test -n "$openssl_path"; then
LIBS="-L$openssl_path/lib $LIBS"
fi
else
CPPFLAGS=$SAVED_CPPFLAGS
fi
fi
fi
dnl *********************************************************************
dnl ** LIBPROXY *********************************************************
dnl *********************************************************************
PKG_CHECK_MODULES([LIBPROXY], [libproxy-1.0], [libproxy=1], [libproxy=0])
AC_DEFINE_UNQUOTED([USE_LIBPROXY], [$libproxy], [Use libproxy])
dnl *********************************************************************
dnl ** PLUGIN ***********************************************************
dnl *********************************************************************
if test "$plugin" = yes; then
AC_CHECK_FUNCS(dlopen, have_dl=yes)
if test "$have_dl" != yes; then
AC_CHECK_LIB(dl, dlopen, have_dl=yes)
if test "$have_dl" = yes; then
LIBS="$LIBS -ldl"
fi
fi
if test "$have_dl" = yes; then
AC_DEFINE(USE_PLUGIN)
AC_PATH_PROG(pkgconfigpath, pkg-config)
dnl we just need the -Wl,--export-dynamic, but not -lgmodule-2.0
RDYNAMIC_FLAGS="`$pkgconfigpath gmodule-2.0 --libs | $sedpath 's/ -lgmodule-2.0//'`"
LIBS="$LIBS $RDYNAMIC_FLAGS"
if test "$LD" = ""; then
VS="`ld --help | grep version-script 2> /dev/null`"
else
VS="`$LD --help | grep version-script 2> /dev/null`"
fi
if test "$VS" != ""; then
GUI_LIBS="$GUI_LIBS -Wl,--version-script,\$(srcdir)/../version-script"
fi
else
plugin=no
fi
fi
dnl #######################################################################
dnl # Check for DBUS libraries
dnl #######################################################################
if test "x$dbus" = "xyes" ; then
PKG_CHECK_MODULES(DBUS, [dbus-1 >= 0.60 dbus-glib-1 >= 0.60 gthread-2.0], dbus=yes, [
AC_MSG_RESULT(no)
dbus=no
])
AC_PATH_PROG(DBUS_BINDING_TOOL, dbus-binding-tool, no)
AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal, no)
if test "x$DBUS_BINDING_TOOL" = "xno" || test "x$GLIB_GENMARSHAL" = "xno" || test "x$dbus" = "xno" ; then
dbus="no"
else
COMMON_LIBS="$COMMON_LIBS $DBUS_LIBS $LIBPROXY_LIBS"
COMMON_CFLAGS="$COMMON_CFLAGS $DBUS_CFLAGS"
AC_DEFINE(USE_DBUS)
AS_AC_EXPAND(DATADIR, $datadir)
DBUS_SERVICES_DIR="$DATADIR/dbus-1/services"
AC_SUBST(DBUS_SERVICES_DIR)
AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Where services dir for DBUS is])
fi
fi
dnl *********************************************************************
dnl ** SPELL ************************************************************
dnl *********************************************************************
if test "$spell" = "gtkspell" ; then
PKG_CHECK_MODULES(GTKSPELL, gtkspell-2.0 >= 2.0.2, [], [
AC_MSG_RESULT(no)
spell=no
])
if test "$spell" != "no" ; then
GUI_LIBS="$GUI_LIBS $GTKSPELL_LIBS"
GUI_CFLAGS="$GUI_CFLAGS $GTKSPELL_CFLAGS"
AC_DEFINE(USE_GTKSPELL)
fi
fi
if test "$spell" = "libsexy" ; then
PKG_CHECK_MODULES([LIBSEXY], [libsexy >= 0.1.8], libsexy=yes, AC_MSG_RESULT(no))
if test "$libsexy" = "yes" ; then
GUI_LIBS="$GUI_LIBS $LIBSEXY_LIBS"
GUI_CFLAGS="$GUI_CFLAGS $LIBSEXY_CFLAGS"
AC_DEFINE(USE_LIBSEXY)
else
dnl use builtin static one
spell="static"
fi
fi
if test "$spell" = "static" ; then
AC_DEFINE(USE_LIBSEXY)
fi
dnl *********************************************************************
dnl ** CONDITIONALS *****************************************************
dnl *********************************************************************
AM_CONDITIONAL(USE_OPENSSL, test "x$openssl" = "xyes")
AM_CONDITIONAL(USE_LIBSEXY, test "x$spell" = "xstatic")
AM_CONDITIONAL(DO_TEXT, test "x$textfe" = "xyes")
AM_CONDITIONAL(DO_GTK, test "x$gtkfe" = "xyes")
AM_CONDITIONAL(DO_PERL, test "x$perl" = "xyes")
AM_CONDITIONAL(DO_PYTHON, test "x$python" = "xyes")
AM_CONDITIONAL(DO_TCL, test "x$tcl" = "xyes")
AM_CONDITIONAL(DO_PLUGIN, test "x$plugin" = "xyes")
AM_CONDITIONAL(USE_DBUS, test "x$dbus" = "xyes")
AM_CONDITIONAL(DO_GCONF, test "x$GCONFTOOL" != "xno")
dnl *********************************************************************
dnl ** SOCKS5 ***********************************************************
dnl *********************************************************************
if test "$socks" = yes; then
socks=no
AC_CHECK_LIB(socks5, SOCKSconnect, have_socks=yes)
if test "$have_socks" = yes; then
AC_CHECK_HEADERS(socks.h, have_socks_h=yes)
if test "$have_socks_h" = yes; then
socks=yes
AC_DEFINE(SOCKS)
LIBS="$LIBS -lsocks5"
fi
fi
fi
dnl *********************************************************************
dnl ** MS PROXY *********************************************************
dnl *********************************************************************
have_ntlm="no"
if test "x$ntlm" = "xyes" ; then
have_ntlm="no"
AC_CHECK_LIB(ntlm, ntlm_smb_encrypt, have_ntlm=yes)
if test "$have_ntlm" = yes; then
LIBS="$LIBS -lntlm"
AC_DEFINE(USE_MSPROXY)
fi
fi
dnl *********************************************************************
dnl ** XShm *************************************************************
dnl *********************************************************************
if test "$shm" = yes; then
oldl=$LIBS
oldc=$CPPFLAGS
LIBS="$LIBS `$pkgconfigpath --libs-only-L xft`"
CPPFLAGS="$CPPFLAGS `$pkgconfigpath --cflags-only-I xft`"
shm=no
AC_CHECK_LIB(Xext, XShmAttach, shm=yes)
if test "$shm" = yes; then
shm=no
AC_CHECK_HEADERS(sys/ipc.h, shm=yes)
if test "$shm" = yes; then
shm=no
AC_CHECK_HEADERS(sys/shm.h, shm=yes)
fi
fi
LIBS=$oldl
if test "$shm" = yes; then
GUI_LIBS="$GUI_LIBS `$pkgconfigpath --libs-only-L xft` -lX11 -lXext"
AC_DEFINE(USE_SHM)
else
CPPFLAGS=$oldc
fi
fi
dnl *********************************************************************
dnl ** MMX **************************************************************
dnl *********************************************************************
dnl we don't need mmx on *this* machine, just i386, because
dnl it's checked at runtime.
if test "$mmx" = "yes"; then
case $host_cpu in
i386|i486|i586|i686|i786|k6|k7)
mmx=yes
;;
*)
mmx=no
esac
if test "$system" = "OpenBSD"; then
dnl openbsd fails because mmx_cmod doesn't prefix its symbols with underscore.
dnl xtext.o: Undefined symbol `_shade_ximage_15_mmx' referenced from text segment
mmx=no
fi
if test "$mmx" = "yes"; then
AC_DEFINE(USE_MMX)
fi
fi
AM_CONDITIONAL(USE_MMX, test "$mmx" = "yes")
dnl *********************************************************************
dnl ** GCC FLAGS ********************************************************
dnl *********************************************************************
dnl Only use -Wall and -pipe if we have gcc
if test "x$GCC" = "xyes"; then
if test -z "`echo "$CFLAGS" | grep "\-Wall" 2> /dev/null`" ; then
CFLAGS="$CFLAGS -Wall"
fi
if test "$system" = "Linux" -o "$system" = "FreeBSD"; then
if test -z "`echo "$CFLAGS" | grep "\-pipe" 2> /dev/null`" ; then
CFLAGS="$CFLAGS -pipe"
fi
fi
if test -z "`echo "$CFLAGS" | grep "\-g " 2> /dev/null`" ; then
CFLAGS="$CFLAGS -g"
fi
fi
dnl does this compiler support -Wno-pointer-sign ?
AC_MSG_CHECKING([if gcc accepts -Wno-pointer-sign ])
safe_CFLAGS=$CFLAGS
CFLAGS="-Wno-pointer-sign"
AC_TRY_COMPILE(, [
int main () { return 0 ; }
],
[
no_pointer_sign=yes
AC_MSG_RESULT([yes])
], [
no_pointer_sign=no
AC_MSG_RESULT([no])
])
CFLAGS=$safe_CFLAGS
if test x$no_pointer_sign = xyes; then
CFLAGS="$CFLAGS -Wno-pointer-sign"
fi
dnl does this compiler support -funsigned-char ?
AC_MSG_CHECKING([if gcc accepts -funsigned-char ])
safe_CFLAGS=$CFLAGS
CFLAGS="-funsigned-char"
AC_TRY_COMPILE(, [
int main () { return 0 ; }
],
[
unsigned_char=yes
AC_MSG_RESULT([yes])
], [
unsigned_char=no
AC_MSG_RESULT([no])
])
CFLAGS=$safe_CFLAGS
if test x$unsigned_char = xyes; then
CFLAGS="$CFLAGS -funsigned-char"
fi
dnl *********************************************************************
dnl ** FUNCTIONS/LIBS/CFLAGS ********************************************
dnl *********************************************************************
AC_MSG_CHECKING(for modern sigaction)
dnl libc5 on linux and FreeBSD 3.x doesn't have siginfo_t
dnl and the sa_sigation field.
AC_TRY_COMPILE(
[#include <signal.h>],
[struct sigaction act;
siginfo_t *si;
act.sa_sigaction = 0;],
[
AC_MSG_RESULT(yes)
AC_DEFINE(USE_SIGACTION)
],
AC_MSG_RESULT(no))
AC_PATH_PROG(gdkpixbufcsourcepath, gdk-pixbuf-csource)
AC_SUBST(gdkpixbufcsourcepath)
if test "$gtkfe" != no -a "_$gdkpixbufcsourcepath" = _; then
AC_MSG_ERROR("Cannot find gdk-pixbuf-csource: Install GTK+ 2.0\!")
fi
dnl if we don't have this, use g_snprintf instead
AC_CHECK_FUNCS(snprintf vsnprintf memrchr strtoull)
AC_CHECK_FUNC(gethostbyname, ,
AC_CHECK_LIB(resolv, gethostbyname, ,
AC_CHECK_LIB(nsl, gethostbyname)))
AC_CHECK_FUNC(gethostname, , AC_CHECK_LIB(nsl, gethostname))
dnl necessary for IRIX
AC_CHECK_HEADERS(strings.h)
dnl Check for type in sys/socket.h - from Squid source (GPL)
AC_CACHE_CHECK(for socklen_t, ac_cv_type_socklen_t, [
AC_EGREP_CPP([socklen_t[^a-zA-Z_0-9]], [#include <sys/types.h>
#include <sys/socket.h>
#if STDC_HEADERS
#include <stdlib.h>
#include <stddef.h>
#endif],
ac_cv_type_socklen_t=yes,
ac_cv_type_socklen_t=no)
])
if test $ac_cv_type_socklen_t = no; then
AC_DEFINE(socklen_t, int)
fi
dnl Mac OS X and Darwin use lookupd, which caches DNS queries by default
AC_EGREP_CPP(lookupd, dnl
[#if (defined(__APPLE__) && defined(__MACH__))
lookupd
#endif], AC_DEFINE([LOOKUPD],1,[Define to 1 if the system uses lookupd]))
dnl freebsd needs this
LIBS="$LIBS $INTLLIBS"
CFLAGS="$CFLAGS $CPPFLAGS"
GUI_LIBS="$GUI_LIBS $COMMON_LIBS"
dnl make these visible to all Makefiles
AC_SUBST(GUI_LIBS)
AC_SUBST(GUI_CFLAGS)
AC_SUBST(COMMON_LIBS)
AC_SUBST(COMMON_CFLAGS)
AC_SUBST(PERL_CFLAGS)
AC_SUBST(PERL_LDFLAGS)
AC_SUBST(PY_CFLAGS)
AC_SUBST(PY_LIBS)
AC_SUBST(TCL_LIBS)
AC_SUBST(TCL_CFLAGS)
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
PLUGIN_INCLUDES='-I$(top_srcdir)/plugins'
AC_SUBST(PLUGIN_INCLUDES)
dnl for plugin.c and pixmaps.c
test "x$prefix" = xNONE && prefix="$ac_default_prefix"
test "x$exec_prefix" = xNONE && exec_prefix="$prefix"
AC_DEFINE_UNQUOTED(PREFIX, "${prefix}")
XCHATLIBDIR=`eval echo ${libdir}/xchat`
AC_DEFINE_UNQUOTED(XCHATLIBDIR, "$XCHATLIBDIR")
XCHATSHAREDIR=`eval echo ${datadir}`
AC_DEFINE_UNQUOTED(XCHATSHAREDIR, "$XCHATSHAREDIR")
dnl for plugins/xxx/Makefile.am
xchatlibdir=${libdir}/xchat
AC_SUBST(xchatlibdir)
AC_OUTPUT([
Makefile
src/Makefile
src/common/Makefile
src/common/dbus/Makefile
src/fe-text/Makefile
src/fe-gtk/Makefile
src/pixmaps/Makefile
plugins/Makefile
plugins/python/Makefile
plugins/perl/Makefile
plugins/tcl/Makefile
intl/Makefile
po/Makefile.in
])
echo
echo xchat $VERSION
echo
echo Building GTK+ Interface .... : $gtkfe
echo Building TEXT Interface .... : $textfe
echo
echo PLUGINS: Perl: $perl Python: $python TCL: $tcl
echo
echo mmx tinting ......... : $mmx\ spelling .............. : $spell
echo XShm tinting ........ : $shm\ plugin interface ...... : $plugin
if test "$xft" = no; then
echo text backend ........ : pango\ nls/gettext ........... : $USE_NLS
else
echo text backend ........ : xft\ nls/gettext ........... : $USE_NLS
fi
echo openssl support ..... : $openssl\ ipv6 support .......... : $ipv6
echo dbus support ........ : $dbus\ msproxy ntlm \(ISA\) .... : $have_ntlm
echo
echo The binary will be installed in $prefix/bin
echo
if test "$gtkfe" = no; then
echo Warning: The GTK \(GUI\) frontend will not be built.
echo
fi
if test "$spell" = "gtkspell"; then
echo Warning: GTK SPELL is not the recommended spelling library.
echo
fi
echo configure complete, now type \'make\' and pray.
echo

537
faq.html Normal file
View File

@ -0,0 +1,537 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<title>XCHAT FAQ</title>
<style type="text/css">
<!--
body {
font-family: sans-serif;
background-color: #FFFBF0;
}
h2 { color: #336701;
background-color: #F4F0E5;
}
h3 { color: #005A9C;
background-color: #F0EAE1;
}
a:link { color: blue; }
p { margin: 3% }
-->
</style>
</head>
<body>
<h1>X-Chat 2.8 Frequently Asked Questions</h1>
<h2>1. Section One: Compiling and Installing.</h2>
<p>
<a href="#q11">1. I get this error: /bin/sh: no: command not found</a>
<br><br>
<a href="#q12">2. How do I compile X-Chat on my Sun OS system?</a>
<br><br>
</p>
<h2>2. Section Two: Using X-Chat.</h2>
<p>
<a href="#q21">1. How do I enable identd in X-Chat? (How do I get rid of the ~ in front of my username?)</a>
<br><br>
<a href="#q22">2. How do I auto join more than one channel with keys?</a>
<br><br>
<a href="#q23">3. How do I autoconnect and join a channel when X-Chat loads?</a>
<br><br>
<a href="#q24">4. How do I cut and paste in X-Chat?</a>
<br><br>
<a href="#q25">5. How do I connect through a proxy?</a>
<br><br>
<a href="#q26">6. How do I show @ and + in front of nicknames that are Op and Voice when they talk?</a>
<br><br>
<a href="#q27">7. How do I change the Op and Voice userlist icons and Tree View icons?</a>
<br><br>
<a href="#q28">8. How do I set different ban types?</a>
<br><br>
<a href="#q29">9. Why can't I see accented-letters/umlauts/upper-ascii-chars in X-Chat?</a>
<br><br>
<a href="#q210">10. Why does the timestamp overlap some nicknames?</a>
<br><br>
<a href="#q211">11. How do I turn on Conference mode where I will not see join or part messages?</a>
<br><br>
<a href="#q212">12. How can I run the /dccserver command?</a>
<br><br>
<a href="#q213">13. Why doesn't DCC send work behind a router (IPNat/ADSL)?</a>
<br><br>
<a href="#q214">14. How do I execute multiple commands in one line?</a>
<br><br>
<a href="#q215">15. How do I enable Emacs key bindings in XChat?</a>
<br><br>
<a href="#q216">16. I get this error: "Unknown file type abc.yz. Maybe you need to install the Perl or Python plugin?"</a>
<br><br>
<a href="#q217">17. How do I play sound files on certain events?</a>
<br><br>
<a href="#q218">18. How do I auto-load scripts at startup?</a>
<br><br>
<a href="#q219">19. How do I minimize X-Chat to the System Tray (Notification Area)?</a>
<br><br>
<a href="#q220">20. Can I select and copy text with the time stamps?</a>
<br><br>
<a href="#q221">21. What's the deal with opening URLs in XChat on Linux/Unix?</a>
<br><br>
<a href="#q222">22. Where are the log files saved to?</a>
<br><br>
<a href="#q223">23. How do I rotate log files every so often?</a>
<br><br>
<a href="#q224">24. How do I enable graphical smilies (emoticons)?</a>
<br><br>
</p>
<h2>3. Section Three: Contributions, Development and Bugs.</h2>
<p>
<a href="#q31">1. Why does X-Chat leak so much memory?</a>
<br><br>
<a href="#q32">2. My copy of X-Chat crashes, what can I do?</a>
<br><br>
<a href="#q33">3. Can I write a new language translation for X-Chat?</a>
</p>
<br><br>
<h2>1. Section One: Compiling and Installing.</h2>
<br><h3><a name="q11">1. I get this error: /bin/sh: no: command not found</a></h3>
<p>
If you get an error something like:
</p>
<blockquote><pre>
Making all in po
make[2]: Entering directory `/home/zed/xchat/files/xchat-1.8.7/po'
file=./`echo ca | sed 's,.*/,,'`.gmo \
&amp;&amp; rm -f $file &amp;&amp; PATH=../src:$PATH no -o $file ca.po
/bin/sh: no: command not found
make[2]: *** [ca.gmo] Error 127
make[2]: Leaving directory `/home/zed/xchat/files/xchat-1.8.7/po'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/zed/xchat/files/xchat-1.8.7'
make: *** [all-recursive-am] Error 2
</pre></blockquote>
<p>
It means you don't have GNU gettext installed. There are two solutions:
</p>
<ul>
<li>Install GNU gettext and try again.</li>
<li>Use <i>./configure --disable-nls</i>. This will disable foreign
language support and all menus and GUI will be in English only.</li>
</ul>
<br><h3><a name="q12">2. How do I compile X-Chat on my Sun OS system?</a></h3>
<p>
X-Chat uses GNU gettext which in turn requires gmake, either install that
and or use ./configure --disable-nls with Sun's own make.
</p>
<br><h2>2. Section Two: Using X-Chat.</h2>
<br><h3><a name="q21">1. How do I enable identd in X-Chat?</a></h3>
<p>
<u>UNIX:</u><br>
Identd isn't actually apart of X-Chat. You will need to download and install
your own ident server. Most distributions, including Fedora, come with an
ident server program called oidentd. Make sure it is enabled in
/etc/xinetd.conf or read you distribution's documentation.
As an alternative, you can try this experimental identd server: <a href="http://xchat.org/auth/">xchat_auth</a>
<br><br><u>WINDOWS:</u><br>
The win32 version of X-Chat comes with a built-in identd server. It is
enabled by default, but can be disabled with <i>/set identd 0</i>.
</p>
<br><h3><a name="q22">2. How do I auto join more than one channel with keys?</a></h3>
<p>
In the Server list's channel column enter multiple channels and separate
them by commas, eg: "#linux,#warez,#chat". Do not put spaces between the
channels. If the channels also have keys (passwords), then the syntax is:
"#channel1,#channel2,#channel3 key1,key2,key3"
</p>
<p>
Example: If you want to join #abc and #talk without keys, but #linux with
a key of "secret", you would enter: "#linux,#abc,#talk secret".
</p>
<br><h3><a name="q23">3. How do I autoconnect and join a channel when X-Chat loads?</a></h3>
<p>
In the Server list, select the Network you want to auto-connect to, click Edit
and turn ON the "Auto connect to this network at startup" checkbox.
</p>
<br><h3><a name="q24">4. How do I cut and paste in X-Chat?</a></h3>
<p>
It's exactly the same as any other X application. You simply mark the text
you want, and then press middle mouse button to paste (if you only have a
2 button mouse, press left and right buttons at once).
</p>
<br><h3><a name="q25">5. How do I connect through a proxy?</a></h3>
<p>
Go to the menus, Settings -> Preferences -> Network Setup and fill in the requested
information there. Authentication (using a username and password) is
only supported for HTTP and Socks5.
</p>
<br><h3><a name="q26">6. How do I show @ and + in front of nicknames that are Op and Voice when they talk?</a></h3>
<p>
To display @ and + characters next to nicknames as they talk, do the following:
</p>
<p>
In the menus, open up Settings -> Advanced -> Text Events. Find the
<i>Channel Message</i> event in the list. The $3 code can be inserted to
print the user's mode-character (e.g. @ or +). For example, you might want
to change the default:
<br><br>%C18%H&lt;%H$4$1%H>%H%O$t$2<br><br>To:
<br><br>%C18%H&lt;%H$4<b>$3</b>$1%H>%H%O$t$2
<br><br>Don't forget to press Enter, so the changes take effect in the
list at the top of the window.
</p>
<br><h3><a name="q27">7. How do I change the Op and Voice userlist icons and Tree View icons?</a></h3>
<p>
<u>Unix/Linux</u>
<br>The default icons are hard coded (compiled) in. You can override them by creating
some PNG files in ${PREFIX}/share/xchat. ${PREFIX} is usually /usr, so that
would translate to /usr/share/xchat. If you compiled from source tarball without
specifying a prefix, it will be /usr/local instead.
<br>
<br>
<u>Windows</u>
<br>Your own custom icons can be placed in C:\Program Files\XChat\Icons. Image format
may be PNG or ICO. PNG support on Windows 2000 may require installing GDI+, but it's
standard on XP or newer.
</p>
<blockquote>
<table border="1" cellpadding="3" rules="all">
<tr bgcolor="#dddddd"><td>Name</td><td>Description</td></tr>
<tr><td>op.png</td><td>Userlist: Op</td></tr>
<tr><td>hop.png</td><td>Userlist: Half-Op</td></tr>
<tr><td>voice.png</td><td>Userlist: Voice</td></tr>
<tr><td>red.png</td><td>Userlist: Owner</td></tr>
<tr><td>purple.png</td><td>Userlist: Founder</td></tr>
<tr><td></td><td></td></tr>
<tr><td>server.png</td><td>Tree: Server</td></tr>
<tr><td>channel.png</td><td>Tree: Channel</td></tr>
<tr><td>dialog.png</td><td>Tree: Dialog/Query</td></tr>
<tr><td>util.png</td><td>Tree: Utility (Channel List, DCC etc)</td></tr>
<tr><td></td><td></td></tr>
<tr><td>message.png</td><td>Tray: Message</td></tr>
<tr><td>highlight.png</td><td>Tray: Highlighted Message</td></tr>
<tr><td>fileoffer.png</td><td>Tray: DCC</td></tr>
<tr><td></td><td></td></tr>
<tr><td>xchat.png</td><td>Main XChat icon</td></tr>
</table>
</blockquote>
<br><b>Tree View icons</b>: Type <b>/set tab_icons 1</b> to enable them and then restart XChat.
<br>
<br><h3><a name="q28">8. How do I set different ban types?</a></h3>
<p>
Three ways:
</p>
<ul>
<li>
Right click the nickname in the userlist, and choose a ban type from the
"Kick/Ban" submenu.
</li>
<li>
You can also do it manually:
/ban &lt;nick> &lt;ban type>
where the &lt;ban type> is a number from 0 to 3.
</li>
<li>
/set irc_ban_type &lt;ban type>
sets the default ban type to use for all bans. The different types are:
<ul>
<li>0 *!*@*.host</li>
<li>1 *!*@domain</li>
<li>2 *!*user@*.host</li>
<li>3 *!*user@domain</li>
</ul>
</li>
</ul>
<br><h3><a name="q29">9. Why can't I see accented-letters/umlauts/upper-ascii-chars in X-Chat?</a></h3>
<p>
Refer to <a href="http://xchat.org/encoding/">http://xchat.org/encoding/</a>.<br>
Note: Log files are always written in UTF-8/Unicode.
</p>
<br><h3><a name="q210">10. Why does the timestamp overlap some nicknames?</a></h3>
<p>
Some networks allow very long nicknames (up to 32 letters). It can be annoying to have
the separator bar move too far to the right, just for one long nick. Therefore, it has
a set limit for the distance it will move to the right. If you use a large font, you
may need to adjust this distance. It is set in pixels, for example:
</p>
<blockquote><pre>
/set text_max_indent 320
</pre></blockquote>
<p>
Once you adjust this setting high enough, overlapping timestamps and nicknames should
not occur. The adjustment will not take effect immediately, a restart may be needed.
</p>
<br><h3><a name="q211">11. How do I turn on Conference mode where I will not see join or part messages?</a></h3>
<p>
Right-click on the tab you want to change. In the submenu of the channel
name, there's a toggle-item "Show join/part messages", simply turn this off.
</p><p>If you want to turn this option on globally, type:</p>
<blockquote><pre>/set irc_conf_mode 1</pre></blockquote>
<p>Then all channels you join after setting this will start with "Show join/part messages" turned off.</p>
<br><h3><a name="q212">12. How can I run the /dccserver command?</a></h3>
<p>
In short you can not do this (easily). This is a mIRC only proprietary feature
that is quite nonstandard. There is no code for doing this, mainly because
/dccserver runs on port 59 which in turn would require running X-Chat as
root. Why do you need this anyway? Just use normal DCC.
<br><br>
Unofficial unix <a href="http://dfx.at/xchat/">patches are available here</a>.
<br><br><u><b>Update</b></u>: DCC Server feature has been added in the official Windows release 2.4.1b.
</p>
<br><h3><a name="q213">13. Why doesn't DCC send work behind a router (IPNat/ADSL)?</a></h3>
<p>
If you are behind a IP-NAT or ADSL router, you will most likely have
an address like 192.168.0.1. This address is not usable on the Internet, and
must be translated.
</p><p>
When offering a DCC file, xchat will tell the receiver your address. If it says
192.168.0.1, the receiver will not be able to connect. One way to make it send
your "real" address is to enable the "Get my IP from IRC Server" option in xchat.
This option is available in Preferences -> File Transfers. When you turn it
ON, you will have to re-login to the server before it'll take effect.
</p><p>
You will also need to forward some ports for use in DCC send. You may pick almost
any port range you wish, for example, in xchat set:
</p>
<pre> <b>First DCC send port</b>: 4990
<b>Last DCC send port</b>: 5000
</pre>
<p>
This will allow you to send up to ten files at the same time, which should be plenty
for most people. Lastly, configure your router/modem to forward ports 4990-5000 to
your PC's address. You'll have to consult your router/modem's manual on how to do this.
</p>
<br><h3><a name="q214">14. How do I execute multiple commands in one line?</a></h3>
<p>
There are three ways to do this:
</p>
<ul>
<li>/LOAD -e &lt;textfile>, where &lt;textfile> is a full pathname to a file
containing commands on each line.</li>
<li>
Separate your commands with CTRL-SHIFT-u-a (CTRL-SHIFT-a on older GTK+ and Windows). This will appear as a little box with numbers on it.</li>
<li>You can create two UserCommands, with the same name, and then execute
the UserCommand. It will be executed in the same order as it's written
in the UserCommands GUI.</li>
</ul>
<br><h3><a name="q215">15. How do I enable Emacs key bindings in XChat?</a></h3>
<p>
The standard Emacs key bindings, such as CTRL-w, CTRL-u etc, are supported by
GTK+ 2.0, but normally disabled. If you run Gnome 2, you can re-enable them in
your Gnome menu under: Preferences -> Keyboard Shortcuts.
</p>
<p>
<i>Note</i>: This doesn't work in the latest Gnome (2.8 and newer). In this case, you need
to run "gconf-editor", and directly change the key /desktop/gnome/interface/gtk_key_theme
from "Default" to "Emacs". Then you need to re-start XChat.
</p>
<p>
If you don't use Gnome 2, but still want Emacs key bindings, it's beyond the
scope of this document. You might find some hints here:
<a href="http://www.gtk.org/gtk-2.4.0-notes.html">GTK+ 2.4.0 release notes</a>.
</p>
<br><h3><a name="q216">16. I get this error: "Unknown file type abc.yz. Maybe you need to install the Perl or Python plugin?"</a></h3>
<p>
If you get this error when trying to load a Perl or Python script, it means
the plugin for running those scripts isn't loaded.
</p>
<ul>
<li>The Perl, Python and TCL plugins come with XChat in the same archive.</li>
<li>During ./configure, it will check for Perl, Python and TCL libs and headers, you should check if it failed there.</li>
<li>The plugins directory can be found by issuing the shell command
<pre>xchat -p</pre>
</li>
<li>All *.so files are auto-loaded at startup (*.dll on Windows).</li>
<li>If you downloaded a binary package, maybe the packager decided to exclude the Perl or Python plugins.</li>
</ul>
<br><h3><a name="q217">17. How do I play sound files on certain events?</a></h3>
<p>
In the menus, go to: Settings > Preferences > Sound.
Select the event you want to make a sound on, then type in a
sound filename (or use the Browse button).
</p>
<br><h3><a name="q218">18. How do I auto-load scripts at startup?</a></h3>
<p>
You just have to place the scripts into XChat's data directory. XChat
will auto-load scripts if they have the right extension .e.g If a filename
ends in .pl, it will be loaded as a Perl script.
This data directory is different on each platform:
<br><br>
<u>Windows</u>
<br><br>
It depends on your version of Windows and where it stores the
<i><b>Application Data</b></i> folder. On Windows XP it is usually:
<br><br>
C:\Documents and Settings\<i><b>username</b></i>\Application Data\X-Chat 2\
<br><b>or simply:</b>
<br>
C:\Program Files\XChat\Plugins\
<br><br><br>
<u>UNIX</u>
<br><br>
~/.xchat2/
Where "~" represents your home directory i.e.: $HOME/.xchat2/
</p>
<br><h3><a name="q219">19. How do I minimize X-Chat to the System Tray (Notification Area)?</a></h3>
<p>
There are two plugins available that allow this:
<br>Unix: <a href="http://www.blight.tk/">SysTray Plugin</a>
<br>Windows: <a href="http://www.sinisterdevelopments.com/">xTray</a>
</p>
<p>
Note that XChat 2.8.0+ has its own tray feature, but you can disable it
in <b>Settings &gt; Preferences &gt; Alerts</b> and still run these plugins, if you prefer.
</p>
<br><h3><a name="q220">20. Can I select and copy text with the time stamps?</a></h3>
<p>
Yes, but this requires at least XChat 2.6.3. Simply hold down SHIFT while marking
the text and the time stamps will be included.
</p>
<br><h3><a name="q221">21. What's the deal with opening URLs in XChat on Unix/Linux?</a></h3>
<p>
Right-clicking on a URL and selecting <i>Open Link in Browser</i> will open the link
in your "preferred browser". In Gnome, your preferred browser can be changed in System > Preferences > More Preferences > Preferred Applications.
<br><br>
<b><u>Notes for 2.8.0 or newer:</u></b>
<br><br>
Everything should just work automatically without any changes from you. Here's how the current
logic works:
</p>
<ul>
<li>First, it tries to run xdg-open, which is a universal URL handler from freedesktop.org. Most modern Linux desktops will have this now, or in the near future.</li>
<li>If xdg-open doesn't exist, it will try to detect a running Gnome or KDE desktop. This is done via the environment variables GNOME_DESKTOP_SESSION_ID and KDE_FULL_SESSION.</li>
<li>If Gnome is detected, it will execute: gnome-open &lt;url></li>
<li>If KDE is detected, it will execute: kfmclient exec &lt;url></li>
</ul>
<p>
<b><u>Notes for 2.6.8 or older:</u></b>
<br><br>
If you're not using Gnome, e.g KDE or some other desktop environment, you're fresh out of luck!
<br><u>Note for Debian and Ubuntu</u>: Integration with Gnome is broken on this distro! Please set
<i>sensible-browser</i> instead. We have no control over what the Debian packagers do, so complain
to them for this screw up. Example:
<i>sudo update-alternatives --set x-www-browser /usr/bin/firefox</i>
<br><br>
<b><u>More details</u></b>
<br><br>
While holding down CTRL you can single left-click a URL to open it in your preferred browser. If you really want to change this to plain left-click you can type: <b>/set gui_url_mod 0</b>, provided you have XChat 2.6.6 or newer.
<br><br>
You can also add more items to the right-click menu in XChat: <b>Settings &gt; Advanced &gt; URL Handlers</b>.
<br>For example, you could add an entry like <b>!firefox -a firefox -remote 'openURL(%s,new-tab)'</b>
<br>But this kind of messing around shouldn't be necessary, it just works automatically in Gnome, KDE and Windows with 2.8.0+!
</p>
<br><h3><a name="q222">22. Where are the log files saved to?</a></h3>
<p>
<u>UNIX</u>
<br>
<br>~/.xchat2/xchatlogs/
<br>where ~ represents your home directory.
<br>
<br>
<br><u>Windows</u>
<br>
<br><b>Windows XP/2000</b>: C:\Documents and Settings\<i><b>username</b></i>\Application Data\X-Chat 2\xchatlogs
<br><b>Windows Vista/7</b>: C:\Users\<i><b>username</b></i>\AppData\Roaming\X-Chat 2\xchatlogs
</p>
<br><h3><a name="q223">23. How do I rotate log files every so often?</a></h3>
<p>
Requires: 2.6.1+
<br><br>
By default settings, no rotation occurs, your log files will just keep getting larger.
<br><br>
Go to <b>Settings</b> &gt; <b>Preferences</b> &gt; <b>Logging</b> and change the log filename to any one of these:
</p>
<blockquote>
<table border="1" cellpadding="6" rules="all">
<tr><td><b>Setting</b></td><td><b>Example filename that would be written</b></td></tr>
<tr><td>%Y-%m-%d/%n-%c.log&nbsp;</td><td>2006-12-30/FreeNode-#channel.log</td></tr>
<tr><td>%n/%Y-%m-%d/%c.log</td><td>FreeNode/2006-12-30/#channel.log</td></tr>
<tr><td>%n/%c.log</td><td>FreeNode/#channel.log (no rotation)</td></tr>
</table>
</blockquote>
<p>
%Y, %m and %d represents the current year, month and day respectively. %n is the
network name, e.g. "FreeNode" or "UnderNet", and finally, %c is the channel. In these
examples, a new log filename and folder would be created after midnight.
<br><br>
You can find more possibilities at <a href="http://xchat.org/docs/log/">http://xchat.org/docs/log/</a>.
</p>
<br><h3><a name="q224">24. How do I enable graphical smilies (emoticons)?</a></h3>
<p>
This feature is only available in the official Windows XChat release. You have to
TICK this feature during installation. If you didn't do this, you can simply run
the installer again, and TICK the "<b>Eye Candy Theme</b>" when given the option.
</p><p>
If you want to use the graphical theme, but disable it just for smilies (i.e leave
it ON for things like Join/Part, Modes etc only), type this command and restart:
<br><br>
<b>/set text_emoticons off</b>
</p>
<br><h2>3. Section Three: Contributions, Development and Bugs.</h2>
<br><h3><a name="q31">1. Why does X-Chat leak so much memory?</a></h3>
<p>
The simple answer is, it doesn't! There are some GTK+ pixmap based themes around that
leak a lot of memory. Please try using a different theme and see if that resolves the
problem. X-Chat itself only allocates about 40kb of memory through malloc()!
</p>
<br><h3><a name="q32">2. My copy of X-Chat crashes, what can I do?</a></h3>
<p>
Firstly, make sure it's the latest stable version of X-Chat. Stable versions have
an EVEN middle number, e.g.: 2.8.0 or 2.8.1. Often late fixes are placed in this
directory: <a href="http://xchat.org/files/source/2.8/patches/">2.8.x patches</a>
</p><p>
If you still experience crashes, you should consider running it through GDB. This
will help us find a fix quickly, and it's easy to do! See <a href="http://xchat.org/gdb/">here</a>.
</p>
<br><h3><a name="q33">3. Can I write a new language translation for X-Chat?</a></h3>
<p>
You sure can, but I don't accept translations directly. They must be done through the
<a href="http://translationproject.org/domain/xchat.html">Translation Project</a>.
All the relevant information should be on that page.
</p>
</body>
</html>

38
plugins/Make.plugin Normal file
View File

@ -0,0 +1,38 @@
# Makefile stub for creating standalone plugin distributions.
plugin_dist: pg_dist pg_dist/config.status
pgi=`cd $(srcdir)/.. && pwd`; cd pg_dist; \
$(MAKE) $(AM_MAKEFLAGS) PLUGIN_INCLUDES=-I$$pgi distcheck dist
pg_dist: pg_distdir pg_dist/configure.in pg_dist/install-sh
cd pg_dist \
&& libtoolize --copy --force --automake \
&& automake --copy --add-missing --foreign \
&& autoconf -l ../$(top_srcdir)
pg_distdir: $(DISTFILES)
test -d pg_dist || mkdir pg_dist
for dfile in $(DISTFILES); do \
test -f $$dfile && cp $$dfile pg_dist \
|| test -f $(srcdir)/$$dfile && cp $(srcdir)/$$dfile pg_dist; done
sed '/Make.plugin/d' < $(srcdir)/Makefile.am > pg_dist/Makefile.am
pg_dist/configure.in: $(srcdir)/../plugin-conf.in
rm -f pg_dist/configure.in
test -f $(srcdir)/config.stub \
&& cat $(srcdir)/config.stub > pg_dist/configure.in || true
cat $(srcdir)/../plugin-conf.in | \
sed 's%@PLUGIN_VERSION@%$(PLUGIN_VERSION)%; \
s%@PLUGIN@%$(PLUGIN)%' >> pg_dist/configure.in
pg_dist/install-sh: pg_distdir
cp $(top_srcdir)/install-sh pg_dist
pg_dist/config.status: pg_dist/configure
cd pg_dist \
&& test -f config.status && $(SHELL) ./config.status --recheck \
|| $(SHELL) ./configure --enable-maintainer-mode
DISTCLEANFILES = pg_dist/* pg_dist
#

21
plugins/Makefile.am Normal file
View File

@ -0,0 +1,21 @@
# temp. solution while mailcheck & xdcc arn't in SUBDIRS
EXTRA_DIST = plugin20.html Make.plugin plugin-conf.in \
xdcc/xdcc.c \
xdcc/Makefile.am
noinst_HEADERS = xchat-plugin.h
if DO_PYTHON
pythondir = python
endif
if DO_PERL
perldir = perl
endif
if DO_TCL
tcldir = tcl
endif
#SUBDIRS = . $(pythondir) $(perldir) mailcheck xdcc
SUBDIRS = . $(pythondir) $(perldir) $(tcldir)

View File

@ -0,0 +1,25 @@
## Process with automake to produce Makefile.in
# To create a standalone tarball of your plugin run the plugin_dist
# target. Note: you must configure the main source tree with
# --enable-maintainer-mode
# These two must be defined.
PLUGIN=mailcheck
PLUGIN_VERSION=0.1
# This file must be in the form PLUGIN-config.h.in, it can be empty but
# must exist
EXTRA_DIST = mailcheck-config.h.in
# Remember to include this line in your Makefile.am
include @top_srcdir@/plugins/Make.plugin
libdir = $(xchatdir)/plugins
lib_LTLIBRARIES = mailcheck.la
mailcheck_la_SOURCES = mailcheck.c
mailcheck_la_LDFLAGS = -avoid-version -module
INCLUDES = $(COMMON_CFLAGS) $(PLUGIN_INCLUDES)
DISTCLEANFILES = pg_dir/*

View File

@ -0,0 +1,94 @@
/* XCHAT 2.0 PLUGIN: Mail checker */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "xchat-plugin.h"
static xchat_plugin *ph; /* plugin handle */
static int
mail_items(char *file)
{
FILE *fp;
int items;
char buf[512];
fp = fopen(file, "r");
if(!fp)
return 1;
items = 0;
while(fgets(buf, sizeof buf, fp))
{
if(!strncmp(buf, "From ", 5))
items++;
}
fclose(fp);
return items;
}
static void
xchat_mail_check (void)
{
static int last_size = -1;
int size;
struct stat st;
char buf[512];
char *maildir;
maildir = getenv("MAIL");
if(!maildir)
{
snprintf (buf, sizeof(buf), "/var/spool/mail/%s", getenv("USER"));
maildir = buf;
}
if(stat(maildir, &st) < 0)
return;
size = st.st_size;
if(last_size == -1)
{
last_size = size;
return;
}
if(size > last_size)
{
xchat_printf(ph,
"-\0033-\0039-\017\tYou have new mail (%d messages, %d bytes total).",
mail_items(maildir), size);
}
last_size = size;
}
static int timeout_cb(void *userdata)
{
xchat_mail_check();
return 1;
}
int xchat_plugin_init(xchat_plugin *plugin_handle,
char **plugin_name, char **plugin_desc, char **plugin_version,
char *arg)
{
ph = plugin_handle;
*plugin_name = "MailCheck";
*plugin_desc = "Checks your mailbox every 30 seconds";
*plugin_version = "0.1";
xchat_hook_timer(ph, 30000, timeout_cb, 0);
return 1;
}

20
plugins/perl/Makefile.am Normal file
View File

@ -0,0 +1,20 @@
EXTRA_DIST=alt_completion.pl xchat2-perldocs.html xchat2-perl.html \
generate_header lib/Xchat.pm lib/Xchat/Embed.pm lib/Xchat/List/Network.pm \
lib/Xchat/List/Network/Entry.pm lib/Xchat/List/Network/AutoJoin.pm \
lib/IRC.pm
libdir = $(xchatlibdir)/plugins
lib_LTLIBRARIES = perl.la
perl_la_SOURCES = perl.c
perl_la_LDFLAGS = -avoid-version -module
perl_la_LIBADD = $(PERL_LDFLAGS)
BUILT_SOURCES = xchat.pm.h irc.pm.h
#CFLAGS = @CFLAGS@ -Wno-unused
INCLUDES = $(PERL_CFLAGS) $(COMMON_CFLAGS) -I$(srcdir)/..
CLEANFILES = xchat.pm.h irc.pm.h
xchat.pm.h irc.pm.h: lib/Xchat.pm lib/Xchat/Embed.pm \
lib/Xchat/List/Network.pm lib/Xchat/List/Network/Entry.pm \
lib/Xchat/List/Network/AutoJoin.pm lib/IRC.pm
perl generate_header

View File

@ -0,0 +1,507 @@
use strict;
use warnings;
use Xchat ();
use File::Spec ();
use File::Basename qw(fileparse);
# if the last time you addressed someone was greater than this many minutes
# ago, ignore it
# this avoids having people you have talked to a long time ago coming up too
# early in the completion list
# Setting this to 0 will disable the check which is effectively the same as
# setting it to infinity
my $last_use_threshold = 10; # 10 minutes
# added to the front of a completion the same way as a suffix, only if
# the word is at the beginning of the line
my $prefix = '';
# ignore leading non-alphanumeric characters: -[\]^_`{|}
# Assuming you have the following nicks in a channel:
# [SomeNick] _SomeNick_ `SomeNick SomeNick SomeOtherNick
# when $ignore_leading_non_alnum is set to 0
# s<tab> will cycle through SomeNick and SomeOtherNick
# when $ignore_leading_non_alnum is set to 1
# s<tab> will cycle through [SomeNick] _SomeNick_ `SomeNick SomeNick
# SomeOtherNick
my $ignore_leading_non_alnum = 0;
# enable path completion
my $path_completion = 1;
my $base_path = '';
Xchat::register(
"Tab Completion", "1.0401", "Alternative tab completion behavior"
);
Xchat::hook_print( "Key Press", \&complete );
Xchat::hook_print( "Close Context", \&close_context );
Xchat::hook_print( "Focus Tab", \&focus_tab );
Xchat::hook_print( "Part", \&clean_selected );
Xchat::hook_print( "Part with Reason", \&clean_selected );
Xchat::hook_command( "", \&track_selected );
sub SHIFT() { 1 }
sub CTRL() { 4 }
sub ALT() { 8 }
sub TAB() { 0xFF09 }
sub LEFT_TAB() { 0xFE20 }
my %completions;
my %last_visit;
my %selected;
my %escape_map = (
'[' => qr![\[{]!,
'{' => qr![\[{]!,
'}' => qr![\]}]!,
']' => qr![\]}]!,
'\\' => qr![\\\|]!,
'|' => qr![\\\|]!,
'.' => qr!\.!,
'^' => qr!\^!,
'$' => qr!\$!,
'*' => qr!\*!,
'+' => qr!\+!,
'?' => qr!\?!,
'(' => qr!\(!,
')' => qr!\)!,
'-' => qr!\-!,
);
my $escapes = join "", keys %escape_map;
$escapes = qr/[\Q$escapes\E]/;
# used to determine if a word is the start of a path
my $path_pattern = qr{^(?:~|/|[[:alpha:]]:\\)};
sub complete {
my ($key, $modifiers) = @{$_[0]};
# if $_[0][0] contains the value of the key pressed
# $_[0][1] contains modifiers
# the value for tab is 0xFF09
# the value for shift-tab(Left Tab) is 0xFE20
# we don't care about other keys
# the key must be a tab and left tab
return Xchat::EAT_NONE unless $key == TAB || $key == LEFT_TAB;
# if it is a tab then it must not have any modifiers
return Xchat::EAT_NONE if $key == TAB && $modifiers & (CTRL|ALT|SHIFT);
# loop backwards for shift+tab/left tab
my $delta = $modifiers & SHIFT ? -1 : 1;
my $context = Xchat::get_context;
$completions{$context} ||= {};
my $completions = $completions{$context};
$completions->{pos} ||= -1;
my $suffix = Xchat::get_prefs( "completion_suffix" );
$suffix =~ s/^\s+//;
my $input = Xchat::get_info( "inputbox" );
my $cursor_pos = Xchat::get_info( "state_cursor" );
my $left = substr( $input, 0, $cursor_pos );
my $right = substr( $input, $cursor_pos );
my $length = length $left;
# trim spaces from the end of $left to avoid grabbing the wrong word
# this is mainly needed for completion at the very beginning where a space
# is added after the completion
$left =~ s/\s+$//;
# always add one to the index because
# 1) if a space is found we want the position after it
# 2) if a space isn't found then we get back -1
my $word_start = rindex( $left, " " ) + 1;
my $word = substr( $left, $word_start );
$left = substr( $left, 0, -length $word );
if( $cursor_pos == $completions->{pos} ) {
my $previous_word = $completions->{completed};
my $new_left = $input;
substr( $new_left, $cursor_pos ) = "";
if( $previous_word and $new_left =~ s/(\Q$previous_word\E)$// ) {
$word = $1;
$word_start = length( $new_left );
$left = $new_left;
}
}
my $command_char = Xchat::get_prefs( "input_command_char" );
# ignore commands
if( ($word !~ m{^[${command_char}]})
or ( $word =~ m{^[${command_char}]} and $word_start != 0 ) ) {
if( $cursor_pos == length $input # end of input box
# not a valid nick char
&& $input =~ /(?<![\x41-\x5A\x61-\x7A\x30-\x39\x5B-\x60\x7B-\x7D-])$/
&& $cursor_pos != $completions->{pos} # not continuing a completion
&& $word !~ m{^(?:[&#/~]|[[:alpha:]]:\\)} # not a channel or path
) {
# check for path completion
unless( $path_completion and $word =~ $path_pattern ) {
$word_start = $cursor_pos;
$left = $input;
$length = length $length;
$right = "";
$word = "";
}
}
if( $word_start == 0 && $prefix && $word =~ /^\Q$prefix/ ) {
$word =~ s/^\Q$prefix//;
}
my $completed; # this is going to be the "completed" word
# for parital completions and channel names so a : isn't added
#$completions->{skip_suffix} = ($word =~ /^[&#]/) ? 1 : 0;
# continuing from a previous completion
if(
exists $completions->{matches} && @{$completions->{matches}}
&& $cursor_pos == $completions->{pos}
&& $word =~ /^\Q$completions->{matches}[$completions->{index}]/
) {
$completions->{index} += $delta;
if( $completions->{index} < 0 ) {
$completions->{index} += @{$completions->{matches}};
} else {
$completions->{index} %= @{$completions->{matches}};
}
} else {
if( $word =~ /^[&#]/ ) {
# channel name completion
$completions->{matches} = [ matching_channels( $word ) ];
$completions->{skip_suffix} = 0;
} elsif( $path_completion and $word =~ $path_pattern ) {
# file name completion
$completions->{matches} = [ matching_files( $word ) ];
$completions->{skip_suffix} = 1;
} else {
# nick completion
# fix $word so { equals [, ] equals }, \ equals |
# and escape regex metacharacters
$word =~ s/($escapes)/$escape_map{$1}/g;
$completions->{matches} = [ matching_nicks( $word ) ];
$completions->{skip_suffix} = 0;
}
$completions->{index} = 0;
}
$completed = $completions->{matches}[ $completions->{index} ];
$completions->{completed} = $completed;
my $completion_amount = Xchat::get_prefs( "completion_amount" );
# don't cycle if the number of possible completions is greater than
# completion_amount
if(
@{$completions->{matches}} > $completion_amount
&& @{$completions->{matches}} != 1
) {
# don't print if we tabbed in the beginning and the list of possible
# completions includes all nicks in the channel
my $context_type = Xchat::context_info->{type};
if( $context_type != 2 # not a channel
or @{$completions->{matches}} < Xchat::get_list("users")
) {
Xchat::print( join " ", @{$completions->{matches}}, "\n" );
}
$completed = lcs( $completions->{matches} );
$completions->{skip_suffix} = 1;
}
if( $completed ) {
if( $word_start == 0 && !$completions->{skip_suffix} ) {
# at the start of the line append completion suffix
Xchat::command( "settext $prefix$completed$suffix$right");
$completions->{pos} = length( "$prefix$completed$suffix" );
} else {
Xchat::command( "settext $left$completed$right" );
$completions->{pos} = length( "$left$completed" );
}
Xchat::command( "setcursor $completions->{pos}" );
}
=begin
# debugging stuff
local $, = " ";
my $input_length = length $input;
Xchat::print [
qq{input[$input]},
qq{input_length[$input_length]},
qq{cursor[$cursor_pos]},
qq{start[$word_start]},
qq{length[$length]},
qq{left[$left]},
qq{word[$word]}, qq{right[$right]},
qq{completed[}. ($completed||""). qq{]},
qq{pos[$completions->{pos}]},
];
use Data::Dumper;
local $Data::Dumper::Indent = 0;
Xchat::print Dumper $completions->{matches};
=cut
return Xchat::EAT_ALL;
} else {
return Xchat::EAT_NONE;
}
}
# all channels starting with $word
sub matching_channels {
my $word = shift;
# for use in compare_channels();
our $current_chan;
local $current_chan = Xchat::get_info( "channel" );
my $conn_id = Xchat::get_info( "id" );
$word =~ s/^[&#]+//;
return
map { $_->[1]->{channel} }
sort compare_channels map {
my $chan = $_->{channel};
$chan =~ s/^[#&]+//;
# comparisons will be done based only on the name
# matching name, same connection, only channels
$chan =~ /^$word/i && $_->{id} == $conn_id ?
[ $chan, $_ ] :
()
} channels();
}
sub channels {
return grep { $_->{type} == 2 } Xchat::get_list( "channels" );
}
sub compare_channels {
# package variable, value set in matching_channels()
our $current_chan;
# turn off warnings generated from channels that have not yet been visited
# since the script was loaded
no warnings "uninitialized";
# the current channel is always first, then ordered by most recently visited
return
$a->[1]{channel} eq $current_chan ? -1 :
$b->[1]{channel} eq $current_chan ? 1 :
$last_visit{ $b->[1]{context} } <=> $last_visit{ $a->[1]{context} }
|| $a->[1]{channel} cmp $b->[1]{channel};
}
sub matching_nicks {
my $word_re = shift;
# for use in compare_nicks()
our ($my_nick, $selections, $now);
local $my_nick = Xchat::get_info( "nick" );
local $selections = $selected{ Xchat::get_context() };
local $now = time;
my $pattern = $ignore_leading_non_alnum ?
qr/^[\-\[\]^_`{|}\\]*$word_re/i : qr/^$word_re/i;
return
map { $_->{nick} }
sort compare_nicks grep {
$_->{nick} =~ $pattern;
} Xchat::get_list( "users" )
}
sub max {
return unless @_;
my $max = shift;
for(@_) {
$max = $_ if $_ > $max;
}
return $max;
}
sub compare_times {
# package variables set in matching_nicks()
our $selections;
our $now;
for my $nick ( $a->{nick}, $b->{nick} ) {
# turn off the warnings that get generated from users who have yet
# to speak since the script was loaded
no warnings "uninitialized";
if( $last_use_threshold
&& (( $now - $selections->{$nick}) > ($last_use_threshold * 60)) ) {
delete $selections->{ $nick }
}
}
my $a_time = $selections->{ $a->{nick} } || 0 ;
my $b_time = $selections->{ $b->{nick} } || 0 ;
if( $a_time || $b_time ) {
return $b_time <=> $a_time;
} elsif( !$a_time && !$b_time ) {
return $b->{lasttalk} <=> $a->{lasttalk};
}
}
sub compare_nicks {
# more package variables, value set in matching_nicks()
our $my_nick;
# our own nick is always last, then ordered by the people we spoke to most
# recently and the people who were speaking most recently
return
$a->{nick} eq $my_nick ? 1 :
$b->{nick} eq $my_nick ? -1 :
compare_times()
|| Xchat::nickcmp( $a->{nick}, $b->{nick} );
# $selections->{ $b->{nick} } <=> $selections->{ $a->{nick} }
# || $b->{lasttalk} <=> $a->{lasttalk}
}
sub matching_files {
my $word = shift;
my ($file, $input_dir) = fileparse( $word );
my $dir = expand_tilde( $input_dir );
if( opendir my $dir_handle, $dir ) {
my @files;
if( $file ) {
@files = grep {
#Xchat::print( $_ );
/^\Q$file/ } readdir $dir_handle;
} else {
@files = readdir $dir_handle;
}
return map {
File::Spec->catfile( $input_dir, $_ );
} sort
grep { !/^[.]{1,2}$/ } @files;
} else {
return ();
}
}
# Remove completion related data for tabs that are closed
sub close_context {
my $context = Xchat::get_context;
delete $completions{$context};
delete $last_visit{$context};
return Xchat::EAT_NONE;
}
# track visit times
sub focus_tab {
$last_visit{Xchat::get_context()} = time();
return Xchat::EAT_NONE;
}
# keep track of the last time a message was addressed to someone
# a message is considered addressed to someone if their nick is used followed
# by the completion suffix
sub track_selected {
my $input = $_[1][0];
return Xchat::EAT_NONE unless defined $input;
my $suffix = Xchat::get_prefs( "completion_suffix" );
for( grep defined, $input =~ /^(.+)\Q$suffix/, $_[0][0] ) {
if( in_channel( $_ ) ) {
$selected{Xchat::get_context()}{$_} = time();
last;
}
}
return Xchat::EAT_NONE;
}
# if a user is in the current channel
# user_info() can also be used instead of the loop
sub in_channel {
my $target = shift;
for my $nick ( nicks() ) {
if( $nick eq $target ) {
return 1;
}
}
return 0;
}
# list of nicks in the current channel
sub nicks {
return map { $_->{nick} } Xchat::get_list( "users" );
}
# remove people from the selected list when they leave the channel
sub clean_selected {
delete $selected{ Xchat::get_context() }{$_[0][0]};
return Xchat::EAT_NONE;
}
# Longest common substring
# Used for partial completion when using non-cycling completion
sub lcs {
my @nicks = @{+shift};
return "" if @nicks == 0;
return $nicks[0] if @nicks == 1;
my $substring = shift @nicks;
while(@nicks) {
$substring = common_string( $substring, shift @nicks );
}
return $substring;
}
sub common_string {
my ($nick1, $nick2) = @_;
my $index = 0;
$index++ while(
($index < length $nick1) && ($index < length $nick2) &&
lc(substr( $nick1, $index, 1 )) eq lc(substr( $nick2, $index, 1 ))
);
return substr( $nick1, 0, $index );
}
sub expand_tilde {
my $file = shift;
$file =~ s/^~/home_dir()/e;
return $file;
}
sub home_dir {
return $base_path if $base_path;
if ( $^O eq "MSWin32" ) {
return $ENV{USERPROFILE};
} else {
return ((getpwuid($>))[7] || $ENV{HOME} || $ENV{LOGDIR});
}
}

101
plugins/perl/char_count.pl Normal file
View File

@ -0,0 +1,101 @@
use strict;
use warnings;
use Xchat qw(:all);
use Glib qw(TRUE FALSE);
use Gtk2 -init;
sub get_inputbox {
my $widget = Glib::Object->new_from_pointer( get_info( "win_ptr" ), 0 );
my $input_box;
my @containers = ($widget);
while( @containers ) {
my $container = shift @containers;
for my $child ( $container->get_children ) {
if( $child->get( "name" ) eq 'xchat-inputbox' ) {
$input_box = $child;
last;
} elsif( $child->isa( "Gtk2::Container" ) ) {
push @containers, $child;
}
}
}
return $input_box;
}
sub get_hbox {
my $widget = shift;
my $hbox;
while( $widget->parent ) {
if( $widget->parent->isa( "Gtk2::HBox" ) ) {
return $widget->parent;
}
$widget = $widget->parent;
}
}
my $input_box = get_inputbox();
if( $input_box ) {
my $hbox = get_hbox( $input_box );
if( $hbox ) {
my $label = Gtk2::Label->new();
$label->set_alignment( 0.5, ($label->get_alignment)[1] );
$hbox->pack_end( $label, 0, 0, 5 );
$label->show();
my $update_label = sub {
my $ctx_type = context_info->{"type"};
hook_timer( 0, sub {
if( $ctx_type == 2 || $ctx_type == 3 ) {
my $count = length get_info "inputbox";
$label->set_text( $count ? $count : "" );
} else {
$label->set_text( "" );
}
return REMOVE;
});
return EAT_NONE;
};
hook_print( "Key Press", $update_label );
hook_print( "Focus Tab", $update_label );
hook_print( "Focus Window", $update_label );
hook_command( "",
sub {
$label->set_text( "" );
return EAT_NONE;
}
);
my @handlers;
my $buffer = $input_box->get_buffer;
my $handler = sub { $update_label->(); return TRUE };
if( $buffer->isa( "Gtk2::TextBuffer" ) ) {
push @handlers, $buffer->signal_connect( "changed", $handler );
} elsif( $buffer->isa( "Gtk2::EntryBuffer" ) ) {
push @handlers,
$buffer->signal_connect( "deleted-text", $handler );
$buffer->signal_connect( "inserted-text", $handler );
}
register( "Character Counter", "1.0.0",
"Display the number of characters in the inputbox",
sub {
$hbox->remove( $label );
$buffer->signal_handler_disconnect( $_ ) for @handlers;
}
);
} else {
prnt "Counldn't find hbox";
}
} else {
prnt "Couldn't fint input box";
}

View File

@ -0,0 +1,50 @@
#!/usr/bin/perl
use strict;
use warnings;
sub header {
my $file = shift;
open my $input, "<", $file or die "Couldn't open '$file':$!";
my @file = <$input>;
close $file;
return toc(@file);
}
sub toc {
my @lines = @_;
for( @lines ) {
if( /^\s*$/s ) { $_ = qq{"\\n"\n}; next; }
if( /^\s*#/ ) { $_ = qq{"\\n"\n}; next; }
s/\\/\\\\/g; # double the number of \'s
s/"/\\"/g;
s/^\s*/"/;
s/\n/\\n"\n/;
}
return @lines;
}
for my $files (
[ "xchat.pm.h", # output file
"lib/Xchat.pm", # input files
"lib/Xchat/Embed.pm",
"lib/Xchat/List/Network.pm",
"lib/Xchat/List/Network/Entry.pm",
"lib/Xchat/List/Network/AutoJoin.pm",
],
[ "irc.pm.h", # output file
"lib/IRC.pm" # input file
]
) {
my ($output,@inputs) = @$files;
open my $header, ">", $output or die "Couldn't open '$output': $!";
for my $input ( @inputs ) {
print $header qq["{\\n"\n];
print $header qq{"#line 1 \\"$input\\"\\n"\n};
print $header header( $input );
print $header qq["}\\n"\n];
}
close $header;
}

View File

@ -0,0 +1,27 @@
#!/usr/bin/env perl
use strict;
use warnings;
use File::Basename qw(dirname);
sub __DIR__ {
return dirname +(caller 0)[1];
}
# this must go before use Pod::Html to use our private copy
use lib __DIR__ . '/lib';
use Pod::Html;
chdir( __DIR__ ) or die $!;
pod2html(
# "pod2html",
"--header",
"--infile=lib/Xchat.pod",
"--outfile=xchat2-perl.html",
);
#system( qw(tidy -m -i -xml -utf8 -quiet xchat2-perl.html) );
unlink( "pod2htmd.tmp" );
unlink( "pod2htmi.tmp" );
exec( "./syntax_highlight", "xchat2-perl.html" )
or die $!;

257
plugins/perl/lib/IRC.pm Normal file
View File

@ -0,0 +1,257 @@
package IRC;
sub IRC::register {
my ($script_name, $version, $callback) = @_;
my $package = caller;
$callback = Xchat::Embed::fix_callback( $package, $callback) if $callback;
Xchat::register( $script_name, $version, undef, $callback );
}
sub IRC::add_command_handler {
my ($command, $callback) = @_;
my $package = caller;
$callback = Xchat::Embed::fix_callback( $package, $callback );
# starting index for word_eol array
# this is for compatibility with '' as the command
my $start_index = $command ? 1 : 0;
Xchat::hook_command( $command,
sub {
no strict 'refs';
return &{$callback}($_[1][$start_index]);
}
);
return;
}
sub IRC::add_message_handler {
my ($message, $callback) = @_;
my $package = caller;
$callback = Xchat::Embed::fix_callback( $package, $callback );
Xchat::hook_server( $message,
sub {
no strict 'refs';
return &{$callback}( $_[1][0] );
}
);
return;
}
sub IRC::add_print_handler {
my ($event, $callback) = @_;
my $package = caller;
$callback = Xchat::Embed::fix_callback( $package, $callback );
Xchat::hook_print( $event,
sub {
my @word = @{$_[0]};
no strict 'refs';
return &{$callback}( join( ' ', @word[0..3] ), @word );
}
);
return;
}
sub IRC::add_timeout_handler {
my ($timeout, $callback) = @_;
my $package = caller;
$callback = Xchat::Embed::fix_callback( $package, $callback );
Xchat::hook_timer( $timeout,
sub {
no strict 'refs';
&{$callback};
return 0;
}
);
return;
}
sub IRC::command {
my $command = shift;
if( $command =~ m{^/} ) {
$command =~ s{^/}{};
Xchat::command( $command );
} else {
Xchat::command( qq[say $command] );
}
}
sub IRC::command_with_channel {
my ($command, $channel, $server) = @_;
my $old_ctx = Xchat::get_context;
my $ctx = Xchat::find_context( $channel, $server );
if( $ctx ) {
Xchat::set_context( $ctx );
IRC::command( $command );
Xchat::set_context( $ctx );
}
}
sub IRC::command_with_server {
my ($command, $server) = @_;
my $old_ctx = Xchat::get_context;
my $ctx = Xchat::find_context( undef, $server );
if( $ctx ) {
Xchat::set_context( $ctx );
IRC::command( $command );
Xchat::set_context( $ctx );
}
}
sub IRC::dcc_list {
my @dccs;
for my $dcc ( Xchat::get_list( 'dcc' ) ) {
push @dccs, $dcc->{nick};
push @dccs, $dcc->{file} ? $dcc->{file} : '';
push @dccs, @{$dcc}{qw(type status cps size)};
push @dccs, $dcc->{type} == 0 ? $dcc->{pos} : $dcc->{resume};
push @dccs, $dcc->{address32};
push @dccs, $dcc->{destfile} ? $dcc->{destfile} : '';
}
return @dccs;
}
sub IRC::channel_list {
my @channels;
for my $channel ( Xchat::get_list( 'channels' ) ) {
push @channels, @{$channel}{qw(channel server)},
Xchat::context_info( $channel->{context} )->{nick};
}
return @channels;
}
sub IRC::get_info {
my $id = shift;
my @ids = qw(version nick channel server xchatdir away network host topic);
if( $id >= 0 && $id <= 8 && $id != 5 ) {
my $info = Xchat::get_info($ids[$id]);
return defined $info ? $info : '';
} else {
if( $id == 5 ) {
return Xchat::get_info( 'away' ) ? 1 : 0;
} else {
return 'Error2';
}
}
}
sub IRC::get_prefs {
return 'Unknown variable' unless defined $_[0];
my $result = Xchat::get_prefs(shift);
return defined $result ? $result : 'Unknown variable';
}
sub IRC::ignore_list {
my @ignores;
for my $ignore ( Xchat::get_list( 'ignore' ) ) {
push @ignores, $ignore->{mask};
my $flags = $ignore->{flags};
push @ignores, $flags & 1, $flags & 2, $flags & 4, $flags & 8, $flags & 16,
$flags & 32, ':';
}
return @ignores;
}
sub IRC::print {
Xchat::print( $_ ) for @_;
return;
}
sub IRC::print_with_channel {
Xchat::print( @_ );
}
sub IRC::send_raw {
Xchat::commandf( qq[quote %s], shift );
}
sub IRC::server_list {
my @servers;
for my $channel ( Xchat::get_list( 'channels' ) ) {
push @servers, $channel->{server} if $channel->{server};
}
return @servers;
}
sub IRC::user_info {
my $user;
if( @_ > 0 ) {
$user = Xchat::user_info( shift );
} else {
$user = Xchat::user_info();
}
my @info;
if( $user ) {
push @info, $user->{nick};
if( $user->{host} ) {
push @info, $user->{host};
} else {
push @info, 'FETCHING';
}
push @info, $user->{prefix} eq '@' ? 1 : 0;
push @info, $user->{prefix} eq '+' ? 1 : 0;
}
return @info;
}
sub IRC::user_list {
my ($channel, $server) = @_;
my $ctx = Xchat::find_context( $channel, $server );
my $old_ctx = Xchat::get_context;
if( $ctx ) {
Xchat::set_context( $ctx );
my @users;
for my $user ( Xchat::get_list( 'users' ) ) {
push @users, $user->{nick};
if( $user->{host} ) {
push @users, $user->{host};
} else {
push @users, 'FETCHING';
}
push @users, $user->{prefix} eq '@' ? 1 : 0;
push @users, $user->{prefix} eq '+' ? 1 : 0;
push @users, ':';
}
Xchat::set_context( $old_ctx );
return @users;
} else {
return;
}
}
sub IRC::user_list_short {
my ($channel, $server) = @_;
my $ctx = Xchat::find_context( $channel, $server );
my $old_ctx = Xchat::get_context;
if( $ctx ) {
Xchat::set_context( $ctx );
my @users;
for my $user ( Xchat::get_list( 'users' ) ) {
my $nick = $user->{nick};
my $host = $user->{host} || 'FETCHING';
push @users, $nick, $host;
}
Xchat::set_context( $old_ctx );
return @users;
} else {
return;
}
}
sub IRC::add_user_list {}
sub IRC::sub_user_list {}
sub IRC::clear_user_list {}
sub IRC::notify_list {}
sub IRC::perl_script_list {}
1

2399
plugins/perl/lib/Pod/Html.pm Normal file

File diff suppressed because it is too large Load Diff

506
plugins/perl/lib/Xchat.pm Normal file
View File

@ -0,0 +1,506 @@
BEGIN {
$INC{'Xchat.pm'} = 'DUMMY';
}
$SIG{__WARN__} = sub {
my $message = shift @_;
my ($package) = caller;
# redirect Gtk/Glib errors and warnings back to STDERR
my $message_levels = qr/ERROR|CRITICAL|WARNING|MESSAGE|INFO|DEBUG/i;
if( $message =~ /^(?:Gtk|GLib|Gdk)(?:-\w+)?-$message_levels/i ) {
print STDERR $message;
} else {
if( defined &Xchat::Internal::print ) {
Xchat::print( $message );
} else {
warn $message;
}
}
};
use File::Spec ();
use File::Basename ();
use File::Glob ();
use List::Util ();
use Symbol();
use Time::HiRes ();
use Carp ();
package Xchat;
use base qw(Exporter);
use strict;
use warnings;
sub PRI_HIGHEST ();
sub PRI_HIGH ();
sub PRI_NORM ();
sub PRI_LOW ();
sub PRI_LOWEST ();
sub EAT_NONE ();
sub EAT_XCHAT ();
sub EAT_PLUIN ();
sub EAT_ALL ();
sub KEEP ();
sub REMOVE ();
sub FD_READ ();
sub FD_WRITE ();
sub FD_EXCEPTION ();
sub FD_NOTSOCKET ();
sub get_context;
sub Xchat::Internal::context_info;
sub Xchat::Internal::print;
our %EXPORT_TAGS = (
constants => [
qw(PRI_HIGHEST PRI_HIGH PRI_NORM PRI_LOW PRI_LOWEST), # priorities
qw(EAT_NONE EAT_XCHAT EAT_PLUGIN EAT_ALL), # callback return values
qw(FD_READ FD_WRITE FD_EXCEPTION FD_NOTSOCKET), # fd flags
qw(KEEP REMOVE), # timers
],
hooks => [
qw(hook_server hook_command hook_print hook_timer hook_fd unhook),
],
util => [
qw(register nickcmp strip_code send_modes), # misc
qw(print prnt printf prntf command commandf emit_print), # output
qw(find_context get_context set_context), # context
qw(get_info get_prefs get_list context_info user_info), # input
],
);
$EXPORT_TAGS{all} = [ map { @{$_} } @EXPORT_TAGS{qw(constants hooks util)}];
our @EXPORT = @{$EXPORT_TAGS{constants}};
our @EXPORT_OK = @{$EXPORT_TAGS{all}};
sub register {
my $package = Xchat::Embed::find_pkg();
my $pkg_info = Xchat::Embed::pkg_info( $package );
my $filename = $pkg_info->{filename};
my ($name, $version, $description, $callback) = @_;
if( defined $pkg_info->{gui_entry} ) {
Xchat::print( "Xchat::register called more than once in "
. $pkg_info->{filename} );
return ();
}
$description = "" unless defined $description;
$pkg_info->{shutdown} = $callback;
unless( $name && $name =~ /[[:print:]\w]/ ) {
$name = "Not supplied";
}
unless( $version && $version =~ /\d+(?:\.\d+)?/ ) {
$version = "NaN";
}
$pkg_info->{gui_entry} =
Xchat::Internal::register( $name, $version, $description, $filename );
# keep with old behavior
return ();
}
sub _process_hook_options {
my ($options, $keys, $store) = @_;
unless( @$keys == @$store ) {
die 'Number of keys must match the size of the store';
}
my @results;
if( ref( $options ) eq 'HASH' ) {
for my $index ( 0 .. @$keys - 1 ) {
my $key = $keys->[$index];
if( exists( $options->{ $key } ) && defined( $options->{ $key } ) ) {
${$store->[$index]} = $options->{ $key };
}
}
}
}
sub hook_server {
return undef unless @_ >= 2;
my $message = shift;
my $callback = shift;
my $options = shift;
my $package = Xchat::Embed::find_pkg();
$callback = Xchat::Embed::fix_callback( $package, $callback );
my ($priority, $data) = ( Xchat::PRI_NORM, undef );
_process_hook_options(
$options,
[qw(priority data)],
[\($priority, $data)],
);
my $pkg_info = Xchat::Embed::pkg_info( $package );
my $hook = Xchat::Internal::hook_server(
$message, $priority, $callback, $data
);
push @{$pkg_info->{hooks}}, $hook if defined $hook;
return $hook;
}
sub hook_command {
return undef unless @_ >= 2;
my $command = shift;
my $callback = shift;
my $options = shift;
my $package = Xchat::Embed::find_pkg();
$callback = Xchat::Embed::fix_callback( $package, $callback );
my ($priority, $help_text, $data) = ( Xchat::PRI_NORM, undef, undef );
_process_hook_options(
$options,
[qw(priority help_text data)],
[\($priority, $help_text, $data)],
);
my $pkg_info = Xchat::Embed::pkg_info( $package );
my $hook = Xchat::Internal::hook_command(
$command, $priority, $callback, $help_text, $data
);
push @{$pkg_info->{hooks}}, $hook if defined $hook;
return $hook;
}
sub hook_print {
return undef unless @_ >= 2;
my $event = shift;
my $callback = shift;
my $options = shift;
my $package = Xchat::Embed::find_pkg();
$callback = Xchat::Embed::fix_callback( $package, $callback );
my ($priority, $run_after, $filter, $data) = ( Xchat::PRI_NORM, 0, 0, undef );
_process_hook_options(
$options,
[qw(priority run_after_event filter data)],
[\($priority, $run_after, $filter, $data)],
);
if( $run_after and $filter ) {
Carp::carp( "Xchat::hook_print's run_after_event and filter options are mutually exclusive, you can only use of them at a time per hook" );
return;
}
if( $run_after ) {
my $cb = $callback;
$callback = sub {
my @args = @_;
hook_timer( 0, sub {
$cb->( @args );
if( ref $run_after eq 'CODE' ) {
$run_after->( @args );
}
return REMOVE;
});
return EAT_NONE;
};
}
if( $filter ) {
my $cb = $callback;
$callback = sub {
my @args = @{$_[0]};
my $last_arg = @args - 1;
my @new = $cb->( \@args, $_[1], $event );
# a filter can either return the new results or it can modify
# @_ in place.
if( @new ) {
emit_print( $event, @new[ 0 .. $last_arg ] );
return EAT_ALL;
} elsif(
join( "\0", @{$_[0]} ) ne join( "\0", @args[ 0 .. $last_arg ] )
) {
emit_print( $event, @args[ 0 .. $last_arg ] );
return EAT_ALL;
}
return EAT_NONE;
};
}
my $pkg_info = Xchat::Embed::pkg_info( $package );
my $hook = Xchat::Internal::hook_print(
$event, $priority, $callback, $data
);
push @{$pkg_info->{hooks}}, $hook if defined $hook;
return $hook;
}
sub hook_timer {
return undef unless @_ >= 2;
my ($timeout, $callback, $data) = @_;
my $package = Xchat::Embed::find_pkg();
$callback = Xchat::Embed::fix_callback( $package, $callback );
if(
ref( $data ) eq 'HASH' && exists( $data->{data} )
&& defined( $data->{data} )
) {
$data = $data->{data};
}
my $pkg_info = Xchat::Embed::pkg_info( $package );
my $hook = Xchat::Internal::hook_timer( $timeout, $callback, $data, $package );
push @{$pkg_info->{hooks}}, $hook if defined $hook;
return $hook;
}
sub hook_fd {
return undef unless @_ >= 2;
my ($fd, $callback, $options) = @_;
return undef unless defined $fd && defined $callback;
my $fileno = fileno $fd;
return undef unless defined $fileno; # no underlying fd for this handle
my ($package) = Xchat::Embed::find_pkg();
$callback = Xchat::Embed::fix_callback( $package, $callback );
my ($flags, $data) = (Xchat::FD_READ, undef);
_process_hook_options(
$options,
[qw(flags data)],
[\($flags, $data)],
);
my $cb = sub {
my $userdata = shift;
return $userdata->{CB}->(
$userdata->{FD}, $userdata->{FLAGS}, $userdata->{DATA},
);
};
my $pkg_info = Xchat::Embed::pkg_info( $package );
my $hook = Xchat::Internal::hook_fd(
$fileno, $cb, $flags, {
DATA => $data, FD => $fd, CB => $callback, FLAGS => $flags,
}
);
push @{$pkg_info->{hooks}}, $hook if defined $hook;
return $hook;
}
sub unhook {
my $hook = shift @_;
my $package = shift @_;
($package) = caller unless $package;
my $pkg_info = Xchat::Embed::pkg_info( $package );
if( defined( $hook )
&& $hook =~ /^\d+$/
&& grep { $_ == $hook } @{$pkg_info->{hooks}} ) {
$pkg_info->{hooks} = [grep { $_ != $hook } @{$pkg_info->{hooks}}];
return Xchat::Internal::unhook( $hook );
}
return ();
}
sub _do_for_each {
my ($cb, $channels, $servers) = @_;
# not specifying any channels or servers is not the same as specifying
# undef for both
# - not specifying either results in calling the callback inthe current ctx
# - specifying undef for for both results in calling the callback in the
# front/currently selected tab
if( @_ == 3 && !($channels || $servers) ) {
$channels = [ undef ];
$servers = [ undef ];
} elsif( !($channels || $servers) ) {
$cb->();
return 1;
}
$channels = [ $channels ] unless ref( $channels ) eq 'ARRAY';
if( $servers ) {
$servers = [ $servers ] unless ref( $servers ) eq 'ARRAY';
} else {
$servers = [ undef ];
}
my $num_done = 0;
my $old_ctx = Xchat::get_context();
for my $server ( @$servers ) {
for my $channel ( @$channels ) {
if( Xchat::set_context( $channel, $server ) ) {
$cb->();
$num_done++
}
}
}
Xchat::set_context( $old_ctx );
return $num_done;
}
sub print {
my $text = shift @_;
return "" unless defined $text;
if( ref( $text ) eq 'ARRAY' ) {
if( $, ) {
$text = join $, , @$text;
} else {
$text = join "", @$text;
}
}
return _do_for_each(
sub { Xchat::Internal::print( $text ); },
@_
);
}
sub printf {
my $format = shift;
Xchat::print( sprintf( $format, @_ ) );
}
# make Xchat::prnt() and Xchat::prntf() as aliases for Xchat::print() and
# Xchat::printf(), mainly useful when these functions are exported
sub prnt {
goto &Xchat::print;
}
sub prntf {
goto &Xchat::printf;
}
sub command {
my $command = shift;
return "" unless defined $command;
my @commands;
if( ref( $command ) eq 'ARRAY' ) {
@commands = @$command;
} else {
@commands = ($command);
}
return _do_for_each(
sub { Xchat::Internal::command( $_ ) foreach @commands },
@_
);
}
sub commandf {
my $format = shift;
Xchat::command( sprintf( $format, @_ ) );
}
sub set_context {
my $context;
if( @_ == 2 ) {
my ($channel, $server) = @_;
$context = Xchat::find_context( $channel, $server );
} elsif( @_ == 1 ) {
if( defined $_[0] && $_[0] =~ /^\d+$/ ) {
$context = $_[0];
} else {
$context = Xchat::find_context( $_[0] );
}
} elsif( @_ == 0 ) {
$context = Xchat::find_context();
}
return $context ? Xchat::Internal::set_context( $context ) : 0;
}
sub get_info {
my $id = shift;
my $info;
if( defined( $id ) ) {
if( grep { $id eq $_ } qw(state_cursor id) ) {
$info = Xchat::get_prefs( $id );
} else {
$info = Xchat::Internal::get_info( $id );
}
}
return $info;
}
sub user_info {
my $nick = Xchat::strip_code(shift @_ || Xchat::get_info( "nick" ));
my $user;
for (Xchat::get_list( "users" ) ) {
if ( Xchat::nickcmp( $_->{nick}, $nick ) == 0 ) {
$user = $_;
last;
}
}
return $user;
}
sub context_info {
my $ctx = shift @_ || Xchat::get_context;
my $old_ctx = Xchat::get_context;
my @fields = (
qw(away channel charset host id inputbox libdirfs modes network),
qw(nick nickserv server topic version win_ptr win_status),
qw(xchatdir xchatdirfs state_cursor),
);
if( Xchat::set_context( $ctx ) ) {
my %info;
for my $field ( @fields ) {
$info{$field} = Xchat::get_info( $field );
}
my $ctx_info = Xchat::Internal::context_info;
@info{keys %$ctx_info} = values %$ctx_info;
Xchat::set_context( $old_ctx );
return %info if wantarray;
return \%info;
} else {
return undef;
}
}
sub get_list {
unless( grep { $_[0] eq $_ } qw(channels dcc ignore notify users networks) ) {
Carp::carp( "'$_[0]' does not appear to be a valid list name" );
}
if( $_[0] eq 'networks' ) {
return Xchat::List::Network->get();
} else {
return Xchat::Internal::get_list( $_[0] );
}
}
sub strip_code {
my $pattern = qr<
\cB| #Bold
\cC\d{0,2}(?:,\d{1,2})?| #Color
\e\[(?:\d{1,2}(?:;\d{1,2})*)?m| # ANSI color code
\cG| #Beep
\cO| #Reset
\cV| #Reverse
\c_ #Underline
>x;
if( defined wantarray ) {
my $msg = shift;
$msg =~ s/$pattern//g;
return $msg;
} else {
$_[0] =~ s/$pattern//g if defined $_[0];
}
}
1

1326
plugins/perl/lib/Xchat.pod Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,253 @@
package Xchat::Embed;
use strict;
use warnings;
# list of loaded scripts keyed by their package names
our %scripts;
sub load {
my $file = expand_homedir( shift @_ );
my $package = file2pkg( $file );
if( exists $scripts{$package} ) {
my $pkg_info = pkg_info( $package );
my $filename = File::Basename::basename( $pkg_info->{filename} );
Xchat::printf(
qq{'%s' already loaded from '%s'.\n},
$filename, $pkg_info->{filename}
);
Xchat::print(
'If this is a different script then it rename and try '.
'loading it again.'
);
return 2;
}
if( open my $source_handle, $file ) {
my $source = do {local $/; <$source_handle>};
close $source_handle;
# we shouldn't care about things after __END__
$source =~ s/^__END__.*//ms;
if(
my @replacements = $source =~
m/^\s*package ((?:[^\W:]+(?:::)?)+)\s*?;/mg
) {
if ( @replacements > 1 ) {
Xchat::print(
"Too many package defintions, only 1 is allowed\n"
);
return 1;
}
my $original_package = shift @replacements;
# remove original package declaration
$source =~ s/^(package $original_package\s*;)/#$1/m;
# fixes things up for code calling subs with fully qualified names
$source =~ s/${original_package}:://g;
}
# this must come before the eval or the filename will not be found in
# Xchat::register
$scripts{$package}{filename} = $file;
$scripts{$package}{loaded_at} = Time::HiRes::time();
my $full_path = File::Spec->rel2abs( $file );
$source =~ s/^/#line 1 "$full_path"\n\x7Bpackage $package;/;
# make sure we add the closing } even if the last line is a comment
if( $source =~ /^#.*\Z/m ) {
$source =~ s/^(?=#.*\Z)/\x7D/m;
} else {
$source =~ s/\Z/\x7D/;
}
_do_eval( $source );
unless( exists $scripts{$package}{gui_entry} ) {
$scripts{$package}{gui_entry} =
Xchat::Internal::register(
"", "unknown", "", $file
);
}
if( $@ ) {
# something went wrong
$@ =~ s/\(eval \d+\)/$file/g;
Xchat::print( "Error loading '$file':\n$@\n" );
# make sure the script list doesn't contain false information
unload( $scripts{$package}{filename} );
return 1;
}
} else {
Xchat::print( "Error opening '$file': $!\n" );
return 2;
}
return 0;
}
sub _do_eval {
no strict;
no warnings;
eval $_[0];
}
sub unload {
my $file = shift @_;
my $package = file2pkg( $file );
my $pkg_info = pkg_info( $package );
if( $pkg_info ) {
# take care of the shutdown callback
if( exists $pkg_info->{shutdown} ) {
# allow incorrectly written scripts to be unloaded
eval {
if( ref $pkg_info->{shutdown} eq 'CODE' ) {
$pkg_info->{shutdown}->();
} elsif ( $pkg_info->{shutdown} ) {
no strict 'refs';
&{$pkg_info->{shutdown}};
}
};
}
if( exists $pkg_info->{hooks} ) {
for my $hook ( @{$pkg_info->{hooks}} ) {
Xchat::unhook( $hook, $package );
}
}
if( exists $pkg_info->{gui_entry} ) {
plugingui_remove( $pkg_info->{gui_entry} );
}
Symbol::delete_package( $package );
delete $scripts{$package};
return Xchat::EAT_ALL;
} else {
Xchat::print( qq{"$file" is not loaded.\n} );
return Xchat::EAT_NONE;
}
}
sub unload_all {
for my $package ( keys %scripts ) {
unload( $scripts{$package}->{filename} );
}
return Xchat::EAT_ALL;
}
sub reload {
my $file = shift @_;
my $package = file2pkg( $file );
my $pkg_info = pkg_info( $package );
my $fullpath = $file;
if( $pkg_info ) {
$fullpath = $pkg_info->{filename};
unload( $file );
}
load( $fullpath );
return Xchat::EAT_ALL;
}
sub reload_all {
my @dirs = Xchat::get_info( "xchatdirfs" ) || Xchat::get_info( "xchatdir" );
push @dirs, File::Spec->catdir( $dirs[0], "plugins" );
for my $dir ( @dirs ) {
my $auto_load_glob = File::Spec->catfile( $dir, "*.pl" );
my @scripts = map { $_->{filename} }
sort { $a->{loaded_at} <=> $b->{loaded_at} } values %scripts;
push @scripts, File::Glob::bsd_glob( $auto_load_glob );
my %seen;
@scripts = grep { !$seen{ $_ }++ } @scripts;
unload_all();
for my $script ( @scripts ) {
if( !pkg_info( file2pkg( $script ) ) ) {
load( $script );
}
}
}
}
sub expand_homedir {
my $file = shift @_;
if ( $^O eq "MSWin32" ) {
$file =~ s/^~/$ENV{USERPROFILE}/;
} else {
$file =~ s{^~}{
(getpwuid($>))[7] || $ENV{HOME} || $ENV{LOGDIR}
}ex;
}
return $file;
}
sub file2pkg {
my $string = File::Basename::basename( shift @_ );
$string =~ s/\.pl$//i;
$string =~ s|([^A-Za-z0-9/])|'_'.unpack("H*",$1)|eg;
return "Xchat::Script::" . $string;
}
sub pkg_info {
my $package = shift @_;
return $scripts{$package};
}
sub find_external_pkg {
my $level = 1;
while( my @frame = caller( $level ) ) {
return @frame if $frame[0] !~ /^Xchat/;
$level++;
}
}
sub find_pkg {
my $level = 1;
while( my ($package, $file, $line) = caller( $level ) ) {
return $package if $package =~ /^Xchat::Script::/;
$level++;
}
my @frame = find_external_pkg();
my $location;
if( $frame[0] or $frame[1] ) {
$location = $frame[1] ? $frame[1] : "package $frame[0]";
$location .= " line $frame[2]";
} else {
$location = "unknown location";
}
die "Unable to determine which script this hook belongs to. at $location\n";
}
sub fix_callback {
my ($package, $callback) = @_;
unless( ref $callback ) {
# change the package to the correct one in case it was hardcoded
$callback =~ s/^.*:://;
$callback = qq[${package}::$callback];
no strict 'subs';
$callback = \&{$callback};
}
return $callback;
}
1

View File

@ -0,0 +1,32 @@
package Xchat::List::Network;
use strict;
use warnings;
use Storable qw(dclone);
my $last_modified;
my @servers;
sub get {
my $server_file = Xchat::get_info( "xchatdirfs" ) . "/servlist_.conf";
# recreate the list only if the server list file has changed
if( -f $server_file &&
(!defined $last_modified || $last_modified != -M $server_file ) ) {
$last_modified = -M _;
if( open my $fh, "<", $server_file ) {
local $/ = "\n\n";
while( my $record = <$fh> ) {
chomp $record;
next if $record =~ /^v=/; # skip the version line
push @servers, Xchat::List::Network::Entry::parse( $record );
}
} else {
warn "Unable to open '$server_file': $!";
}
}
my $clone = dclone( \@servers );
return @$clone;
}
1

View File

@ -0,0 +1,82 @@
package Xchat::List::Network::AutoJoin;
use strict;
use warnings;
use overload
# '%{}' => \&as_hash,
# '@{}' => \&as_array,
'""' => 'as_string',
'0+' => 'as_bool';
sub new {
my $class = shift;
my $line = shift;
my @autojoins;
if ( $line ) {
my ( $channels, $keys ) = split / /, $line, 2;
my @channels = split /,/, $channels;
my @keys = split /,/, ($keys || '');
for my $channel ( @channels ) {
my $key = shift @keys;
$key = '' unless defined $key;
push @autojoins, {
channel => $channel,
key => $key,
};
}
}
return bless \@autojoins, $class;
}
sub channels {
my $self = shift;
if( wantarray ) {
return map { $_->{channel} } @$self;
} else {
return scalar @$self;
}
}
sub keys {
my $self = shift;
return map { $_->{key} } @$self ;
}
sub pairs {
my $self = shift;
my @channels = $self->channels;
my @keys = $self->keys;
my @pairs = map { $_ => shift @keys } @channels;
}
sub as_hash {
my $self = shift;
return +{ $self->pairs };
}
sub as_string {
my $self = shift;
return join " ",
join( ",", $self->channels ),
join( ",", $self->keys );
}
sub as_array {
my $self = shift;
return [ map { \%$_ } @$self ];
}
sub as_bool {
my $self = shift;
return $self->channels ? 1 : "";
}
1

View File

@ -0,0 +1,105 @@
package Xchat::List::Network::Entry;
use strict;
use warnings;
my %key_for = (
I => "irc_nick1",
i => "irc_nick2",
U => "irc_user_name",
R => "irc_real_name",
P => "server_password",
B => "nickserv_password",
N => "network",
D => "selected",
E => "encoding",
);
my $letter_key_re = join "|", keys %key_for;
sub parse {
my $data = shift;
my $entry = {
irc_nick1 => undef,
irc_nick2 => undef,
irc_user_name => undef,
irc_real_name => undef,
server_password => undef,
# the order of the channels need to be maintained
# list of { channel => .., key => ... }
autojoins => Xchat::List::Network::AutoJoin->new( '' ),
connect_commands => [],
flags => {},
selected => undef,
encoding => undef,
servers => [],
nickserv_password => undef,
network => undef,
};
my @fields = split /\n/, $data;
chomp @fields;
for my $field ( @fields ) {
SWITCH: for ( $field ) {
/^($letter_key_re)=(.*)/ && do {
$entry->{ $key_for{ $1 } } = $2;
last SWITCH;
};
/^J.(.*)/ && do {
$entry->{ autojoins } =
Xchat::List::Network::AutoJoin->new( $1 );
};
/^F.(.*)/ && do {
$entry->{ flags } = parse_flags( $1 );
};
/^S.(.+)/ && do {
push @{$entry->{servers}}, parse_server( $1 );
};
/^C.(.+)/ && do {
push @{$entry->{connect_commands}}, $1;
};
}
}
# $entry->{ autojoins } = $entry->{ autojoin_channels };
return $entry;
}
sub parse_flags {
my $value = shift || 0;
my %flags;
$flags{ "cycle" } = $value & 1 ? 1 : 0;
$flags{ "use_global" } = $value & 2 ? 1 : 0;
$flags{ "use_ssl" } = $value & 4 ? 1 : 0;
$flags{ "autoconnect" } = $value & 8 ? 1 : 0;
$flags{ "use_proxy" } = $value & 16 ? 1 : 0;
$flags{ "allow_invalid" } = $value & 32 ? 1 : 0;
return \%flags;
}
sub parse_server {
my $data = shift;
if( $data ) {
my ($host, $port) = split /\//, $data;
unless( $port ) {
my @parts = split /:/, $host;
# if more than 2 then we are probably dealing with a IPv6 address
# if less than 2 then no port was specified
if( @parts == 2 ) {
$port = $parts[1];
}
}
$port ||= 6667;
return { host => $host, port => $port };
}
}
1

1522
plugins/perl/perl.c Normal file

File diff suppressed because it is too large Load Diff

4
plugins/perl/perl.def Normal file
View File

@ -0,0 +1,4 @@
EXPORTS
xchat_plugin_init
xchat_plugin_deinit
xchat_plugin_get_info

View File

@ -0,0 +1,69 @@
#!/usr/bin/env perl
use 5.010;
use strict;
use warnings;
use Text::VimColor;
use HTML::TokeParser::Simple;
use HTML::Entities qw(decode_entities);
use Path::Class;
my $html_file = shift;
my $reader = file( $html_file )->openr;
unlink $html_file;
my $writer = file( $html_file )->openw;
my $parser = HTML::TokeParser::Simple->new( $reader );
while( my $token = $parser->get_token ) {
my $class_name = $token->get_attr( "class" );
if( $token->is_start_tag( "div" )
&& ( $class_name && $class_name =~ qr/\bexample\b/ )
) {
my $start_tag = $token;
$start_tag->set_attr( class => $class_name . " synNormal" );
my @content;
my $end_tag;
EXAMPLE:
while( $token = $parser->get_token ) {
if( $token->is_end_tag( "div" ) ) {
$end_tag = $token;
last EXAMPLE;
}
if( $token->is_text ) {
push @content, decode_entities( $token->as_is );
}
}
my $code = join "", @content;
# say $code;
my $vim = Text::VimColor->new(
string => $code,
filetype => "perl",
vim_options => [qw( -RXZ -i NONE -u NONE -N -n)],
);
my $html = $vim->html;
$html =~ s/^\s+//;
$html =~ s/\s+$//;
print $writer $start_tag->as_is;
my $lines = $html =~ tr/\n/\n/;
say $writer "<div class='line_number'>";
for my $line ( 0 .. $lines ) {
say $writer "<div>",1 + $line,"</div>";
}
say $writer "</div>";
print $writer "<div class='content'><pre>";
say $writer $html;
say $writer "</pre></div>";
print $writer $end_tag->as_is;
} else {
print $writer $token->as_is;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,475 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>XChat - IRC (chat) client for UNIX</title>
<style type="text/css">
body{font-family:sans-serif;background-color:#FFFBF0;}
:link{color:#00C;}
:visited{color:#609;}
:active{color:#C00;}
.date{background-color:#dddddd;font-family:terminal;font-size:small;}
th,td{font-family:sans-serif;}
h2{font-family:sans-serif;color:#990066;}
</style></head>
<body>
<h1><center>This interface is deprecated</center></h1>
<table width="90%" cellpadding="0" cellspacing="0" border="0">
<tbody><tr>
<td align="left" valign="top">
<blockquote>
<h2>Xchat Perl Docs</h2>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial" color="#990066">
Introduction
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
<p>Good Hello!</p>
<p>The purpose of this page is to give people some quick documentation on the
things that they will encounter when they try to code scripts for X-Chat.
It is <strong>not</strong> meant to be a comprehensive programming tutorial,
by any means. If that's what you're looking for, then you can just keep on
looking.</p>
<p>If you're going to do any scripting with X-Chat at all, you will
need to know perl. It also won't hurt to have had experience writing tcl for
eggdrops or ircII scripts. Otherwise you're going to have to be very careful
to avoid creating conditions which could flood you offline or do other
not-so-optimal things. ;) Thankfully, it shouldn't take most intelligent
people more than a week (month on the outside) enough perl to do some nice
things in it.
<a HREF="http://www.perl.com">Perl</a> is a very flexible language.</p>
<p>You should probably also go read (or at least skim over and then carefully
bookmark this copy of the thing that defines how IRC works: <a HREF="http://www.irchelp.org/irchelp/rfc1459.html">RFC 1459</a>.
Other documents that scripters might find useful would be this
<a HREF="http://www.irchelp.org/irchelp/ircd/numerics.html">nice list of server
numerics</a>, and this list of <a HREF="http://www.irchelp.org/irchelp/ircd/hybrid6.html">changes
for Hybrid 6</a> which is something everyone on EFNet should read. In fact, I
<strong>strongly</strong> suggest saving copies of these documents to your local
hard drive, because you <i>will</i> be back to look at them again soon.</p>
<p>One last thing... While you may hear that RFC 1459 isn't being followed very
well, and this is partly true, do your absolute best to stick with RFC-compliant
behaviours anyway because otherwise there's a good chance that your script will
never interoperate properly with others, or at least just piss off a lot of other
people. <i>Pay special attention to section 2.2 of the RFC.</i></p>
</blockquote>
<table ALIGN=CENTER WIDTH="75%" CELLPADDING=5 CELLSPACING=0>
<tr><td ALIGN=CENTER BGCOLOR="#FF7070">
<font COLOR="#FFFFFF" FACE="Verdana, Helvetica, Arial, Sans"><b>Standard Disclaimer</b>
</font>
</td></tr><tr> <td BGCOLOR="#FFCECE" ALIGN=CENTER><font COLOR="#800000" FACE="Helvetica, Lucida, Arial, Sans">
This documentation is provided on an "as-is" basis and comes with no warranty of accuracy or usefulness, either expressed or implied. It is subject to change without any notice, and may contain omissions or errors which could cause your genitalia to shrivel and fall off, or spontaneously combust. If you have any further questions,<br>please feel free to seek professional help.</font>
</td></tr></table>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial" color="#990066;">
About Handlers
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
There are [currently] four basic ways to make things call the subroutines you write for X-Chat and they are:
<ul><li>message handlers - Triggered by messagse sent from the IRC server to your client</li>
<li>command handlers - triggered by / commands typed in by the user at the keyboard</li>
<li>timeout handlers - triggered by gtk+</li>
<li>print handlers - triggered just before xchat calls its built in print handlers for events</li></ul>
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial" color="#990066;">
About Exit Codes
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
These are very important. Every time you set up a handler, it takes precedent over the built-in functions and commands of X-Chat. That is, whatever thing which triggered your subroutine will go to your code before it goes to X-Chat to be dealt with. In this way you can replace almost every built-in function that the client has with your own routines. The thing to remember is that if your code exits by hitting the end of your subroutine, or by a plain 'return' statement, processing of the event will go on to whatever other things have set up hooks for the event, and then (provided nothing else exits with a return value of 1) to X-Chat itself. There is only one problem with this, (which is solved by the brokering handler that I'll explain that later) and that is that you cannot really control what order the custom routines get called. Normally they will execute in order of which ones were installed first, but a single script has no real way of knowing this. Beware.
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial" color="#990066;">
About @_
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
If you've never heard of @_ before, then you've obviously not coded in perl. When a message handler triggers, the raw line from the IRC server is passed to the subroutine you specify in @_. When a command handler is triggered, only the arguments are passed to the routine through @_ and they are not broken into a list, but left as one long string. You'll have to parse those yourself with split. (I advise using s/\s+/ /g to collapse the blank space to single space first.) When a timer handler is triggered, I *think* absolutely nothing is passed in @_, but it's not like anything terrifically important could be passed along anyway. Be especially careful when setting up message handlers for mode changes, since the modes are not broken up into individual events like they are with eggdrop. The upside of this is that X-Chat has no mode hooks of it's own, so you don't have to worry about it too much. (This is not the case with the brokering handler, however.)
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial" color="#990066;">
About Context
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
There are some really nice things about coding for X-Chat, and the biggest one is that it's fairly good about determining the proper context for things. If a server sends something that triggers a message handler, then you can be sure that unless you specify otherwise, that your IRC::print or IRC::command function call will go back to that server and that server alone. If you really really need to know what the current context is, use the IRC::get_info function as detailed below.
</blockquote>
<hr width="95%">
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial" color="#990066;">
script initialization commands
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::register(scriptname, version, shutdownroutine, unused);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
<p>This is the first function your script should call, example:</p>
<blockquote><p>IRC::register ("my script", "1.0", "", "");</p></blockquote>
<p>The "shutdownroutine" arg is a function that will be called when X-Chat shuts down, so you get a chance to save config files etc. You can omit this arg, it is optional. The "unused" arg is reserved for future use, for now just provide "". This function also returns X-Chat's version number. </p>
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial" color="#990066;">
Handler initialization commands
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::add_message_handler(message, subroutine_name);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
<p>This function allows you to set up hooks to subroutines so that when a particular message arrives from the IRC server that you are connected to, it can be passed to a subroutine to be dealt with appropriately. The message argument is essentially the second solid token from the raw line sent by the IRC server, and X-Chat doesn't know that some numeric messages have associated text messages, so for now set up a handler for both if you want to be sure odd servers don't screw up your expectations. (Read: fear IRCNet.) The entire line sent by the IRC server will be passed to your subroutine in @_. For the completely uninitiated, messages are things like 'PRIVMSG', 'NOTICE', '372', etc.</p>
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::add_command_handler(command, subroutine_name);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
<p>This function allows you to set up hooks for actual commands that the user can type into the text window. The arguments are passed to the subroutine via @_, and arrive as a single string. @_ will be null if no arguments are supplied. It's recommended that you be sure and collapse the excess whitespace with s/\s+/ /g before attempting to chop the line up with split. As mentioned earlier, exiting with an undefined return value will allow the command to be parsed by other handlers, while using a return value of 1 will signal the program that no further parsing needs to be done with this command.</p>
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::add_timeout_handler(interval, subroutine_name);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
<p>This function allows you to set up hooks for subroutines to be called at a particular interval. The interval is measured in milliseconds, so don't use a particularly small value unless you wish to drive the CPU load through the roof. 1000ms = 1 second. No values will be passed to the routine via @_ and return values don't affect anything either.</p>
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::add_print_handler(message, subroutine_name);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
<p>This function allows you to catch the system messages (those who generally start by three stars) and to execute a function each time an event appear. The events are those you can see in "Settings->Edit Events Texts". message is the name of the event (you can find it in the Edit Events box, "Events" column) , subroutine_name is the name of the function that will get messages. Be carrful: all the arguments are sent to function in $_[0] separated by spaces. </p>
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial" color="#990066;">
Output commands
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::print(text);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
This is a very simple routine. All it does is put the contents of the text string to the current window. The current window will be whichever window a command was typed into when called from a command handler, or in whichever window the message command is appropriate to if it is called from within a message handler. As with any perl program, newlines are not assumed, so don't forget to end the line with \n if you don't want things to look screwey.
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::print_with_channel( text, channelname, servername );
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
This routine does the same thing as IRC::Print does, except it allows you to direct the output to a specific window. It returns 1 on success, 0 on fail.
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::command(text);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
This routine allows you to execute commands in the current context. The text string containing the command will be parsed by everything that would normally parse a command, including your own command handlers, so be careful. Newlines are assumed, thankfully.
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::command_with_server(text, servername);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
This routine allows you to specify the context of the server for which the command will be executed. It's not particularly useful unless you're managing a connection manually, yet the command still exists for it's usefulness in doing things like managing a bnc connection, etc. Newlines are assumed here as well.
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::send_raw(text);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
This routine is very useful in that it allows you to send a string directly to the IRC server you are connected to. It is assumed that the server will be the one you first connected to if there is no clear context for the command, otherwise it will go to whatever server triggered the message handler or command handler window. You must specify newlines here always or you can be guaranteed that strange things will happen. The text message you specify should be a proper RAW IRC message, so don't play with it if you don't know how to do these. Additionally, while newlines are also not assumed here as with the IRC::print function, the RFC specifies that newlines are a CR+LF pair, even if most servers will accept a mere newline. It's best to play it safe and use \r\n instead of just \n.
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial" color="#990066;">
Information retrieval commands
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::get_info(integer);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
This function returns a bit of selected information depending on what the value of the integer is.
Here's a list of the currently supported values:
<ul><li>0 - xchat version</li>
<li>1 - your nickname</li>
<li>2 - channel</li>
<li>3 - server</li>
<li>4 - xchatdir</li>
<li>5 - away status</li>
<li>6 - network name</li>
<li>7 - server hostname</li>
<li>8 - channel topic</li></ul>
<p>If you are requesting information that isn't available in the current context, then it will return null.</p>
<p>Any numbers other than the above will return an error message.</p>
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::get_prefs(var);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
This command lets you read the preferences that are set in the xchat configuration file. Just look at the xchat.conf dir to see what variables are available to use with this command. Returns the value of the variable requested or "Unknown Variable" if the variable isn't available.
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::user_info( nickname );
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
Returns a flat list of information on the nickname specified consisting of... nickname, nick host, and whether they have op or voice in the current context.
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::channel_list( );
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
This command returns a flat list which contains the current channel, server, and nickname for all channels the client is currently in. You'll have to break the list up into groups of three yourself. No arguments are necessary, or used [currently].
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::server_list( );
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
This command returns a flat list of servers. (Note, it is incompatible with xchat 1.8 in that it also returns a list of servers you are NOT connected to as well.)
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::user_list(channel, server);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
<p>Works very much like the dcc_list command below, except that is returns information about the users on the channel provided as first argument. The second argument is the server and is optional.</p>
<p>NOTE: If a user has both op and voice, only the op flag will be set to 1 by this command in xchat2.</p>
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::user_list_short(channel, server);
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
<p>A simpler version of IRC::user_list that returns pairs of nick & user@host suitable for assigning to a hash.</p>
<p>NOTE: If a user has both op and voice, only the op flag will be set to 1 by this command in xchat2.</p>
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::dcc_list( );
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
This command does essentially the same thing as channel_list, giving you the details of each DCC connection currently in progress. I have no idea exactly what is returned because I haven't had a chance to poke at this one much, but suffice it to say that it's a flat list, and the first time you play with it the meaning of the returned values should be pretty obvious.
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial">
IRC::ignore_list( );
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
This command returns a flat list of the contents of your ignore list. You'll have to play with it a little as I have not had a chance to yet. Works basically the same as the other list commands.
</blockquote>
<table width="95%" cellpadding="0" cellspacing="3" border="0" align="center">
<tbody><tr><td bgcolor="#000000">
<table width="100%" cellpadding="2" cellspacing="1" border="0"><tbody><tr>
<td width="20%" align="left" bgcolor="#dddddd">
<font face="Lucida, Helvetica, Arial" color="#990066;">
Unimplemented commands that were available in xchat 1.8.x
</font></td>
</tr></tbody></table>
</td></tr></tbody></table>
<blockquote>
add_user_list , sub_user_list , clear_user_list, notify_list were available in xchat 1.8.x but are not implemented in xchat 2 at this time.
</blockquote>
</blockquote>
</td>
</tr>
</tbody></table>
<br><hr>
<font size="-10">This document originally written by Dagmar d'Surreal on March 26th, 1998 for xchat 1.4<br>
Updated on July 30th, 1999 by Peter Zelezny<br>
Updated on May 16th, 2003 by DaNumber8 to comply with the perl plugin for xchat2 version 2.0.3</font>
</body></html>

View File

@ -0,0 +1,43 @@
perl generate_header
gcc -W -Os -DWIN32 -I "C:\MinGW\include" -I .. -I "C:\ActivePerl-5.8.9\perl\lib\CORE" -L "C:\ActivePerl-5.8.9\perl\bin" -c perl.c -o perl5.8.9.o
dllwrap --def perl.def --dllname xcperl5.8.9.dll "C:\ActivePerl-5.8.9\perl\bin\perl58.dll" perl5.8.9.o
strip xcperl5.8.9.dll
gcc -W -Os -DWIN32 -I "C:\MinGW\include" -I .. -I "C:\Perl\lib\CORE" -L "C:\Perl\bin" -c perl.c -o perl5.10.0.o
dllwrap --def perl.def --dllname xcperl5.10.0.dll "C:\Perl\bin\perl510.dll" perl5.10.0.o
strip xcperl5.10.0.dll
gcc -W -Os -DWIN32 -I "C:\MinGW\include" -I .. -I "C:\ActivePerl-5.10.1\perl\lib\CORE" -L "C:\ActivePerl-5.10.1\perl\bin" -c perl.c -o perl5.10.1.o
dllwrap --def perl.def --dllname xcperl5.10.1.dll "C:\ActivePerl-5.10.1\perl\bin\perl510.dll" perl5.10.1.o
strip xcperl5.10.1.dll
gcc -W -Os -DWIN32 -I "C:\MinGW\include" -I .. -I "C:\ActivePerl-5.12.1\perl\lib\CORE" -L "C:\ActivePerl-5.12.1\perl\bin" -c perl.c -o perl5.12.1.o
dllwrap --def perl.def --dllname xcperl5.12.1.dll "C:\ActivePerl-5.12.1\perl\bin\perl512.dll" perl5.12.1.o
strip xcperl5.12.1.dll
gcc -W -Os -DWIN32 -I "C:\MinGW\include" -I .. -I "C:\strawberry-perl-5.10.1.3\perl\lib\CORE" -L "C:\strawberry-perl-5.10.1.3\perl\bin" -c perl.c -o perl-strawberry5.10.1.o
dllwrap --def perl.def --dllname xcperl-strawberry5.10.1.dll "C:\strawberry-perl-5.10.1.3\perl\bin\perl510.dll" perl5.10.1.o
strip xcperl-strawberry5.10.1.dll
gcc -W -Os -DWIN32 -I "C:\MinGW\include" -I .. -I "C:\strawberry-perl-5.12.1.0-portable\perl\lib\CORE" -L "C:\strawberry-perl-5.12.1.0-portable\perl\bin" -c perl.c -o perl-strawberry5.12.1.o
dllwrap --def perl.def --dllname xcperl-strawberry5.12.1.dll "C:\strawberry-perl-5.12.1.0-portable\perl\bin\perl512.dll" perl5.12.1.o
strip xcperl-strawberry5.12.1.dll

20
plugins/plugin-conf.in Normal file
View File

@ -0,0 +1,20 @@
AC_INIT(@PLUGIN@-config.h.in)
AM_CONFIG_HEADER(@PLUGIN@-config.h)
AM_INIT_AUTOMAKE(xchat-@PLUGIN@, @PLUGIN_VERSION@)
AM_MAINTAINER_MODE
AM_DISABLE_STATIC
AM_PROG_LIBTOOL
AC_ARG_WITH(plugin-includes,
[ --with-plugin-includes directory containing xchat-plugin.h],
PLUGIN_INCLUDES=$enableval)
AC_SUBST(PLUGIN_INCLUDES)
xchatlibdir=${libdir}/xchat
AC_SUBST(xchatlibdir)
AC_OUTPUT(
Makefile
)

1002
plugins/plugin20.html Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
EXTRA_DIST =
libdir = $(xchatlibdir)/plugins
lib_LTLIBRARIES = python.la
python_la_SOURCES = python.c
python_la_LDFLAGS = -avoid-version -module
python_la_LIBADD = $(PY_LIBS)
INCLUDES = $(PY_CFLAGS) $(COMMON_CFLAGS) -I$(srcdir)/..

2257
plugins/python/python.c Normal file

File diff suppressed because it is too large Load Diff

10
plugins/tcl/Makefile.am Normal file
View File

@ -0,0 +1,10 @@
EXTRA_DIST=printevents.h tclplugin.h README
libdir = $(xchatlibdir)/plugins
lib_LTLIBRARIES = tcl.la
tcl_la_SOURCES = tclplugin.c
tcl_la_LDFLAGS = -avoid-version -module
tcl_la_LIBADD = $(TCL_LIBS)
INCLUDES = $(TCL_CFLAGS) $(COMMON_CFLAGS) -I$(srcdir)/..

55
plugins/tcl/README Normal file
View File

@ -0,0 +1,55 @@
Please read this document before asking questions.
(1) WHAT IS THE TCL PLUGIN?
The XChat Tcl Plugin adds the complete Tcl scripting language to the
XChat 1.9.x and 2.x IRC client. The design philosophy behind the tcl
plugin was to give all the power of the C API. yet completely shield
the user from all the complexities of it. It is lightly modeled after
after Xircon; an old windows TCL enabled client with a little bit of
eggdrop functionality to it.
Features:
* Uses the popular TCL scripting language.
* Familiar to eggdrop bot owners.
* Adds many new XChat specific commands to the Tcl language for
handling of events, user commands, timers, etc.
* It's actually documented! (Hey, what a concept!)
* Works with XChat 1.9.x and 2.x.
* Open source (GPL)
The supplied documentation for Tcl Plugin commands can be
found in doc/tclplugin.html
For a comprehensive list of IRC server tokens, see
doc/tokens.txt
(2) HOW TO GET TCL PLUGIN
You can always find the latest version of the Tcl Plugin at:
http://www.scriptkitties.com/tclplugin
You must also have Tcl 8.3 or higher installed on your system.
Tcl can be obtained from:
http://sourceforge.net/projects/tcl
http://tcl.activestate.com (pre-compiled binaries)
Tcl Man Pages
http://tcl.activestate.com/man/
Tcl Tutorials:
http://hegel.ittc.ukans.edu/topics/tcltk/tutorial-noplugin/
http://jan.netcomp.monash.edu.au/ProgrammingUnix/tcl/tcl_tut.html
http://users.belgacom.net/bruno.champagne/tcl.html
(3) QUICK STARTUP
SEE 'INSTALL'

319
plugins/tcl/printevents.h Normal file
View File

@ -0,0 +1,319 @@
/***************************************************************************
printevents.h - TCL plugin header file
-------------------------------------------------
begin : Sat Nov 9 17:31:20 MST 2002
copyright : Copyright 2002-2007 Daniel P. Stasinski
email : mooooooo@avenues.org
generated : Mon May 21 06:03:00 PM MST 2007
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
typedef struct {
char *event;
char *emit;
int argc;
xchat_hook *hook;
} print_event;
enum
{
CHAT,
XC_APPFOCUS,
XC_TABOPEN,
XC_TABCLOSE,
XC_TABFOCUS,
XC_KEYPRESS,
XC_ADDNOTIFY,
XC_BANLIST,
XC_BANNED,
XC_BEEP,
XC_CHANGENICK,
XC_CHANACTION,
XC_HCHANACTION,
XC_CHANBAN,
XC_CHANDATE,
XC_CHANDEHOP,
XC_CHANDEOP,
XC_CHANDEVOICE,
XC_CHANEXEMPT,
XC_CHANHOP,
XC_CHANINVITE,
XC_CHANLISTHEAD,
XC_CHANMSG,
XC_CHANMODEGEN,
XC_CHANMODES,
XC_HCHANMSG,
XC_CHANNOTICE,
XC_CHANOP,
XC_CHANRMEXEMPT,
XC_CHANRMINVITE,
XC_CHANRMKEY,
XC_CHANRMLIMIT,
XC_CHANSETKEY,
XC_CHANSETLIMIT,
XC_CHANUNBAN,
XC_CHANVOICE,
XC_CONNECTED,
XC_CONNECT,
XC_CONNFAIL,
XC_CTCPGEN,
XC_CTCPGENC,
XC_CTCPSEND,
XC_CTCPSND,
XC_CTCPSNDC,
XC_DCCCHATABORT,
XC_DCCCONCHAT,
XC_DCCCHATF,
XC_DCCCHATOFFER,
XC_DCCCHATOFFERING,
XC_DCCCHATREOFFER,
XC_DCCCONFAIL,
XC_DCCGENERICOFFER,
XC_DCCHEAD,
XC_MALFORMED,
XC_DCCOFFER,
XC_DCCIVAL,
XC_DCCRECVABORT,
XC_DCCRECVCOMP,
XC_DCCCONRECV,
XC_DCCRECVERR,
XC_DCCFILEERR,
XC_DCCRENAME,
XC_DCCRESUMEREQUEST,
XC_DCCSENDABORT,
XC_DCCSENDCOMP,
XC_DCCCONSEND,
XC_DCCSENDFAIL,
XC_DCCSENDOFFER,
XC_DCCSTALL,
XC_DCCTOUT,
XC_DELNOTIFY,
XC_DISCON,
XC_FOUNDIP,
XC_GENMSG,
XC_IGNOREADD,
XC_IGNORECHANGE,
XC_IGNOREFOOTER,
XC_IGNOREHEADER,
XC_IGNOREREMOVE,
XC_IGNOREEMPTY,
XC_INVITE,
XC_INVITED,
XC_JOIN,
XC_KEYWORD,
XC_KICK,
XC_KILL,
XC_MSGSEND,
XC_MOTD,
XC_MOTDSKIP,
XC_NICKCLASH,
XC_NICKFAIL,
XC_NODCC,
XC_NOCHILD,
XC_NOTICE,
XC_NOTICESEND,
XC_NOTIFYEMPTY,
XC_NOTIFYHEAD,
XC_NOTIFYNUMBER,
XC_NOTIFYOFFLINE,
XC_NOTIFYONLINE,
XC_OPENDIALOG,
XC_PART,
XC_PARTREASON,
XC_PINGREP,
XC_PINGTIMEOUT,
XC_PRIVMSG,
XC_DPRIVMSG,
XC_ALREADYPROCESS,
XC_QUIT,
XC_RAWMODES,
XC_WALLOPS,
XC_RESOLVINGUSER,
XC_SERVERCONNECTED,
XC_SERVERERROR,
XC_SERVERLOOKUP,
XC_SERVNOTICE,
XC_SERVTEXT,
XC_STOPCONNECT,
XC_TOPIC,
XC_NEWTOPIC,
XC_TOPICDATE,
XC_UKNHOST,
XC_USERLIMIT,
XC_USERSONCHAN,
XC_WHOIS_AUTH,
XC_WHOIS5,
XC_WHOIS2,
XC_WHOIS6,
XC_WHOIS_ID,
XC_WHOIS4,
XC_WHOIS4T,
XC_WHOIS1,
XC_WHOIS_REALHOST,
XC_WHOIS3,
XC_WHOIS_SPECIAL,
XC_UJOIN,
XC_UKICK,
XC_UPART,
XC_UPARTREASON,
XC_UACTION,
XC_UINVITE,
XC_UCHANMSG,
XC_UCHANGENICK,
XC_SIZE
};
static print_event xc[] = {
{ "CHAT", "DCC Chat Text", -1, NULL },
{ "XC_APPFOCUS", "Focus Window", -3, NULL },
{ "XC_TABOPEN", "Open Context", -2, NULL },
{ "XC_TABCLOSE", "Close Context", -2, NULL },
{ "XC_TABFOCUS", "Focus Tab", -2, NULL },
{ "XC_KEYPRESS", "Key Press", 4, NULL },
{ "XC_ADDNOTIFY", "Add Notify", 1, NULL },
{ "XC_BANLIST", "Ban List", 4, NULL },
{ "XC_BANNED", "Banned", 1, NULL },
{ "XC_BEEP", "Beep", 0, NULL },
{ "XC_CHANGENICK", "Change Nick", 2, NULL },
{ "XC_CHANACTION", "Channel Action", 3, NULL },
{ "XC_HCHANACTION", "Channel Action Hilight", 3, NULL },
{ "XC_CHANBAN", "Channel Ban", 2, NULL },
{ "XC_CHANDATE", "Channel Creation", 2, NULL },
{ "XC_CHANDEHOP", "Channel DeHalfOp", 2, NULL },
{ "XC_CHANDEOP", "Channel DeOp", 2, NULL },
{ "XC_CHANDEVOICE", "Channel DeVoice", 2, NULL },
{ "XC_CHANEXEMPT", "Channel Exempt", 2, NULL },
{ "XC_CHANHOP", "Channel Half-Operator", 2, NULL },
{ "XC_CHANINVITE", "Channel INVITE", 2, NULL },
{ "XC_CHANLISTHEAD", "Channel List", 0, NULL },
{ "XC_CHANMSG", "Channel Message", 4, NULL },
{ "XC_CHANMODEGEN", "Channel Mode Generic", 4, NULL },
{ "XC_CHANMODES", "Channel Modes", 2, NULL },
{ "XC_HCHANMSG", "Channel Msg Hilight", 4, NULL },
{ "XC_CHANNOTICE", "Channel Notice", 3, NULL },
{ "XC_CHANOP", "Channel Operator", 2, NULL },
{ "XC_CHANRMEXEMPT", "Channel Remove Exempt", 2, NULL },
{ "XC_CHANRMINVITE", "Channel Remove Invite", 2, NULL },
{ "XC_CHANRMKEY", "Channel Remove Keyword", 1, NULL },
{ "XC_CHANRMLIMIT", "Channel Remove Limit", 1, NULL },
{ "XC_CHANSETKEY", "Channel Set Key", 2, NULL },
{ "XC_CHANSETLIMIT", "Channel Set Limit", 2, NULL },
{ "XC_CHANUNBAN", "Channel UnBan", 2, NULL },
{ "XC_CHANVOICE", "Channel Voice", 2, NULL },
{ "XC_CONNECTED", "Connected", 0, NULL },
{ "XC_CONNECT", "Connecting", 3, NULL },
{ "XC_CONNFAIL", "Connection Failed", 1, NULL },
{ "XC_CTCPGEN", "CTCP Generic", 2, NULL },
{ "XC_CTCPGENC", "CTCP Generic to Channel", 3, NULL },
{ "XC_CTCPSEND", "CTCP Send", 2, NULL },
{ "XC_CTCPSND", "CTCP Sound", 2, NULL },
{ "XC_CTCPSNDC", "CTCP Sound to Channel", 3, NULL },
{ "XC_DCCCHATABORT", "DCC CHAT Abort", 1, NULL },
{ "XC_DCCCONCHAT", "DCC CHAT Connect", 2, NULL },
{ "XC_DCCCHATF", "DCC CHAT Failed", 4, NULL },
{ "XC_DCCCHATOFFER", "DCC CHAT Offer", 1, NULL },
{ "XC_DCCCHATOFFERING", "DCC CHAT Offering", 1, NULL },
{ "XC_DCCCHATREOFFER", "DCC CHAT Reoffer", 1, NULL },
{ "XC_DCCCONFAIL", "DCC Conection Failed", 3, NULL },
{ "XC_DCCGENERICOFFER", "DCC Generic Offer", 2, NULL },
{ "XC_DCCHEAD", "DCC Header", 0, NULL },
{ "XC_MALFORMED", "DCC Malformed", 2, NULL },
{ "XC_DCCOFFER", "DCC Offer", 3, NULL },
{ "XC_DCCIVAL", "DCC Offer Not Valid", 0, NULL },
{ "XC_DCCRECVABORT", "DCC RECV Abort", 2, NULL },
{ "XC_DCCRECVCOMP", "DCC RECV Complete", 4, NULL },
{ "XC_DCCCONRECV", "DCC RECV Connect", 3, NULL },
{ "XC_DCCRECVERR", "DCC RECV Failed", 4, NULL },
{ "XC_DCCFILEERR", "DCC RECV File Open Error", 2, NULL },
{ "XC_DCCRENAME", "DCC Rename", 2, NULL },
{ "XC_DCCRESUMEREQUEST", "DCC RESUME Request", 3, NULL },
{ "XC_DCCSENDABORT", "DCC SEND Abort", 2, NULL },
{ "XC_DCCSENDCOMP", "DCC SEND Complete", 3, NULL },
{ "XC_DCCCONSEND", "DCC SEND Connect", 3, NULL },
{ "XC_DCCSENDFAIL", "DCC SEND Failed", 3, NULL },
{ "XC_DCCSENDOFFER", "DCC SEND Offer", 4, NULL },
{ "XC_DCCSTALL", "DCC Stall", 3, NULL },
{ "XC_DCCTOUT", "DCC Timeout", 3, NULL },
{ "XC_DELNOTIFY", "Delete Notify", 1, NULL },
{ "XC_DISCON", "Disconnected", 1, NULL },
{ "XC_FOUNDIP", "Found IP", 1, NULL },
{ "XC_GENMSG", "Generic Message", 2, NULL },
{ "XC_IGNOREADD", "Ignore Add", 1, NULL },
{ "XC_IGNORECHANGE", "Ignore Changed", 1, NULL },
{ "XC_IGNOREFOOTER", "Ignore Footer", 0, NULL },
{ "XC_IGNOREHEADER", "Ignore Header", 0, NULL },
{ "XC_IGNOREREMOVE", "Ignore Remove", 1, NULL },
{ "XC_IGNOREEMPTY", "Ignorelist Empty", 0, NULL },
{ "XC_INVITE", "Invite", 1, NULL },
{ "XC_INVITED", "Invited", 3, NULL },
{ "XC_JOIN", "Join", 3, NULL },
{ "XC_KEYWORD", "Keyword", 1, NULL },
{ "XC_KICK", "Kick", 4, NULL },
{ "XC_KILL", "Killed", 2, NULL },
{ "XC_MSGSEND", "Message Send", 2, NULL },
{ "XC_MOTD", "Motd", 1, NULL },
{ "XC_MOTDSKIP", "MOTD Skipped", 0, NULL },
{ "XC_NICKCLASH", "Nick Clash", 2, NULL },
{ "XC_NICKFAIL", "Nick Failed", 0, NULL },
{ "XC_NODCC", "No DCC", 0, NULL },
{ "XC_NOCHILD", "No Running Process", 0, NULL },
{ "XC_NOTICE", "Notice", 2, NULL },
{ "XC_NOTICESEND", "Notice Send", 2, NULL },
{ "XC_NOTIFYEMPTY", "Notify Empty", 0, NULL },
{ "XC_NOTIFYHEAD", "Notify Header", 0, NULL },
{ "XC_NOTIFYNUMBER", "Notify Number", 1, NULL },
{ "XC_NOTIFYOFFLINE", "Notify Offline", 3, NULL },
{ "XC_NOTIFYONLINE", "Notify Online", 3, NULL },
{ "XC_OPENDIALOG", "Open Dialog", 0, NULL },
{ "XC_PART", "Part", 3, NULL },
{ "XC_PARTREASON", "Part with Reason", 4, NULL },
{ "XC_PINGREP", "Ping Reply", 2, NULL },
{ "XC_PINGTIMEOUT", "Ping Timeout", 1, NULL },
{ "XC_PRIVMSG", "Private Message", 3, NULL },
{ "XC_DPRIVMSG", "Private Message to Dialog", 3, NULL },
{ "XC_ALREADYPROCESS", "Process Already Running", 0, NULL },
{ "XC_QUIT", "Quit", 3, NULL },
{ "XC_RAWMODES", "Raw Modes", 2, NULL },
{ "XC_WALLOPS", "Receive Wallops", 2, NULL },
{ "XC_RESOLVINGUSER", "Resolving User", 2, NULL },
{ "XC_SERVERCONNECTED", "Server Connected", 0, NULL },
{ "XC_SERVERERROR", "Server Error", 1, NULL },
{ "XC_SERVERLOOKUP", "Server Lookup", 1, NULL },
{ "XC_SERVNOTICE", "Server Notice", 2, NULL },
{ "XC_SERVTEXT", "Server Text", 2, NULL },
{ "XC_STOPCONNECT", "Stop Connection", 1, NULL },
{ "XC_TOPIC", "Topic", 2, NULL },
{ "XC_NEWTOPIC", "Topic Change", 3, NULL },
{ "XC_TOPICDATE", "Topic Creation", 3, NULL },
{ "XC_UKNHOST", "Unknown Host", 0, NULL },
{ "XC_USERLIMIT", "User Limit", 1, NULL },
{ "XC_USERSONCHAN", "Users On Channel", 2, NULL },
{ "XC_WHOIS_AUTH", "WhoIs Authenticated", 3, NULL },
{ "XC_WHOIS5", "WhoIs Away Line", 2, NULL },
{ "XC_WHOIS2", "WhoIs Channel/Oper Line", 2, NULL },
{ "XC_WHOIS6", "WhoIs End", 1, NULL },
{ "XC_WHOIS_ID", "WhoIs Identified", 2, NULL },
{ "XC_WHOIS4", "WhoIs Idle Line", 2, NULL },
{ "XC_WHOIS4T", "WhoIs Idle Line with Signon", 3, NULL },
{ "XC_WHOIS1", "WhoIs Name Line", 4, NULL },
{ "XC_WHOIS_REALHOST", "WhoIs Real Host", 4, NULL },
{ "XC_WHOIS3", "WhoIs Server Line", 2, NULL },
{ "XC_WHOIS_SPECIAL", "WhoIs Special", 3, NULL },
{ "XC_UJOIN", "You Join", 3, NULL },
{ "XC_UKICK", "You Kicked", 4, NULL },
{ "XC_UPART", "You Part", 3, NULL },
{ "XC_UPARTREASON", "You Part with Reason", 4, NULL },
{ "XC_UACTION", "Your Action", 3, NULL },
{ "XC_UINVITE", "Your Invitation", 3, NULL },
{ "XC_UCHANMSG", "Your Message", 4, NULL },
{ "XC_UCHANGENICK", "Your Nick Changing", 2, NULL }
};

2290
plugins/tcl/tclplugin.c Normal file

File diff suppressed because it is too large Load Diff

98
plugins/tcl/tclplugin.h Normal file
View File

@ -0,0 +1,98 @@
/***************************************************************************
tclplugin.h - TCL plugin header file
-------------------------------------------------
begin : Sat Nov 9 17:31:20 MST 2002
copyright : Copyright 2002-2010 Daniel P. Stasinski
email : daniel@avenues.org
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#define BADARGS(nl,nh,example) \
if ((argc<(nl)) || (argc>(nh))) { \
Tcl_AppendResult(irp,"wrong # args: should be \"",argv[0], \
(example),"\"",NULL); \
return TCL_ERROR; \
}
#define CHECKCTX(ctx) \
if (ctx == NULL) { \
Tcl_AppendResult(irp, "No such server/channel/nick", NULL); \
return TCL_ERROR; \
}
typedef struct {
char *procPtr;
xchat_hook *hook;
} alias;
typedef struct {
int timerid;
time_t timestamp;
char *procPtr;
int count;
int seconds;
} timer;
typedef struct {
int result;
int defresult;
char **word;
char **word_eol;
} t_complete;
#define MAX_TIMERS 512
#define MAX_COMPLETES 128
static char *StrDup(const char *string, int *length);
static char *myitoa(long value);
static xchat_context *xchat_smart_context(const char *arg1, const char *arg2);
static void queue_nexttimer();
static int insert_timer(int seconds, int count, const char *script);
static void do_timer();
static int Server_raw_line(char *word[], char *word_eol[], void *userdata);
static int Print_Hook(char *word[], void *userdata);
static int tcl_timerexists(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_killtimer(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_timers(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_timer(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_on(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_off(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_alias(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_complete(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_raw(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_command(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_xchat_puts(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_print(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_channels(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_servers(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_queries(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_users(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_chats(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_ignores(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_dcclist(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_me(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_xchat_nickcmp(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_strip(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_topic(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_word(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_word_eol(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int tcl_notifylist(ClientData cd, Tcl_Interp * irp, int argc, const char *argv[]);
static int Command_Alias(char *word[], char *word_eol[], void *userdata);
static int Null_Command_Alias(char *word[], char *word_eol[], void *userdata);
static int Command_TCL(char *word[], char *word_eol[], void *userdata);
static int Command_Source(char *word[], char *word_eol[], void *userdata);
static int Command_Reload(char *word[], char *word_eol[], void *userdata);
static int TCL_Event_Handler(void *userdata);
static void Tcl_Plugin_Init();
static void Tcl_Plugin_DeInit();
static void banner();
int xchat_plugin_init(xchat_plugin * plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg);
int xchat_plugin_deinit();

334
plugins/xchat-plugin.h Normal file
View File

@ -0,0 +1,334 @@
/* You can distribute this header with your plugins for easy compilation */
#ifndef XCHAT_PLUGIN_H
#define XCHAT_PLUGIN_H
#include <time.h>
#define XCHAT_IFACE_MAJOR 1
#define XCHAT_IFACE_MINOR 9
#define XCHAT_IFACE_MICRO 11
#define XCHAT_IFACE_VERSION ((XCHAT_IFACE_MAJOR * 10000) + \
(XCHAT_IFACE_MINOR * 100) + \
(XCHAT_IFACE_MICRO))
#define XCHAT_PRI_HIGHEST 127
#define XCHAT_PRI_HIGH 64
#define XCHAT_PRI_NORM 0
#define XCHAT_PRI_LOW (-64)
#define XCHAT_PRI_LOWEST (-128)
#define XCHAT_FD_READ 1
#define XCHAT_FD_WRITE 2
#define XCHAT_FD_EXCEPTION 4
#define XCHAT_FD_NOTSOCKET 8
#define XCHAT_EAT_NONE 0 /* pass it on through! */
#define XCHAT_EAT_XCHAT 1 /* don't let xchat see this event */
#define XCHAT_EAT_PLUGIN 2 /* don't let other plugins see this event */
#define XCHAT_EAT_ALL (XCHAT_EAT_XCHAT|XCHAT_EAT_PLUGIN) /* don't let anything see this event */
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _xchat_plugin xchat_plugin;
typedef struct _xchat_list xchat_list;
typedef struct _xchat_hook xchat_hook;
#ifndef PLUGIN_C
typedef struct _xchat_context xchat_context;
#endif
#ifndef PLUGIN_C
struct _xchat_plugin
{
/* these are only used on win32 */
xchat_hook *(*xchat_hook_command) (xchat_plugin *ph,
const char *name,
int pri,
int (*callback) (char *word[], char *word_eol[], void *user_data),
const char *help_text,
void *userdata);
xchat_hook *(*xchat_hook_server) (xchat_plugin *ph,
const char *name,
int pri,
int (*callback) (char *word[], char *word_eol[], void *user_data),
void *userdata);
xchat_hook *(*xchat_hook_print) (xchat_plugin *ph,
const char *name,
int pri,
int (*callback) (char *word[], void *user_data),
void *userdata);
xchat_hook *(*xchat_hook_timer) (xchat_plugin *ph,
int timeout,
int (*callback) (void *user_data),
void *userdata);
xchat_hook *(*xchat_hook_fd) (xchat_plugin *ph,
int fd,
int flags,
int (*callback) (int fd, int flags, void *user_data),
void *userdata);
void *(*xchat_unhook) (xchat_plugin *ph,
xchat_hook *hook);
void (*xchat_print) (xchat_plugin *ph,
const char *text);
void (*xchat_printf) (xchat_plugin *ph,
const char *format, ...);
void (*xchat_command) (xchat_plugin *ph,
const char *command);
void (*xchat_commandf) (xchat_plugin *ph,
const char *format, ...);
int (*xchat_nickcmp) (xchat_plugin *ph,
const char *s1,
const char *s2);
int (*xchat_set_context) (xchat_plugin *ph,
xchat_context *ctx);
xchat_context *(*xchat_find_context) (xchat_plugin *ph,
const char *servname,
const char *channel);
xchat_context *(*xchat_get_context) (xchat_plugin *ph);
const char *(*xchat_get_info) (xchat_plugin *ph,
const char *id);
int (*xchat_get_prefs) (xchat_plugin *ph,
const char *name,
const char **string,
int *integer);
xchat_list * (*xchat_list_get) (xchat_plugin *ph,
const char *name);
void (*xchat_list_free) (xchat_plugin *ph,
xchat_list *xlist);
const char * const * (*xchat_list_fields) (xchat_plugin *ph,
const char *name);
int (*xchat_list_next) (xchat_plugin *ph,
xchat_list *xlist);
const char * (*xchat_list_str) (xchat_plugin *ph,
xchat_list *xlist,
const char *name);
int (*xchat_list_int) (xchat_plugin *ph,
xchat_list *xlist,
const char *name);
void * (*xchat_plugingui_add) (xchat_plugin *ph,
const char *filename,
const char *name,
const char *desc,
const char *version,
char *reserved);
void (*xchat_plugingui_remove) (xchat_plugin *ph,
void *handle);
int (*xchat_emit_print) (xchat_plugin *ph,
const char *event_name, ...);
int (*xchat_read_fd) (xchat_plugin *ph,
void *src,
char *buf,
int *len);
time_t (*xchat_list_time) (xchat_plugin *ph,
xchat_list *xlist,
const char *name);
char *(*xchat_gettext) (xchat_plugin *ph,
const char *msgid);
void (*xchat_send_modes) (xchat_plugin *ph,
const char **targets,
int ntargets,
int modes_per_line,
char sign,
char mode);
char *(*xchat_strip) (xchat_plugin *ph,
const char *str,
int len,
int flags);
void (*xchat_free) (xchat_plugin *ph,
void *ptr);
};
#endif
xchat_hook *
xchat_hook_command (xchat_plugin *ph,
const char *name,
int pri,
int (*callback) (char *word[], char *word_eol[], void *user_data),
const char *help_text,
void *userdata);
xchat_hook *
xchat_hook_server (xchat_plugin *ph,
const char *name,
int pri,
int (*callback) (char *word[], char *word_eol[], void *user_data),
void *userdata);
xchat_hook *
xchat_hook_print (xchat_plugin *ph,
const char *name,
int pri,
int (*callback) (char *word[], void *user_data),
void *userdata);
xchat_hook *
xchat_hook_timer (xchat_plugin *ph,
int timeout,
int (*callback) (void *user_data),
void *userdata);
xchat_hook *
xchat_hook_fd (xchat_plugin *ph,
int fd,
int flags,
int (*callback) (int fd, int flags, void *user_data),
void *userdata);
void *
xchat_unhook (xchat_plugin *ph,
xchat_hook *hook);
void
xchat_print (xchat_plugin *ph,
const char *text);
void
xchat_printf (xchat_plugin *ph,
const char *format, ...);
void
xchat_command (xchat_plugin *ph,
const char *command);
void
xchat_commandf (xchat_plugin *ph,
const char *format, ...);
int
xchat_nickcmp (xchat_plugin *ph,
const char *s1,
const char *s2);
int
xchat_set_context (xchat_plugin *ph,
xchat_context *ctx);
xchat_context *
xchat_find_context (xchat_plugin *ph,
const char *servname,
const char *channel);
xchat_context *
xchat_get_context (xchat_plugin *ph);
const char *
xchat_get_info (xchat_plugin *ph,
const char *id);
int
xchat_get_prefs (xchat_plugin *ph,
const char *name,
const char **string,
int *integer);
xchat_list *
xchat_list_get (xchat_plugin *ph,
const char *name);
void
xchat_list_free (xchat_plugin *ph,
xchat_list *xlist);
const char * const *
xchat_list_fields (xchat_plugin *ph,
const char *name);
int
xchat_list_next (xchat_plugin *ph,
xchat_list *xlist);
const char *
xchat_list_str (xchat_plugin *ph,
xchat_list *xlist,
const char *name);
int
xchat_list_int (xchat_plugin *ph,
xchat_list *xlist,
const char *name);
time_t
xchat_list_time (xchat_plugin *ph,
xchat_list *xlist,
const char *name);
void *
xchat_plugingui_add (xchat_plugin *ph,
const char *filename,
const char *name,
const char *desc,
const char *version,
char *reserved);
void
xchat_plugingui_remove (xchat_plugin *ph,
void *handle);
int
xchat_emit_print (xchat_plugin *ph,
const char *event_name, ...);
char *
xchat_gettext (xchat_plugin *ph,
const char *msgid);
void
xchat_send_modes (xchat_plugin *ph,
const char **targets,
int ntargets,
int modes_per_line,
char sign,
char mode);
char *
xchat_strip (xchat_plugin *ph,
const char *str,
int len,
int flags);
void
xchat_free (xchat_plugin *ph,
void *ptr);
#if !defined(PLUGIN_C) && defined(WIN32)
#ifndef XCHAT_PLUGIN_HANDLE
#define XCHAT_PLUGIN_HANDLE (ph)
#endif
#define xchat_hook_command ((XCHAT_PLUGIN_HANDLE)->xchat_hook_command)
#define xchat_hook_server ((XCHAT_PLUGIN_HANDLE)->xchat_hook_server)
#define xchat_hook_print ((XCHAT_PLUGIN_HANDLE)->xchat_hook_print)
#define xchat_hook_timer ((XCHAT_PLUGIN_HANDLE)->xchat_hook_timer)
#define xchat_hook_fd ((XCHAT_PLUGIN_HANDLE)->xchat_hook_fd)
#define xchat_unhook ((XCHAT_PLUGIN_HANDLE)->xchat_unhook)
#define xchat_print ((XCHAT_PLUGIN_HANDLE)->xchat_print)
#define xchat_printf ((XCHAT_PLUGIN_HANDLE)->xchat_printf)
#define xchat_command ((XCHAT_PLUGIN_HANDLE)->xchat_command)
#define xchat_commandf ((XCHAT_PLUGIN_HANDLE)->xchat_commandf)
#define xchat_nickcmp ((XCHAT_PLUGIN_HANDLE)->xchat_nickcmp)
#define xchat_set_context ((XCHAT_PLUGIN_HANDLE)->xchat_set_context)
#define xchat_find_context ((XCHAT_PLUGIN_HANDLE)->xchat_find_context)
#define xchat_get_context ((XCHAT_PLUGIN_HANDLE)->xchat_get_context)
#define xchat_get_info ((XCHAT_PLUGIN_HANDLE)->xchat_get_info)
#define xchat_get_prefs ((XCHAT_PLUGIN_HANDLE)->xchat_get_prefs)
#define xchat_list_get ((XCHAT_PLUGIN_HANDLE)->xchat_list_get)
#define xchat_list_free ((XCHAT_PLUGIN_HANDLE)->xchat_list_free)
#define xchat_list_fields ((XCHAT_PLUGIN_HANDLE)->xchat_list_fields)
#define xchat_list_str ((XCHAT_PLUGIN_HANDLE)->xchat_list_str)
#define xchat_list_int ((XCHAT_PLUGIN_HANDLE)->xchat_list_int)
#define xchat_list_time ((XCHAT_PLUGIN_HANDLE)->xchat_list_time)
#define xchat_list_next ((XCHAT_PLUGIN_HANDLE)->xchat_list_next)
#define xchat_plugingui_add ((XCHAT_PLUGIN_HANDLE)->xchat_plugingui_add)
#define xchat_plugingui_remove ((XCHAT_PLUGIN_HANDLE)->xchat_plugingui_remove)
#define xchat_emit_print ((XCHAT_PLUGIN_HANDLE)->xchat_emit_print)
#define xchat_gettext ((XCHAT_PLUGIN_HANDLE)->xchat_gettext)
#define xchat_send_modes ((XCHAT_PLUGIN_HANDLE)->xchat_send_modes)
#define xchat_strip ((XCHAT_PLUGIN_HANDLE)->xchat_strip)
#define xchat_free ((XCHAT_PLUGIN_HANDLE)->xchat_free)
#endif
#ifdef __cplusplus
}
#endif
#endif

7
plugins/xdcc/Makefile.am Normal file
View File

@ -0,0 +1,7 @@
libdir = $(xchatdir)/plugins
lib_LTLIBRARIES = xdcc.la
xdcc_la_SOURCES = xdcc.c
xdcc_la_LDFLAGS = -avoid-version -module
INCLUDES = $(COMMON_CFLAGS) -I$(srcdir)/..

327
plugins/xdcc/xdcc.c Normal file
View File

@ -0,0 +1,327 @@
/* xchat 2.0 plugin: simple xdcc server example */
#include <glib.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include "xchat-plugin.h"
static xchat_plugin *ph; /* plugin handle */
static int xdcc_on = 1;
static int xdcc_slots = 3;
static GSList *file_list = 0;
typedef struct fileoffer
{
char *file;
char *fullpath;
char *desc;
int downloads;
} fileoffer;
/* find the number of open dccs */
static int num_open_dccs(void)
{
xchat_list *list;
int num = 0;
list = xchat_list_get(ph, "dcc");
if(!list)
return 0;
while(xchat_list_next(ph, list))
{
/* check only ACTIVE dccs */
if(xchat_list_int(ph, list, "status") == 1)
{
/* check only SEND dccs */
if(xchat_list_int(ph, list, "type") == 0)
num++;
}
}
xchat_list_free(ph, list);
return num;
}
static void xdcc_get(char *nick, char *host, char *arg)
{
int num;
GSList *list;
fileoffer *offer;
if(arg[0] == '#')
arg++;
num = atoi(arg);
list = g_slist_nth(file_list, num - 1);
if(!list)
{
xchat_commandf(ph, "quote NOTICE %s :No such file number #%d!", nick, num);
return;
}
if(num_open_dccs() >= xdcc_slots)
{
xchat_commandf(ph, "quote NOTICE %s :All slots full. Try again later.", nick);
return;
}
offer = (fileoffer *) list->data;
offer->downloads++;
xchat_commandf(ph, "quote NOTICE %s :Sending offer #%d %s", nick, num, offer->file);
xchat_commandf(ph, "dcc send %s %s", nick, offer->fullpath);
}
static void xdcc_del(char *name)
{
GSList *list;
fileoffer *offer;
list = file_list;
while(list)
{
offer = (fileoffer *) list->data;
if(strcasecmp(name, offer->file) == 0)
{
file_list = g_slist_remove(file_list, offer);
xchat_printf(ph, "%s [%s] removed.\n", offer->file, offer->fullpath);
free(offer->file);
free(offer->desc);
free(offer->fullpath);
free(offer);
return;
}
list = list->next;
}
}
static void xdcc_add(char *name, char *fullpath, char *desc, int dl)
{
fileoffer *offer;
offer = (fileoffer *) malloc(sizeof(fileoffer));
offer->file = strdup(name);
offer->desc = strdup(desc);
offer->fullpath = strdup(fullpath);
offer->downloads = dl;
file_list = g_slist_append(file_list, offer);
}
static void xdcc_list(char *nick, char *host, char *arg, char *cmd)
{
GSList *list;
int i = 0;
fileoffer *offer;
xchat_commandf(ph, "%s %s :XDCC List:", cmd, nick);
list = file_list;
while(list)
{
i++;
offer = (fileoffer *) list->data;
xchat_commandf(ph, "%s %s :[#%d] %s - %s [%d dl]", cmd,
nick, i, offer->file, offer->desc, offer->downloads);
list = list->next;
}
if(i == 0)
xchat_commandf(ph, "%s %s :- list empty.", cmd, nick);
else
xchat_commandf(ph, "%s %s :%d files listed.", cmd, nick, i);
}
static int xdcc_command(char *word[], char *word_eol[], void *userdata)
{
if(strcasecmp(word[2], "ADD") == 0)
{
if(!word_eol[5][0])
xchat_print(ph, "Syntax: /XDCC ADD <name> <path> <description>\n");
else
{
if(access(word[4], R_OK) == 0)
{
xdcc_add(word[3], word[4], word_eol[5], 0);
xchat_printf(ph, "%s [%s] added.\n", word[3], word[4]);
}
else
xchat_printf(ph, "Cannot read %s\n", word[4]);
}
return XCHAT_EAT_XCHAT;
}
if(strcasecmp(word[2], "DEL") == 0)
{
xdcc_del(word[3]);
return XCHAT_EAT_XCHAT;
}
if(strcasecmp(word[2], "SLOTS") == 0)
{
if(word[3][0])
{
xdcc_slots = atoi(word[3]);
xchat_printf(ph, "XDCC slots set to %d\n", xdcc_slots);
} else
{
xchat_printf(ph, "XDCC slots: %d\n", xdcc_slots);
}
return XCHAT_EAT_XCHAT;
}
if(strcasecmp(word[2], "ON") == 0)
{
xdcc_on = TRUE;
xchat_print(ph, "XDCC now ON\n");
return XCHAT_EAT_XCHAT;
}
if(strcasecmp(word[2], "LIST") == 0)
{
xdcc_list("", "", "", "echo");
return XCHAT_EAT_XCHAT;
}
if(strcasecmp(word[2], "OFF") == 0)
{
xdcc_on = FALSE;
xchat_print(ph, "XDCC now OFF\n");
return XCHAT_EAT_XCHAT;
}
xchat_print(ph, "Syntax: XDCC ADD <name> <fullpath> <description>\n"
" XDCC DEL <name>\n"
" XDCC SLOTS <number>\n"
" XDCC LIST\n"
" XDCC ON\n"
" XDCC OFF\n\n");
return XCHAT_EAT_XCHAT;
}
static void xdcc_remote(char *from, char *msg)
{
char *ex, *nick, *host;
ex = strchr(from, '!');
if(!ex)
return;
ex[0] = 0;
nick = from;
host = ex + 1;
if(xdcc_on == 0)
{
xchat_commandf(ph, "notice %s XDCC is turned OFF!", from);
return;
}
if(strncasecmp(msg, "LIST", 4) == 0)
xdcc_list(nick, host, msg + 4, "quote notice");
else if(strncasecmp(msg, "GET ", 4) == 0)
xdcc_get(nick, host, msg + 4);
else
xchat_commandf(ph, "notice %s Unknown XDCC command!", from);
}
static int ctcp_cb(char *word[], void *userdata)
{
char *msg = word[1];
char *from = word[2];
if(strncasecmp(msg, "XDCC ", 5) == 0)
xdcc_remote(from, msg + 5);
return XCHAT_EAT_NONE;
}
static void xdcc_save(void)
{
char buf[512];
FILE *fp;
GSList *list;
fileoffer *offer;
snprintf(buf, sizeof(buf), "%s/xdcclist.conf", xchat_get_info(ph, "xchatdir"));
fp = fopen(buf, "w");
if(!fp)
return;
list = file_list;
while(list)
{
offer = (fileoffer *) list->data;
fprintf(fp, "%s\n%s\n%s\n%d\n\n\n", offer->file, offer->fullpath,
offer->desc, offer->downloads);
list = list->next;
}
fclose(fp);
}
static void xdcc_load(void)
{
char buf[512];
char file[128];
char path[128];
char desc[128];
char dl[128];
FILE *fp;
snprintf(buf, sizeof(buf), "%s/xdcclist.conf", xchat_get_info(ph, "xchatdir"));
fp = fopen(buf, "r");
if(!fp)
return;
while(fgets(file, sizeof(file), fp))
{
file[strlen(file)-1] = 0;
fgets(path, sizeof(path), fp);
path[strlen(path)-1] = 0;
fgets(desc, sizeof(desc), fp);
desc[strlen(desc)-1] = 0;
fgets(dl, sizeof(dl), fp);
dl[strlen(dl)-1] = 0;
fgets(buf, sizeof(buf), fp);
fgets(buf, sizeof(buf), fp);
xdcc_add(file, path, desc, atoi(dl));
}
fclose(fp);
}
int xchat_plugin_deinit(void)
{
xdcc_save();
xchat_print(ph, "XDCC List saved\n");
return 1;
}
int xchat_plugin_init(xchat_plugin *plugin_handle,
char **plugin_name, char **plugin_desc, char **plugin_version,
char *arg)
{
ph = plugin_handle;
*plugin_name = "XDCC";
*plugin_desc = "Very simple XDCC server";
*plugin_version = "0.1";
xchat_hook_command(ph, "XDCC", XCHAT_PRI_NORM, xdcc_command, 0, 0);
xchat_hook_print(ph, "CTCP Generic", XCHAT_PRI_NORM, ctcp_cb, 0);
xchat_hook_print(ph, "CTCP Generic to Channel", XCHAT_PRI_NORM, ctcp_cb, 0);
xdcc_load();
xchat_print(ph, "XDCC loaded. Type /XDCC for help.\n");
return 1;
}

7
po/Makevars Normal file
View File

@ -0,0 +1,7 @@
DOMAIN = $(PACKAGE)
subdir = po
top_builddir = ..
XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
COPYRIGHT_HOLDER =
MSGID_BUGS_ADDRESS = www.xchat.org
EXTRA_LOCALE_CATEGORIES =

37
po/POTFILES.in Normal file
View File

@ -0,0 +1,37 @@
src/common/cfgfiles.c
src/common/dcc.c
src/common/ignore.c
src/common/notify.c
src/common/outbound.c
src/common/plugin.c
src/common/server.c
src/common/servlist.c
src/common/textevents.h
src/common/text.c
src/common/util.c
src/common/xchat.c
src/common/dbus/dbus-client.c
src/common/dbus/dbus-plugin.c
src/fe-gtk/about.c
src/fe-gtk/ascii.c
src/fe-gtk/banlist.c
src/fe-gtk/chanlist.c
src/fe-gtk/dccgui.c
src/fe-gtk/editlist.c
src/fe-gtk/fe-gtk.c
src/fe-gtk/fkeys.c
src/fe-gtk/gtkutil.c
src/fe-gtk/ignoregui.c
src/fe-gtk/joind.c
src/fe-gtk/maingui.c
src/fe-gtk/menu.c
src/fe-gtk/notifygui.c
src/fe-gtk/plugin-tray.c
src/fe-gtk/plugingui.c
src/fe-gtk/rawlog.c
src/fe-gtk/search.c
src/fe-gtk/servlistgui.c
src/fe-gtk/setup.c
src/fe-gtk/textgui.c
src/fe-gtk/urlgrab.c
src/fe-gtk/userlistgui.c

4818
po/am.po Normal file

File diff suppressed because it is too large Load Diff

4808
po/az.po Normal file

File diff suppressed because it is too large Load Diff

5278
po/be.po Normal file

File diff suppressed because it is too large Load Diff

5078
po/bg.po Normal file

File diff suppressed because it is too large Load Diff

6395
po/ca.po Normal file

File diff suppressed because it is too large Load Diff

5721
po/cs.po Normal file

File diff suppressed because it is too large Load Diff

5543
po/de.po Normal file

File diff suppressed because it is too large Load Diff

5486
po/el.po Normal file

File diff suppressed because it is too large Load Diff

4775
po/en_GB.po Normal file

File diff suppressed because it is too large Load Diff

5569
po/es.po Normal file

File diff suppressed because it is too large Load Diff

5317
po/et.po Normal file

File diff suppressed because it is too large Load Diff

5049
po/eu.po Normal file

File diff suppressed because it is too large Load Diff

5341
po/fi.po Normal file

File diff suppressed because it is too large Load Diff

6208
po/fr.po Normal file

File diff suppressed because it is too large Load Diff

5651
po/gl.po Normal file

File diff suppressed because it is too large Load Diff

5023
po/hi.po Normal file

File diff suppressed because it is too large Load Diff

5646
po/hu.po Normal file

File diff suppressed because it is too large Load Diff

5501
po/it.po Normal file

File diff suppressed because it is too large Load Diff

6535
po/ja.po Normal file

File diff suppressed because it is too large Load Diff

5286
po/kn.po Normal file

File diff suppressed because it is too large Load Diff

5569
po/ko.po Normal file

File diff suppressed because it is too large Load Diff

6313
po/lt.po Normal file

File diff suppressed because it is too large Load Diff

5091
po/lv.po Normal file

File diff suppressed because it is too large Load Diff

5316
po/mk.po Normal file

File diff suppressed because it is too large Load Diff

4926
po/ms.po Normal file

File diff suppressed because it is too large Load Diff

5278
po/nb.po Normal file

File diff suppressed because it is too large Load Diff

5449
po/nl.po Normal file

File diff suppressed because it is too large Load Diff

4852
po/no.po Normal file

File diff suppressed because it is too large Load Diff

5641
po/pa.po Normal file

File diff suppressed because it is too large Load Diff

5616
po/pl.po Normal file

File diff suppressed because it is too large Load Diff

5401
po/pt.po Normal file

File diff suppressed because it is too large Load Diff

6078
po/pt_BR.po Normal file

File diff suppressed because it is too large Load Diff

19
po/remove-potcdate.sin Normal file
View File

@ -0,0 +1,19 @@
# Sed script that remove the POT-Creation-Date line in the header entry
# from a POT file.
#
# The distinction between the first and the following occurrences of the
# pattern is achieved by looking at the hold space.
/^"POT-Creation-Date: .*"$/{
x
# Test if the hold space is empty.
s/P/P/
ta
# Yes it was empty. First occurrence. Remove the line.
g
d
bb
:a
# The hold space was nonempty. Following occurrences. Do nothing.
x
:b
}

5806
po/ru.po Normal file

File diff suppressed because it is too large Load Diff

5209
po/sk.po Normal file

File diff suppressed because it is too large Load Diff

5026
po/sl.po Normal file

File diff suppressed because it is too large Load Diff

5455
po/sq.po Normal file

File diff suppressed because it is too large Load Diff

5456
po/sr.po Normal file

File diff suppressed because it is too large Load Diff

5367
po/sv.po Normal file

File diff suppressed because it is too large Load Diff

5317
po/th.po Normal file

File diff suppressed because it is too large Load Diff

5871
po/uk.po Normal file

File diff suppressed because it is too large Load Diff

5478
po/vi.po Normal file

File diff suppressed because it is too large Load Diff

4682
po/wa.po Normal file

File diff suppressed because it is too large Load Diff

5671
po/zh_CN.po Normal file

File diff suppressed because it is too large Load Diff

5434
po/zh_TW.po Normal file

File diff suppressed because it is too large Load Diff

14
src/Makefile.am Normal file
View File

@ -0,0 +1,14 @@
## Process this file with automake to produce Makefile.in
EXTRA_DIST = fe-text/fe-text.c \
fe-text/README fe-text/fe-text.h version-script
if DO_TEXT
text_fe = fe-text
endif
if DO_GTK
gtk_fe = fe-gtk
endif
SUBDIRS = pixmaps common $(gtk_fe) $(text_fe)

61
src/common/Makefile.am Normal file
View File

@ -0,0 +1,61 @@
## Process this file with automake to produce Makefile.in
noinst_LIBRARIES = libxchatcommon.a
INCLUDES = $(COMMON_CFLAGS)
EXTRA_DIST = \
cfgfiles.h \
chanopt.h \
ctcp.h \
dcc.h \
fe.h \
history.h \
identd.c \
ignore.h \
inbound.h \
inet.h \
make-te.c \
modes.h \
msproxy.h \
network.h \
notify.h \
outbound.h \
plugin.h \
plugin-timer.h \
proto-irc.h \
server.h \
servlist.h \
ssl.h \
ssl.c \
text.h \
textenums.h \
textevents.h \
textevents.in \
tree.h \
url.h \
userlist.h \
util.h \
xchat.h \
xchatc.h \
xchat-plugin.h
if USE_OPENSSL
ssl_c = ssl.c
endif
if USE_DBUS
dbusdir = dbus
libxchatcommon_a_LIBADD = \
$(top_builddir)/src/common/dbus/dbus-*.$(OBJEXT)
endif
SUBDIRS = $(dbusdir) .
libxchatcommon_a_SOURCES = cfgfiles.c chanopt.c ctcp.c dcc.c history.c ignore.c \
inbound.c modes.c msproxy.c network.c notify.c outbound.c \
plugin.c plugin-timer.c proto-irc.c server.c servlist.c $(ssl_c) \
text.c tree.c url.c userlist.c util.c xchat.c
libxchatcommon_a_CFLAGS = $(LIBPROXY_CFLAGS)
textevents: make-te
./make-te < textevents.in > textevents.h 2> textenums.h

1105
src/common/cfgfiles.c Normal file

File diff suppressed because it is too large Load Diff

55
src/common/cfgfiles.h Normal file
View File

@ -0,0 +1,55 @@
/* cfgfiles.h */
#ifndef XCHAT_CFGFILES_H
#define XCHAT_CFGFILES_H
#include "xchat.h"
extern char *xdir_fs;
extern char *xdir_utf;
char *cfg_get_str (char *cfg, char *var, char *dest, int dest_len);
int cfg_get_bool (char *var);
int cfg_get_int_with_result (char *cfg, char *var, int *result);
int cfg_get_int (char *cfg, char *var);
int cfg_put_int (int fh, int value, char *var);
int cfg_get_color (char *cfg, char *var, int *r, int *g, int *b);
int cfg_put_color (int fh, int r, int g, int b, char *var);
char *get_xdir_fs (void);
char *get_xdir_utf8 (void);
void load_config (void);
int save_config (void);
void list_free (GSList ** list);
void list_loadconf (char *file, GSList ** list, char *defaultconf);
int list_delentry (GSList ** list, char *name);
void list_addentry (GSList ** list, char *cmd, char *name);
int cmd_set (session *sess, char *tbuf, char *word[], char *word_eol[]);
int xchat_open_file (char *file, int flags, int mode, int xof_flags);
FILE *xchat_fopen_file (const char *file, const char *mode, int xof_flags);
#define XOF_DOMODE 1
#define XOF_FULLPATH 2
#define STRUCT_OFFSET_STR(type,field) \
( (unsigned int) (((char *) (&(((type *) NULL)->field)))- ((char *) NULL)) )
#define STRUCT_OFFSET_INT(type,field) \
( (unsigned int) (((int *) (&(((type *) NULL)->field)))- ((int *) NULL)) )
#define P_OFFSET(field) STRUCT_OFFSET_STR(struct xchatprefs, field),sizeof(prefs.field)
#define P_OFFSETNL(field) STRUCT_OFFSET_STR(struct xchatprefs, field)
#define P_OFFINT(field) STRUCT_OFFSET_INT(struct xchatprefs, field),0
#define P_OFFINTNL(field) STRUCT_OFFSET_INT(struct xchatprefs, field)
struct prefs
{
char *name;
unsigned short offset;
unsigned short len;
unsigned short type;
};
#define TYPE_STR 0
#define TYPE_INT 1
#define TYPE_BOOL 2
#endif

Some files were not shown because too many files have changed in this diff Show More