From ee0d2e6e1967294f4a62da1840b0ffdaa3124a2d Mon Sep 17 00:00:00 2001 From: tpearson Date: Fri, 19 Feb 2010 18:29:46 +0000 Subject: Added old abandoned KDE3 version of Konversation git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/konversation@1092922 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- AUTHORS | 7 + COPYING | 280 + COPYING-DOCS | 397 + ChangeLog | 1333 ++ INSTALL | 181 + Makefile.am | 5 + Makefile.am.in | 4 + README | 4 + TODO | 3 + VERSION | 1 + acinclude.m4 | 12643 +++++++++++++++++++ aclocal.m4 | 910 ++ config.h.in | 252 + configure.files | 3 + configure.in | 234 + configure.in.in | 11 + doc/Makefile.am | 5 + doc/da/Makefile.am | 2 + doc/da/index.docbook | 5935 +++++++++ doc/es/Makefile.am | 2 + doc/es/addchannel.png | Bin 0 -> 11767 bytes doc/es/addnetwork_co.png | Bin 0 -> 38945 bytes doc/es/addserver_co.png | Bin 0 -> 19211 bytes doc/es/channel_screen_tour_co.png | Bin 0 -> 87922 bytes doc/es/channellist_screen_co.png | Bin 0 -> 92402 bytes doc/es/checkidentities.png | Bin 0 -> 19017 bytes doc/es/colorchooser_screen.png | Bin 0 -> 18441 bytes doc/es/colorize.png | Bin 0 -> 1022 bytes doc/es/common/1.png | Bin 0 -> 235 bytes doc/es/common/2.png | Bin 0 -> 260 bytes doc/es/common/3.png | Bin 0 -> 264 bytes doc/es/common/4.png | Bin 0 -> 259 bytes doc/es/common/5.png | Bin 0 -> 260 bytes doc/es/common/6.png | Bin 0 -> 277 bytes doc/es/common/7.png | Bin 0 -> 252 bytes doc/es/common/8.png | Bin 0 -> 274 bytes doc/es/common/9.png | Bin 0 -> 283 bytes doc/es/configure.png | Bin 0 -> 1054 bytes doc/es/dccstatus_screen_co.png | Bin 0 -> 40081 bytes doc/es/first_channel_co.png | Bin 0 -> 55889 bytes doc/es/first_serverlist_co.png | Bin 0 -> 24256 bytes doc/es/highlighting_screen_co.png | Bin 0 -> 89347 bytes doc/es/identities_adv_co.png | Bin 0 -> 34376 bytes doc/es/identities_away_co.png | Bin 0 -> 34513 bytes doc/es/identities_gen_co.png | Bin 0 -> 41119 bytes doc/es/irc_admin.png | Bin 0 -> 205 bytes doc/es/irc_away.png | Bin 0 -> 181 bytes doc/es/irc_halfop.png | Bin 0 -> 212 bytes doc/es/irc_normal.png | Bin 0 -> 206 bytes doc/es/irc_op.png | Bin 0 -> 212 bytes doc/es/irc_owner.png | Bin 0 -> 212 bytes doc/es/irc_voice.png | Bin 0 -> 212 bytes doc/es/kaddressbook.png | Bin 0 -> 783 bytes doc/es/kimproxy_create_screen2.png | Bin 0 -> 23652 bytes doc/es/kimproxy_create_screen_co.png | Bin 0 -> 58630 bytes doc/es/led_blue_off.png | Bin 0 -> 282 bytes doc/es/led_blue_on.png | Bin 0 -> 250 bytes doc/es/led_green_off.png | Bin 0 -> 277 bytes doc/es/led_green_on.png | Bin 0 -> 245 bytes doc/es/led_red_off.png | Bin 0 -> 248 bytes doc/es/led_red_on.png | Bin 0 -> 255 bytes doc/es/led_yellow_off.png | Bin 0 -> 259 bytes doc/es/led_yellow_on.png | Bin 0 -> 224 bytes doc/es/logviewer_co.png | Bin 0 -> 105998 bytes doc/es/nicksonline_co.png | Bin 0 -> 43449 bytes doc/es/nickthemes_screen_co.png | Bin 0 -> 88233 bytes doc/es/notification_screen_co.png | Bin 0 -> 72555 bytes doc/es/notifylist_screen_co.png | Bin 0 -> 83279 bytes doc/es/osd_demo.png | Bin 0 -> 67027 bytes doc/es/osd_screen_co.png | Bin 0 -> 92388 bytes doc/es/quickbuttons_screen.png | Bin 0 -> 100953 bytes doc/es/quickconnect_screen.png | Bin 0 -> 15369 bytes doc/es/serverlist_co.png | Bin 0 -> 29459 bytes doc/es/urlcatcher_screen_co.png | Bin 0 -> 41032 bytes doc/es/webbrowser_screen_co.png | Bin 0 -> 98548 bytes doc/et/Makefile.am | 2 + doc/et/index.docbook | 5981 +++++++++ doc/it/Makefile.am | 2 + doc/it/addchannel.png | Bin 0 -> 6493 bytes doc/it/addnetwork_co.png | Bin 0 -> 29590 bytes doc/it/addserver_co.png | Bin 0 -> 12390 bytes doc/it/channel_screen_tour_co.png | Bin 0 -> 87723 bytes doc/it/channellist_screen_co.png | Bin 0 -> 63868 bytes doc/it/checkidentities.png | Bin 0 -> 12118 bytes doc/it/colorchooser_screen.png | Bin 0 -> 9637 bytes doc/it/first_channel_co.png | Bin 0 -> 78996 bytes doc/it/first_serverlist_co.png | Bin 0 -> 15863 bytes doc/it/identities_adv_co.png | Bin 0 -> 24545 bytes doc/it/identities_away_co.png | Bin 0 -> 26257 bytes doc/it/identities_gen_co.png | Bin 0 -> 28834 bytes doc/it/index.docbook | 5935 +++++++++ doc/it/nicksonline_co.png | Bin 0 -> 43056 bytes doc/it/notification_screen_co.png | Bin 0 -> 48043 bytes doc/it/notifylist_screen_co.png | Bin 0 -> 42182 bytes doc/it/osd_demo.png | Bin 0 -> 71780 bytes doc/it/osd_screen_co.png | Bin 0 -> 48937 bytes doc/it/quickbuttons_screen.png | Bin 0 -> 75688 bytes doc/it/quickconnect_screen.png | Bin 0 -> 11062 bytes doc/it/serverlist_co.png | Bin 0 -> 17643 bytes doc/konversation/Makefile.am | 9 + doc/konversation/addchannel.png | Bin 0 -> 6040 bytes doc/konversation/addnetwork_co.png | Bin 0 -> 14855 bytes doc/konversation/addserver_co.png | Bin 0 -> 7753 bytes doc/konversation/channel_screen_co.png | Bin 0 -> 25490 bytes doc/konversation/channel_screen_tour_co.png | Bin 0 -> 42891 bytes doc/konversation/channellist_screen_co.png | Bin 0 -> 28003 bytes doc/konversation/checkidentities.png | Bin 0 -> 7639 bytes doc/konversation/colorchooser_screen.png | Bin 0 -> 7155 bytes doc/konversation/colorize.png | Bin 0 -> 1011 bytes doc/konversation/configure.png | Bin 0 -> 1094 bytes doc/konversation/dccstatus_screen_co.png | Bin 0 -> 18463 bytes doc/konversation/editserver_screen_co.png | Bin 0 -> 8594 bytes doc/konversation/first_channel_co.png | Bin 0 -> 28553 bytes doc/konversation/first_serverlist_co.png | Bin 0 -> 9272 bytes doc/konversation/highlighting_screen_co.png | Bin 0 -> 29812 bytes doc/konversation/identities_adv_co.png | Bin 0 -> 13151 bytes doc/konversation/identities_away_co.png | Bin 0 -> 27971 bytes doc/konversation/identities_gen_co.png | Bin 0 -> 14338 bytes doc/konversation/index.docbook | 3483 +++++ doc/konversation/irc_admin.png | Bin 0 -> 205 bytes doc/konversation/irc_away.png | Bin 0 -> 181 bytes doc/konversation/irc_halfop.png | Bin 0 -> 212 bytes doc/konversation/irc_normal.png | Bin 0 -> 206 bytes doc/konversation/irc_op.png | Bin 0 -> 212 bytes doc/konversation/irc_owner.png | Bin 0 -> 212 bytes doc/konversation/irc_voice.png | Bin 0 -> 212 bytes doc/konversation/kaddressbook.png | Bin 0 -> 672 bytes doc/konversation/kimproxy_create_screen2.png | Bin 0 -> 11651 bytes doc/konversation/kimproxy_create_screen_co.png | Bin 0 -> 53750 bytes doc/konversation/led_blue_off.png | Bin 0 -> 282 bytes doc/konversation/led_blue_on.png | Bin 0 -> 250 bytes doc/konversation/led_green_off.png | Bin 0 -> 277 bytes doc/konversation/led_green_on.png | Bin 0 -> 245 bytes doc/konversation/led_red_off.png | Bin 0 -> 248 bytes doc/konversation/led_red_on.png | Bin 0 -> 255 bytes doc/konversation/led_yellow_off.png | Bin 0 -> 259 bytes doc/konversation/led_yellow_on.png | Bin 0 -> 224 bytes doc/konversation/logviewer_co.png | Bin 0 -> 22420 bytes doc/konversation/nicksonline_co.png | Bin 0 -> 32817 bytes doc/konversation/nickthemes_screen_co.png | Bin 0 -> 27299 bytes doc/konversation/notification_screen_co.png | Bin 0 -> 60442 bytes doc/konversation/notifylist_screen_co.png | Bin 0 -> 64301 bytes doc/konversation/osd_demo.png | Bin 0 -> 67027 bytes doc/konversation/osd_screen_co.png | Bin 0 -> 67636 bytes doc/konversation/prefs_identity_screen_co.png | Bin 0 -> 21694 bytes doc/konversation/quickbuttons_screen.png | Bin 0 -> 29444 bytes doc/konversation/quickconnect_screen.png | Bin 0 -> 7586 bytes doc/konversation/serverlist_co.png | Bin 0 -> 11629 bytes doc/konversation/serverlist_screen_co.png | Bin 0 -> 16017 bytes doc/konversation/urlcatcher_screen_co.png | Bin 0 -> 22315 bytes doc/konversation/webbrowser_screen_co.png | Bin 0 -> 70507 bytes doc/pt/Makefile.am | 2 + doc/pt/index.docbook | 5959 +++++++++ doc/ru/Makefile.am | 2 + doc/ru/index.docbook | 5961 +++++++++ doc/sv/Makefile.am | 2 + doc/sv/addchannel.png | Bin 0 -> 3984 bytes doc/sv/addnetwork_co.png | Bin 0 -> 11968 bytes doc/sv/addserver_co.png | Bin 0 -> 5900 bytes doc/sv/channel_screen_tour_co.png | Bin 0 -> 27271 bytes doc/sv/channellist_screen_co.png | Bin 0 -> 28917 bytes doc/sv/checkidentities.png | Bin 0 -> 5652 bytes doc/sv/colorchooser_screen.png | Bin 0 -> 5191 bytes doc/sv/dccstatus_screen_co.png | Bin 0 -> 14108 bytes doc/sv/first_channel_co.png | Bin 0 -> 20621 bytes doc/sv/first_serverlist_co.png | Bin 0 -> 6882 bytes doc/sv/highlighting_screen_co.png | Bin 0 -> 25707 bytes doc/sv/identities_adv_co.png | Bin 0 -> 10426 bytes doc/sv/identities_away_co.png | Bin 0 -> 11280 bytes doc/sv/identities_gen_co.png | Bin 0 -> 11731 bytes doc/sv/index.docbook | 5965 +++++++++ doc/sv/kimproxy_create_screen2.png | Bin 0 -> 9385 bytes doc/sv/kimproxy_create_screen_co.png | Bin 0 -> 19639 bytes doc/sv/logviewer_co.png | Bin 0 -> 18170 bytes doc/sv/nicksonline_co.png | Bin 0 -> 20764 bytes doc/sv/nickthemes_screen_co.png | Bin 0 -> 22362 bytes doc/sv/notification_screen_co.png | Bin 0 -> 19049 bytes doc/sv/notifylist_screen_co.png | Bin 0 -> 24737 bytes doc/sv/osd_demo.png | Bin 0 -> 23486 bytes doc/sv/osd_screen_co.png | Bin 0 -> 26120 bytes doc/sv/quickbuttons_screen.png | Bin 0 -> 27270 bytes doc/sv/quickconnect_screen.png | Bin 0 -> 5645 bytes doc/sv/serverlist_co.png | Bin 0 -> 9385 bytes doc/sv/urlcatcher_screen_co.png | Bin 0 -> 12773 bytes doc/sv/webbrowser_screen_co.png | Bin 0 -> 28892 bytes konversation/Makefile.am | 19 + konversation/NEWS | 5 + konversation/configure.files | 3 + konversation/configure.in.in | 48 + konversation/images/Makefile.am | 1 + konversation/images/icons/Makefile.am | 1 + konversation/images/icons/README-kimproxy | 5 + .../images/icons/cr16-action-kimproxyaway.png | Bin 0 -> 521 bytes .../images/icons/cr16-action-kimproxyoffline.png | Bin 0 -> 540 bytes .../images/icons/cr16-action-kimproxyonline.png | Bin 0 -> 460 bytes konversation/images/icons/cr22-action-char.png | Bin 0 -> 342 bytes .../images/icons/cr22-action-kimproxyaway.png | Bin 0 -> 685 bytes .../images/icons/cr22-action-kimproxyoffline.png | Bin 0 -> 711 bytes .../images/icons/cr22-action-kimproxyonline.png | Bin 0 -> 590 bytes .../images/icons/cr22-action-konv_message.png | Bin 0 -> 1091 bytes .../images/icons/cr32-action-kimproxyaway.png | Bin 0 -> 1007 bytes .../images/icons/cr32-action-kimproxyoffline.png | Bin 0 -> 1030 bytes .../images/icons/cr32-action-kimproxyonline.png | Bin 0 -> 816 bytes .../images/icons/crsc-action-kimproxyaway.svgz | Bin 0 -> 1272 bytes .../images/icons/crsc-action-kimproxyoffline.svgz | Bin 0 -> 1284 bytes .../images/icons/crsc-action-kimproxyonline.svgz | Bin 0 -> 1305 bytes .../images/icons/crsc-action-konv_message.svgz | Bin 0 -> 2946 bytes .../images/icons/hi128-app-konversation.png | Bin 0 -> 11281 bytes .../images/icons/hi16-app-konversation.png | Bin 0 -> 827 bytes .../images/icons/hi22-app-konversation.png | Bin 0 -> 1198 bytes .../images/icons/hi32-app-konversation.png | Bin 0 -> 1806 bytes .../images/icons/hi48-app-konversation.png | Bin 0 -> 3358 bytes .../images/icons/hi64-app-konversation.png | Bin 0 -> 4757 bytes .../images/icons/hisc-app-konversation.svgz | Bin 0 -> 3051 bytes konversation/images/nickicons/Makefile.am | 1 + .../images/nickicons/alternative/Makefile.am | 3 + .../images/nickicons/alternative/index.desktop | 57 + .../images/nickicons/alternative/irc_admin.png | Bin 0 -> 797 bytes .../images/nickicons/alternative/irc_away.png | Bin 0 -> 225 bytes .../images/nickicons/alternative/irc_halfop.png | Bin 0 -> 784 bytes .../images/nickicons/alternative/irc_normal.png | Bin 0 -> 746 bytes .../images/nickicons/alternative/irc_op.png | Bin 0 -> 892 bytes .../images/nickicons/alternative/irc_owner.png | Bin 0 -> 824 bytes .../images/nickicons/alternative/irc_voice.png | Bin 0 -> 811 bytes .../images/nickicons/christmas/Makefile.am | 3 + .../images/nickicons/christmas/index.desktop | 68 + .../images/nickicons/christmas/irc_admin.png | Bin 0 -> 777 bytes .../images/nickicons/christmas/irc_away.png | Bin 0 -> 770 bytes .../images/nickicons/christmas/irc_halfop.png | Bin 0 -> 859 bytes .../images/nickicons/christmas/irc_normal.png | Bin 0 -> 871 bytes konversation/images/nickicons/christmas/irc_op.png | Bin 0 -> 938 bytes .../images/nickicons/christmas/irc_owner.png | Bin 0 -> 868 bytes .../images/nickicons/christmas/irc_voice.png | Bin 0 -> 697 bytes konversation/images/nickicons/classic/Makefile.am | 3 + .../images/nickicons/classic/index.desktop | 70 + .../images/nickicons/classic/irc_admin.png | Bin 0 -> 250 bytes konversation/images/nickicons/classic/irc_away.png | Bin 0 -> 111 bytes .../images/nickicons/classic/irc_halfop.png | Bin 0 -> 275 bytes .../images/nickicons/classic/irc_normal.png | Bin 0 -> 246 bytes konversation/images/nickicons/classic/irc_op.png | Bin 0 -> 234 bytes .../images/nickicons/classic/irc_owner.png | Bin 0 -> 242 bytes .../images/nickicons/classic/irc_voice.png | Bin 0 -> 246 bytes konversation/images/nickicons/default/Makefile.am | 3 + .../images/nickicons/default/index.desktop | 69 + .../images/nickicons/default/irc_admin.png | Bin 0 -> 225 bytes konversation/images/nickicons/default/irc_away.png | Bin 0 -> 193 bytes .../images/nickicons/default/irc_halfop.png | Bin 0 -> 236 bytes .../images/nickicons/default/irc_normal.png | Bin 0 -> 227 bytes konversation/images/nickicons/default/irc_op.png | Bin 0 -> 238 bytes .../images/nickicons/default/irc_owner.png | Bin 0 -> 238 bytes .../images/nickicons/default/irc_voice.png | Bin 0 -> 238 bytes konversation/images/nickicons/oxygen/Makefile.am | 3 + konversation/images/nickicons/oxygen/index.desktop | 22 + konversation/images/nickicons/oxygen/irc_admin.png | Bin 0 -> 754 bytes konversation/images/nickicons/oxygen/irc_away.png | Bin 0 -> 472 bytes .../images/nickicons/oxygen/irc_halfop.png | Bin 0 -> 750 bytes .../images/nickicons/oxygen/irc_normal.png | Bin 0 -> 743 bytes konversation/images/nickicons/oxygen/irc_op.png | Bin 0 -> 752 bytes konversation/images/nickicons/oxygen/irc_owner.png | Bin 0 -> 739 bytes konversation/images/nickicons/oxygen/irc_voice.png | Bin 0 -> 743 bytes konversation/images/nickicons/smiling/Makefile.am | 3 + .../images/nickicons/smiling/index.desktop | 70 + .../images/nickicons/smiling/irc_admin.png | Bin 0 -> 813 bytes konversation/images/nickicons/smiling/irc_away.png | Bin 0 -> 442 bytes .../images/nickicons/smiling/irc_halfop.png | Bin 0 -> 972 bytes .../images/nickicons/smiling/irc_normal.png | Bin 0 -> 921 bytes konversation/images/nickicons/smiling/irc_op.png | Bin 0 -> 919 bytes .../images/nickicons/smiling/irc_owner.png | Bin 0 -> 898 bytes .../images/nickicons/smiling/irc_voice.png | Bin 0 -> 923 bytes konversation/images/nickicons/square/Makefile.am | 3 + konversation/images/nickicons/square/index.desktop | 69 + konversation/images/nickicons/square/irc_admin.png | Bin 0 -> 570 bytes konversation/images/nickicons/square/irc_away.png | Bin 0 -> 578 bytes .../images/nickicons/square/irc_halfop.png | Bin 0 -> 631 bytes .../images/nickicons/square/irc_normal.png | Bin 0 -> 331 bytes konversation/images/nickicons/square/irc_op.png | Bin 0 -> 546 bytes konversation/images/nickicons/square/irc_owner.png | Bin 0 -> 611 bytes konversation/images/nickicons/square/irc_voice.png | Bin 0 -> 559 bytes konversation/scripts/Makefile.am | 4 + konversation/scripts/README | 55 + konversation/scripts/bug | 18 + konversation/scripts/cmd | 31 + konversation/scripts/fortune | 53 + konversation/scripts/fortunes.dat | 680 + konversation/scripts/gauge | 71 + konversation/scripts/kdeversion | 9 + konversation/scripts/mail | 70 + konversation/scripts/media | 484 + konversation/scripts/sayclip | 19 + konversation/scripts/sysinfo | 86 + konversation/scripts/tinyurl | 31 + konversation/scripts/uptime | 56 + konversation/scripts/weather | 70 + konversation/src/Makefile.am | 73 + konversation/src/alias_preferences.cpp | 223 + konversation/src/alias_preferences.h | 51 + konversation/src/alias_preferencesui.ui | 174 + konversation/src/autoreplace_preferences.cpp | 403 + konversation/src/autoreplace_preferences.h | 57 + konversation/src/autoreplace_preferencesui.ui | 292 + konversation/src/awaymanager.cpp | 372 + konversation/src/awaymanager.h | 73 + konversation/src/blowfish/BlowfishCbc.cpp | 654 + konversation/src/blowfish/BlowfishCbc.h | 228 + konversation/src/blowfish/Makefile.am | 7 + konversation/src/blowfish/README | 3 + konversation/src/blowfish/b64stuff.cpp | 218 + konversation/src/blowfish/b64stuff.h | 53 + konversation/src/blowfish/blowfish.cpp | 129 + konversation/src/blowfish/blowfish.h | 30 + konversation/src/blowfish/mc_blowfish.cpp | 63 + konversation/src/blowfish/mc_blowfish.h | 34 + konversation/src/blowfish/newblowfish.cpp | 208 + konversation/src/blowfish/newblowfish.h | 32 + konversation/src/blowfish/oldblowfish.cpp | 425 + konversation/src/blowfish/oldblowfish1.h | 141 + konversation/src/blowfish/oldblowfish2.h | 295 + konversation/src/channel.cpp | 2960 +++++ konversation/src/channel.h | 375 + konversation/src/channeldialog.cpp | 82 + konversation/src/channeldialog.h | 46 + konversation/src/channellistpanel.cpp | 597 + konversation/src/channellistpanel.h | 147 + konversation/src/channellistviewitem.cpp | 40 + konversation/src/channellistviewitem.h | 31 + konversation/src/channelnick.cpp | 259 + konversation/src/channelnick.h | 95 + konversation/src/channeloptionsdialog.cpp | 537 + konversation/src/channeloptionsdialog.h | 102 + konversation/src/channeloptionsui.ui | 559 + konversation/src/chatwindow.cpp | 526 + konversation/src/chatwindow.h | 205 + .../src/chatwindowappearance_preferences.ui | 378 + .../src/chatwindowbehaviour_preferences.ui | 374 + konversation/src/colorsappearance_preferences.ui | 1395 ++ konversation/src/commit.h | 4 + konversation/src/common.cpp | 196 + konversation/src/common.h | 56 + konversation/src/config/Makefile.am | 8 + konversation/src/config/konversation.kcfg | 996 ++ konversation/src/config/preferences.cpp | 605 + konversation/src/config/preferences.h | 169 + konversation/src/config/preferences_base.kcfgc | 8 + konversation/src/connectionbehavior_preferences.ui | 187 + konversation/src/connectionmanager.cpp | 580 + konversation/src/connectionmanager.h | 95 + konversation/src/connectionsettings.cpp | 55 + konversation/src/connectionsettings.h | 61 + konversation/src/dcc_preferences.cpp | 54 + konversation/src/dcc_preferences.h | 38 + konversation/src/dcc_preferencesui.ui | 527 + konversation/src/dccchat.cpp | 473 + konversation/src/dccchat.h | 102 + konversation/src/dcccommon.cpp | 118 + konversation/src/dcccommon.h | 48 + konversation/src/dccrecipientdialog.cpp | 100 + konversation/src/dccrecipientdialog.h | 47 + konversation/src/dccresumedialog.cpp | 198 + konversation/src/dccresumedialog.h | 59 + konversation/src/dcctransfer.cpp | 358 + konversation/src/dcctransfer.h | 186 + konversation/src/dcctransferdetailedinfopanel.cpp | 214 + konversation/src/dcctransferdetailedinfopanel.h | 44 + konversation/src/dcctransferdetailedinfopanelui.ui | 492 + konversation/src/dcctransfermanager.cpp | 238 + konversation/src/dcctransfermanager.h | 95 + konversation/src/dcctransferpanel.cpp | 459 + konversation/src/dcctransferpanel.h | 113 + konversation/src/dcctransferpanelitem.cpp | 403 + konversation/src/dcctransferpanelitem.h | 98 + konversation/src/dcctransferrecv.cpp | 799 ++ konversation/src/dcctransferrecv.h | 184 + konversation/src/dcctransfersend.cpp | 509 + konversation/src/dcctransfersend.h | 98 + konversation/src/decoder.h | 113 + konversation/src/editnotifydialog.cpp | 103 + konversation/src/editnotifydialog.h | 50 + konversation/src/emoticon.cpp | 209 + konversation/src/emoticon.h | 47 + konversation/src/eventsrc | 973 ++ konversation/src/fontappearance_preferences.ui | 160 + konversation/src/generalbehavior_preferences.ui | 360 + konversation/src/guess_ja.cpp | 377 + konversation/src/guess_ja.h | 116 + konversation/src/highlight.cpp | 49 + konversation/src/highlight.h | 63 + konversation/src/highlight_preferences.cpp | 352 + konversation/src/highlight_preferences.h | 63 + konversation/src/highlight_preferencesui.ui | 453 + konversation/src/highlightviewitem.cpp | 93 + konversation/src/highlightviewitem.h | 72 + konversation/src/identity.cpp | 177 + konversation/src/identity.h | 133 + konversation/src/identitydialog.cpp | 642 + konversation/src/identitydialog.h | 99 + konversation/src/ignore.cpp | 30 + konversation/src/ignore.h | 46 + konversation/src/ignore_preferences.cpp | 219 + konversation/src/ignore_preferences.h | 58 + konversation/src/ignore_preferencesui.ui | 219 + konversation/src/ignorelistviewitem.cpp | 55 + konversation/src/ignorelistviewitem.h | 39 + konversation/src/images.cpp | 319 + konversation/src/images.h | 102 + konversation/src/inputfilter.cpp | 1985 +++ konversation/src/inputfilter.h | 94 + konversation/src/insertchardialog.cpp | 57 + konversation/src/insertchardialog.h | 46 + konversation/src/irccharsets.cpp | 177 + konversation/src/irccharsets.h | 106 + konversation/src/irccolorchooser.cpp | 83 + konversation/src/irccolorchooser.h | 41 + konversation/src/irccolorchooserui.ui | 148 + konversation/src/ircinput.cpp | 551 + konversation/src/ircinput.h | 91 + konversation/src/ircqueue.cpp | 209 + konversation/src/ircqueue.h | 137 + konversation/src/ircview.cpp | 1791 +++ konversation/src/ircview.h | 242 + konversation/src/ircviewbox.cpp | 141 + konversation/src/ircviewbox.h | 49 + konversation/src/joinchanneldialog.cpp | 104 + konversation/src/joinchanneldialog.h | 44 + konversation/src/joinchannelui.ui | 110 + konversation/src/konsolepanel.cpp | 75 + konversation/src/konsolepanel.h | 47 + konversation/src/konvdcop.cpp | 359 + konversation/src/konvdcop.h | 110 + konversation/src/konversation-0.19-appearance.pl | 52 + konversation/src/konversation-0.19-colorcodes.pl | 26 + konversation/src/konversation-0.19-colors.pl | 23 + .../src/konversation-0.19-custombrowser.pl | 26 + konversation/src/konversation-0.19-notifylists.pl | 43 + konversation/src/konversation-0.19-sortorder.pl | 69 + konversation/src/konversation-0.19-tabplacement.pl | 26 + konversation/src/konversation-0.20-customfonts.pl | 21 + konversation/src/konversation-0.20-quickbuttons.pl | 137 + konversation/src/konversation.desktop | 47 + konversation/src/konversation.upd | 144 + konversation/src/konversationapplication.cpp | 888 ++ konversation/src/konversationapplication.h | 169 + konversation/src/konversationmainwindow.cpp | 654 + konversation/src/konversationmainwindow.h | 148 + konversation/src/konversationsound.cpp | 41 + konversation/src/konversationsound.h | 41 + konversation/src/konversationstatusbar.cpp | 242 + konversation/src/konversationstatusbar.h | 67 + konversation/src/konversationui.rc | 82 + konversation/src/konvibookmarkhandler.cpp | 96 + konversation/src/konvibookmarkhandler.h | 55 + konversation/src/konvibookmarkmenu.cpp | 154 + konversation/src/konvibookmarkmenu.h | 65 + konversation/src/konviconfigdialog.cpp | 284 + konversation/src/konviconfigdialog.h | 124 + konversation/src/konviface.h | 89 + konversation/src/konvirc.protocol | 11 + konversation/src/konvirc6.protocol | 11 + konversation/src/konvisettingsdialog.cpp | 316 + konversation/src/konvisettingsdialog.h | 95 + konversation/src/konvisettingspage.h | 27 + konversation/src/linkaddressbook/Makefile.am | 13 + konversation/src/linkaddressbook/addressbook.cpp | 339 + konversation/src/linkaddressbook/addressbook.h | 99 + .../src/linkaddressbook/addressbook_base.cpp | 516 + .../src/linkaddressbook/addressbook_base.h | 128 + konversation/src/linkaddressbook/addresseeitem.cpp | 63 + konversation/src/linkaddressbook/addresseeitem.h | 66 + konversation/src/linkaddressbook/kimiface.h | 191 + .../src/linkaddressbook/linkaddressbookui.cpp | 191 + .../src/linkaddressbook/linkaddressbookui.h | 68 + .../src/linkaddressbook/linkaddressbookui_base.ui | 174 + .../src/linkaddressbook/nicklisttooltip.cpp | 68 + konversation/src/linkaddressbook/nicklisttooltip.h | 45 + .../src/linkaddressbook/nicksonlinetooltip.cpp | 67 + .../src/linkaddressbook/nicksonlinetooltip.h | 45 + konversation/src/log_preferences.ui | 116 + konversation/src/logfilereader.cpp | 187 + konversation/src/logfilereader.h | 59 + konversation/src/main.cpp | 103 + konversation/src/modebutton.cpp | 44 + konversation/src/modebutton.h | 40 + konversation/src/multilineedit.cpp | 79 + konversation/src/multilineedit.h | 40 + konversation/src/multilinetextedit.cpp | 175 + konversation/src/multilinetextedit.h | 41 + konversation/src/nick.cpp | 262 + konversation/src/nick.h | 55 + konversation/src/nickinfo.cpp | 445 + konversation/src/nickinfo.h | 185 + konversation/src/nicklistbehavior_preferences.cpp | 108 + konversation/src/nicklistbehavior_preferences.h | 46 + konversation/src/nicklistbehavior_preferencesui.ui | 160 + konversation/src/nicklistview.cpp | 336 + konversation/src/nicklistview.h | 77 + konversation/src/nicksonline.cpp | 975 ++ konversation/src/nicksonline.h | 261 + konversation/src/nicksonlineitem.cpp | 52 + konversation/src/nicksonlineitem.h | 58 + konversation/src/notificationhandler.cpp | 334 + konversation/src/notificationhandler.h | 61 + konversation/src/osd.cpp | 446 + konversation/src/osd.h | 124 + konversation/src/osd_preferences.cpp | 190 + konversation/src/osd_preferences.h | 57 + konversation/src/osd_preferencesui.ui | 424 + konversation/src/outputfilter.cpp | 1790 +++ konversation/src/outputfilter.h | 182 + konversation/src/query.cpp | 673 + konversation/src/query.h | 118 + konversation/src/queuetuner.cpp | 256 + konversation/src/queuetuner.h | 62 + konversation/src/queuetunerbase.ui | 767 ++ konversation/src/quickbutton.cpp | 38 + konversation/src/quickbutton.h | 42 + konversation/src/quickbuttons_preferences.cpp | 262 + konversation/src/quickbuttons_preferences.h | 53 + konversation/src/quickbuttons_preferencesui.ui | 222 + konversation/src/quickconnectdialog.cpp | 108 + konversation/src/quickconnectdialog.h | 54 + konversation/src/rawlog.cpp | 79 + konversation/src/rawlog.h | 40 + konversation/src/replycodes.h | 160 + konversation/src/scriptlauncher.cpp | 74 + konversation/src/scriptlauncher.h | 39 + konversation/src/searchbar.cpp | 245 + konversation/src/searchbar.h | 83 + konversation/src/searchbarbase.ui | 131 + konversation/src/server.cpp | 3348 +++++ konversation/src/server.h | 717 ++ konversation/src/serverdialog.cpp | 103 + konversation/src/serverdialog.h | 48 + konversation/src/servergroupdialog.cpp | 418 + konversation/src/servergroupdialog.h | 85 + konversation/src/servergroupdialogui.ui | 318 + konversation/src/servergroupsettings.cpp | 229 + konversation/src/servergroupsettings.h | 131 + konversation/src/serverison.cpp | 242 + konversation/src/serverison.h | 113 + konversation/src/serverlistdialog.cpp | 564 + konversation/src/serverlistdialog.h | 110 + konversation/src/serverlistview.cpp | 114 + konversation/src/serverlistview.h | 38 + konversation/src/serversettings.cpp | 66 + konversation/src/serversettings.h | 52 + konversation/src/ssllabel.cpp | 29 + konversation/src/ssllabel.h | 33 + konversation/src/sslsocket.cpp | 358 + konversation/src/sslsocket.h | 60 + konversation/src/statuspanel.cpp | 398 + konversation/src/statuspanel.h | 96 + konversation/src/tabnotifications_preferences.ui | 407 + konversation/src/tabs_preferences.cpp | 59 + konversation/src/tabs_preferences.h | 33 + konversation/src/tabs_preferencesui.ui | 192 + konversation/src/theme_preferences.cpp | 307 + konversation/src/theme_preferences.h | 56 + konversation/src/theme_preferencesui.ui | 222 + konversation/src/topiccombobox.cpp | 50 + konversation/src/topiccombobox.h | 39 + konversation/src/topiclabel.cpp | 385 + konversation/src/topiclabel.h | 90 + konversation/src/trayicon.cpp | 99 + konversation/src/trayicon.h | 60 + konversation/src/unicode.cpp | 145 + konversation/src/urlcatcher.cpp | 233 + konversation/src/urlcatcher.h | 66 + konversation/src/valuelistviewitem.cpp | 40 + konversation/src/valuelistviewitem.h | 33 + konversation/src/version.h | 3 + konversation/src/viewcontainer.cpp | 2454 ++++ konversation/src/viewcontainer.h | 229 + konversation/src/viewtree.cpp | 973 ++ konversation/src/viewtree.h | 112 + konversation/src/viewtreeitem.cpp | 490 + konversation/src/viewtreeitem.h | 92 + konversation/src/warnings_preferences.cpp | 185 + konversation/src/warnings_preferences.h | 48 + konversation/src/warnings_preferencesui.ui | 50 + konversation/src/watchednicknames_preferences.cpp | 420 + konversation/src/watchednicknames_preferences.h | 59 + konversation/src/watchednicknames_preferencesui.ui | 415 + po/Makefile.am | 1 + po/ar/Makefile.am | 3 + po/ar/konversation.po | 7541 +++++++++++ po/bg/Makefile.am | 3 + po/bg/konversation.po | 7602 +++++++++++ po/ca/Makefile.am | 3 + po/ca/konversation.po | 7385 +++++++++++ po/da/Makefile.am | 3 + po/da/konversation.po | 7533 +++++++++++ po/de/Makefile.am | 3 + po/de/konversation.po | 7651 +++++++++++ po/el/Makefile.am | 3 + po/el/konversation.po | 7676 +++++++++++ po/en_GB/Makefile.am | 3 + po/en_GB/konversation.po | 8388 ++++++++++++ po/es/Makefile.am | 3 + po/es/konversation.po | 7625 +++++++++++ po/et/Makefile.am | 3 + po/et/konversation.po | 7515 +++++++++++ po/fi/Makefile.am | 3 + po/fi/konversation.po | 8364 ++++++++++++ po/fr/Makefile.am | 3 + po/fr/konversation.po | 7722 +++++++++++ po/gl/Makefile.am | 3 + po/gl/konversation.po | 7746 ++++++++++++ po/he/Makefile.am | 3 + po/he/konversation.po | 7072 +++++++++++ po/hu/Makefile.am | 3 + po/hu/konversation.po | 8076 ++++++++++++ po/it/Makefile.am | 3 + po/it/konversation.po | 8033 ++++++++++++ po/ja/Makefile.am | 3 + po/ja/konversation.po | 7231 +++++++++++ po/ka/Makefile.am | 3 + po/ka/konversation.po | 7869 ++++++++++++ po/ko/Makefile.am | 3 + po/ko/konversation.po | 8336 ++++++++++++ po/pa/Makefile.am | 3 + po/pa/konversation.po | 7129 +++++++++++ po/pt/Makefile.am | 3 + po/pt/konversation.po | 7627 +++++++++++ po/ru/Makefile.am | 3 + po/ru/konversation.po | 7676 +++++++++++ po/sr/Makefile.am | 3 + po/sr/konversation.po | 7503 +++++++++++ po/sr@Latn/Makefile.am | 3 + po/sr@Latn/konversation.po | 7506 +++++++++++ po/sv/Makefile.am | 3 + po/sv/konversation.po | 7463 +++++++++++ po/tr/Makefile.am | 3 + po/tr/konversation.po | 7522 +++++++++++ po/zh_CN/Makefile.am | 3 + po/zh_CN/konversation.po | 7256 +++++++++++ po/zh_TW/Makefile.am | 3 + po/zh_TW/konversation.po | 7164 +++++++++++ stamp-h.in | 0 subdirs | 3 + 638 files changed, 331765 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 COPYING-DOCS create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 Makefile.am.in create mode 100644 README create mode 100644 TODO create mode 100644 VERSION create mode 100644 acinclude.m4 create mode 100644 aclocal.m4 create mode 100644 config.h.in create mode 100644 configure.files create mode 100644 configure.in create mode 100644 configure.in.in create mode 100644 doc/Makefile.am create mode 100644 doc/da/Makefile.am create mode 100644 doc/da/index.docbook create mode 100644 doc/es/Makefile.am create mode 100644 doc/es/addchannel.png create mode 100644 doc/es/addnetwork_co.png create mode 100644 doc/es/addserver_co.png create mode 100644 doc/es/channel_screen_tour_co.png create mode 100644 doc/es/channellist_screen_co.png create mode 100644 doc/es/checkidentities.png create mode 100644 doc/es/colorchooser_screen.png create mode 100644 doc/es/colorize.png create mode 100644 doc/es/common/1.png create mode 100644 doc/es/common/2.png create mode 100644 doc/es/common/3.png create mode 100644 doc/es/common/4.png create mode 100644 doc/es/common/5.png create mode 100644 doc/es/common/6.png create mode 100644 doc/es/common/7.png create mode 100644 doc/es/common/8.png create mode 100644 doc/es/common/9.png create mode 100644 doc/es/configure.png create mode 100644 doc/es/dccstatus_screen_co.png create mode 100644 doc/es/first_channel_co.png create mode 100644 doc/es/first_serverlist_co.png create mode 100644 doc/es/highlighting_screen_co.png create mode 100644 doc/es/identities_adv_co.png create mode 100644 doc/es/identities_away_co.png create mode 100644 doc/es/identities_gen_co.png create mode 100644 doc/es/irc_admin.png create mode 100644 doc/es/irc_away.png create mode 100644 doc/es/irc_halfop.png create mode 100644 doc/es/irc_normal.png create mode 100644 doc/es/irc_op.png create mode 100644 doc/es/irc_owner.png create mode 100644 doc/es/irc_voice.png create mode 100644 doc/es/kaddressbook.png create mode 100644 doc/es/kimproxy_create_screen2.png create mode 100644 doc/es/kimproxy_create_screen_co.png create mode 100644 doc/es/led_blue_off.png create mode 100644 doc/es/led_blue_on.png create mode 100644 doc/es/led_green_off.png create mode 100644 doc/es/led_green_on.png create mode 100644 doc/es/led_red_off.png create mode 100644 doc/es/led_red_on.png create mode 100644 doc/es/led_yellow_off.png create mode 100644 doc/es/led_yellow_on.png create mode 100644 doc/es/logviewer_co.png create mode 100644 doc/es/nicksonline_co.png create mode 100644 doc/es/nickthemes_screen_co.png create mode 100644 doc/es/notification_screen_co.png create mode 100644 doc/es/notifylist_screen_co.png create mode 100644 doc/es/osd_demo.png create mode 100644 doc/es/osd_screen_co.png create mode 100644 doc/es/quickbuttons_screen.png create mode 100644 doc/es/quickconnect_screen.png create mode 100644 doc/es/serverlist_co.png create mode 100644 doc/es/urlcatcher_screen_co.png create mode 100644 doc/es/webbrowser_screen_co.png create mode 100644 doc/et/Makefile.am create mode 100644 doc/et/index.docbook create mode 100644 doc/it/Makefile.am create mode 100644 doc/it/addchannel.png create mode 100644 doc/it/addnetwork_co.png create mode 100644 doc/it/addserver_co.png create mode 100644 doc/it/channel_screen_tour_co.png create mode 100644 doc/it/channellist_screen_co.png create mode 100644 doc/it/checkidentities.png create mode 100644 doc/it/colorchooser_screen.png create mode 100644 doc/it/first_channel_co.png create mode 100644 doc/it/first_serverlist_co.png create mode 100644 doc/it/identities_adv_co.png create mode 100644 doc/it/identities_away_co.png create mode 100644 doc/it/identities_gen_co.png create mode 100644 doc/it/index.docbook create mode 100644 doc/it/nicksonline_co.png create mode 100644 doc/it/notification_screen_co.png create mode 100644 doc/it/notifylist_screen_co.png create mode 100644 doc/it/osd_demo.png create mode 100644 doc/it/osd_screen_co.png create mode 100644 doc/it/quickbuttons_screen.png create mode 100644 doc/it/quickconnect_screen.png create mode 100644 doc/it/serverlist_co.png create mode 100644 doc/konversation/Makefile.am create mode 100644 doc/konversation/addchannel.png create mode 100644 doc/konversation/addnetwork_co.png create mode 100644 doc/konversation/addserver_co.png create mode 100644 doc/konversation/channel_screen_co.png create mode 100644 doc/konversation/channel_screen_tour_co.png create mode 100644 doc/konversation/channellist_screen_co.png create mode 100644 doc/konversation/checkidentities.png create mode 100644 doc/konversation/colorchooser_screen.png create mode 100644 doc/konversation/colorize.png create mode 100644 doc/konversation/configure.png create mode 100644 doc/konversation/dccstatus_screen_co.png create mode 100644 doc/konversation/editserver_screen_co.png create mode 100644 doc/konversation/first_channel_co.png create mode 100644 doc/konversation/first_serverlist_co.png create mode 100644 doc/konversation/highlighting_screen_co.png create mode 100644 doc/konversation/identities_adv_co.png create mode 100644 doc/konversation/identities_away_co.png create mode 100644 doc/konversation/identities_gen_co.png create mode 100644 doc/konversation/index.docbook create mode 100644 doc/konversation/irc_admin.png create mode 100644 doc/konversation/irc_away.png create mode 100644 doc/konversation/irc_halfop.png create mode 100644 doc/konversation/irc_normal.png create mode 100644 doc/konversation/irc_op.png create mode 100644 doc/konversation/irc_owner.png create mode 100644 doc/konversation/irc_voice.png create mode 100644 doc/konversation/kaddressbook.png create mode 100644 doc/konversation/kimproxy_create_screen2.png create mode 100644 doc/konversation/kimproxy_create_screen_co.png create mode 100644 doc/konversation/led_blue_off.png create mode 100644 doc/konversation/led_blue_on.png create mode 100644 doc/konversation/led_green_off.png create mode 100644 doc/konversation/led_green_on.png create mode 100644 doc/konversation/led_red_off.png create mode 100644 doc/konversation/led_red_on.png create mode 100644 doc/konversation/led_yellow_off.png create mode 100644 doc/konversation/led_yellow_on.png create mode 100644 doc/konversation/logviewer_co.png create mode 100644 doc/konversation/nicksonline_co.png create mode 100644 doc/konversation/nickthemes_screen_co.png create mode 100644 doc/konversation/notification_screen_co.png create mode 100644 doc/konversation/notifylist_screen_co.png create mode 100644 doc/konversation/osd_demo.png create mode 100644 doc/konversation/osd_screen_co.png create mode 100644 doc/konversation/prefs_identity_screen_co.png create mode 100644 doc/konversation/quickbuttons_screen.png create mode 100644 doc/konversation/quickconnect_screen.png create mode 100644 doc/konversation/serverlist_co.png create mode 100644 doc/konversation/serverlist_screen_co.png create mode 100644 doc/konversation/urlcatcher_screen_co.png create mode 100644 doc/konversation/webbrowser_screen_co.png create mode 100644 doc/pt/Makefile.am create mode 100644 doc/pt/index.docbook create mode 100644 doc/ru/Makefile.am create mode 100644 doc/ru/index.docbook create mode 100644 doc/sv/Makefile.am create mode 100644 doc/sv/addchannel.png create mode 100644 doc/sv/addnetwork_co.png create mode 100644 doc/sv/addserver_co.png create mode 100644 doc/sv/channel_screen_tour_co.png create mode 100644 doc/sv/channellist_screen_co.png create mode 100644 doc/sv/checkidentities.png create mode 100644 doc/sv/colorchooser_screen.png create mode 100644 doc/sv/dccstatus_screen_co.png create mode 100644 doc/sv/first_channel_co.png create mode 100644 doc/sv/first_serverlist_co.png create mode 100644 doc/sv/highlighting_screen_co.png create mode 100644 doc/sv/identities_adv_co.png create mode 100644 doc/sv/identities_away_co.png create mode 100644 doc/sv/identities_gen_co.png create mode 100644 doc/sv/index.docbook create mode 100644 doc/sv/kimproxy_create_screen2.png create mode 100644 doc/sv/kimproxy_create_screen_co.png create mode 100644 doc/sv/logviewer_co.png create mode 100644 doc/sv/nicksonline_co.png create mode 100644 doc/sv/nickthemes_screen_co.png create mode 100644 doc/sv/notification_screen_co.png create mode 100644 doc/sv/notifylist_screen_co.png create mode 100644 doc/sv/osd_demo.png create mode 100644 doc/sv/osd_screen_co.png create mode 100644 doc/sv/quickbuttons_screen.png create mode 100644 doc/sv/quickconnect_screen.png create mode 100644 doc/sv/serverlist_co.png create mode 100644 doc/sv/urlcatcher_screen_co.png create mode 100644 doc/sv/webbrowser_screen_co.png create mode 100644 konversation/Makefile.am create mode 100644 konversation/NEWS create mode 100644 konversation/configure.files create mode 100644 konversation/configure.in.in create mode 100644 konversation/images/Makefile.am create mode 100644 konversation/images/icons/Makefile.am create mode 100644 konversation/images/icons/README-kimproxy create mode 100644 konversation/images/icons/cr16-action-kimproxyaway.png create mode 100644 konversation/images/icons/cr16-action-kimproxyoffline.png create mode 100644 konversation/images/icons/cr16-action-kimproxyonline.png create mode 100644 konversation/images/icons/cr22-action-char.png create mode 100644 konversation/images/icons/cr22-action-kimproxyaway.png create mode 100644 konversation/images/icons/cr22-action-kimproxyoffline.png create mode 100644 konversation/images/icons/cr22-action-kimproxyonline.png create mode 100644 konversation/images/icons/cr22-action-konv_message.png create mode 100644 konversation/images/icons/cr32-action-kimproxyaway.png create mode 100644 konversation/images/icons/cr32-action-kimproxyoffline.png create mode 100644 konversation/images/icons/cr32-action-kimproxyonline.png create mode 100644 konversation/images/icons/crsc-action-kimproxyaway.svgz create mode 100644 konversation/images/icons/crsc-action-kimproxyoffline.svgz create mode 100644 konversation/images/icons/crsc-action-kimproxyonline.svgz create mode 100644 konversation/images/icons/crsc-action-konv_message.svgz create mode 100644 konversation/images/icons/hi128-app-konversation.png create mode 100644 konversation/images/icons/hi16-app-konversation.png create mode 100644 konversation/images/icons/hi22-app-konversation.png create mode 100644 konversation/images/icons/hi32-app-konversation.png create mode 100644 konversation/images/icons/hi48-app-konversation.png create mode 100644 konversation/images/icons/hi64-app-konversation.png create mode 100644 konversation/images/icons/hisc-app-konversation.svgz create mode 100644 konversation/images/nickicons/Makefile.am create mode 100644 konversation/images/nickicons/alternative/Makefile.am create mode 100644 konversation/images/nickicons/alternative/index.desktop create mode 100644 konversation/images/nickicons/alternative/irc_admin.png create mode 100644 konversation/images/nickicons/alternative/irc_away.png create mode 100644 konversation/images/nickicons/alternative/irc_halfop.png create mode 100644 konversation/images/nickicons/alternative/irc_normal.png create mode 100644 konversation/images/nickicons/alternative/irc_op.png create mode 100644 konversation/images/nickicons/alternative/irc_owner.png create mode 100644 konversation/images/nickicons/alternative/irc_voice.png create mode 100644 konversation/images/nickicons/christmas/Makefile.am create mode 100644 konversation/images/nickicons/christmas/index.desktop create mode 100644 konversation/images/nickicons/christmas/irc_admin.png create mode 100644 konversation/images/nickicons/christmas/irc_away.png create mode 100644 konversation/images/nickicons/christmas/irc_halfop.png create mode 100644 konversation/images/nickicons/christmas/irc_normal.png create mode 100644 konversation/images/nickicons/christmas/irc_op.png create mode 100644 konversation/images/nickicons/christmas/irc_owner.png create mode 100644 konversation/images/nickicons/christmas/irc_voice.png create mode 100644 konversation/images/nickicons/classic/Makefile.am create mode 100644 konversation/images/nickicons/classic/index.desktop create mode 100644 konversation/images/nickicons/classic/irc_admin.png create mode 100644 konversation/images/nickicons/classic/irc_away.png create mode 100644 konversation/images/nickicons/classic/irc_halfop.png create mode 100644 konversation/images/nickicons/classic/irc_normal.png create mode 100644 konversation/images/nickicons/classic/irc_op.png create mode 100644 konversation/images/nickicons/classic/irc_owner.png create mode 100644 konversation/images/nickicons/classic/irc_voice.png create mode 100644 konversation/images/nickicons/default/Makefile.am create mode 100644 konversation/images/nickicons/default/index.desktop create mode 100644 konversation/images/nickicons/default/irc_admin.png create mode 100644 konversation/images/nickicons/default/irc_away.png create mode 100644 konversation/images/nickicons/default/irc_halfop.png create mode 100644 konversation/images/nickicons/default/irc_normal.png create mode 100644 konversation/images/nickicons/default/irc_op.png create mode 100644 konversation/images/nickicons/default/irc_owner.png create mode 100644 konversation/images/nickicons/default/irc_voice.png create mode 100644 konversation/images/nickicons/oxygen/Makefile.am create mode 100644 konversation/images/nickicons/oxygen/index.desktop create mode 100644 konversation/images/nickicons/oxygen/irc_admin.png create mode 100644 konversation/images/nickicons/oxygen/irc_away.png create mode 100644 konversation/images/nickicons/oxygen/irc_halfop.png create mode 100644 konversation/images/nickicons/oxygen/irc_normal.png create mode 100644 konversation/images/nickicons/oxygen/irc_op.png create mode 100644 konversation/images/nickicons/oxygen/irc_owner.png create mode 100644 konversation/images/nickicons/oxygen/irc_voice.png create mode 100644 konversation/images/nickicons/smiling/Makefile.am create mode 100644 konversation/images/nickicons/smiling/index.desktop create mode 100644 konversation/images/nickicons/smiling/irc_admin.png create mode 100644 konversation/images/nickicons/smiling/irc_away.png create mode 100644 konversation/images/nickicons/smiling/irc_halfop.png create mode 100644 konversation/images/nickicons/smiling/irc_normal.png create mode 100644 konversation/images/nickicons/smiling/irc_op.png create mode 100644 konversation/images/nickicons/smiling/irc_owner.png create mode 100644 konversation/images/nickicons/smiling/irc_voice.png create mode 100644 konversation/images/nickicons/square/Makefile.am create mode 100644 konversation/images/nickicons/square/index.desktop create mode 100644 konversation/images/nickicons/square/irc_admin.png create mode 100644 konversation/images/nickicons/square/irc_away.png create mode 100644 konversation/images/nickicons/square/irc_halfop.png create mode 100644 konversation/images/nickicons/square/irc_normal.png create mode 100644 konversation/images/nickicons/square/irc_op.png create mode 100644 konversation/images/nickicons/square/irc_owner.png create mode 100644 konversation/images/nickicons/square/irc_voice.png create mode 100644 konversation/scripts/Makefile.am create mode 100644 konversation/scripts/README create mode 100755 konversation/scripts/bug create mode 100755 konversation/scripts/cmd create mode 100755 konversation/scripts/fortune create mode 100644 konversation/scripts/fortunes.dat create mode 100755 konversation/scripts/gauge create mode 100755 konversation/scripts/kdeversion create mode 100755 konversation/scripts/mail create mode 100755 konversation/scripts/media create mode 100755 konversation/scripts/sayclip create mode 100644 konversation/scripts/sysinfo create mode 100755 konversation/scripts/tinyurl create mode 100755 konversation/scripts/uptime create mode 100755 konversation/scripts/weather create mode 100644 konversation/src/Makefile.am create mode 100644 konversation/src/alias_preferences.cpp create mode 100644 konversation/src/alias_preferences.h create mode 100644 konversation/src/alias_preferencesui.ui create mode 100644 konversation/src/autoreplace_preferences.cpp create mode 100644 konversation/src/autoreplace_preferences.h create mode 100644 konversation/src/autoreplace_preferencesui.ui create mode 100644 konversation/src/awaymanager.cpp create mode 100644 konversation/src/awaymanager.h create mode 100644 konversation/src/blowfish/BlowfishCbc.cpp create mode 100644 konversation/src/blowfish/BlowfishCbc.h create mode 100644 konversation/src/blowfish/Makefile.am create mode 100644 konversation/src/blowfish/README create mode 100644 konversation/src/blowfish/b64stuff.cpp create mode 100644 konversation/src/blowfish/b64stuff.h create mode 100644 konversation/src/blowfish/blowfish.cpp create mode 100644 konversation/src/blowfish/blowfish.h create mode 100644 konversation/src/blowfish/mc_blowfish.cpp create mode 100644 konversation/src/blowfish/mc_blowfish.h create mode 100644 konversation/src/blowfish/newblowfish.cpp create mode 100644 konversation/src/blowfish/newblowfish.h create mode 100644 konversation/src/blowfish/oldblowfish.cpp create mode 100644 konversation/src/blowfish/oldblowfish1.h create mode 100644 konversation/src/blowfish/oldblowfish2.h create mode 100644 konversation/src/channel.cpp create mode 100644 konversation/src/channel.h create mode 100644 konversation/src/channeldialog.cpp create mode 100644 konversation/src/channeldialog.h create mode 100644 konversation/src/channellistpanel.cpp create mode 100644 konversation/src/channellistpanel.h create mode 100644 konversation/src/channellistviewitem.cpp create mode 100644 konversation/src/channellistviewitem.h create mode 100644 konversation/src/channelnick.cpp create mode 100644 konversation/src/channelnick.h create mode 100644 konversation/src/channeloptionsdialog.cpp create mode 100644 konversation/src/channeloptionsdialog.h create mode 100644 konversation/src/channeloptionsui.ui create mode 100644 konversation/src/chatwindow.cpp create mode 100644 konversation/src/chatwindow.h create mode 100644 konversation/src/chatwindowappearance_preferences.ui create mode 100644 konversation/src/chatwindowbehaviour_preferences.ui create mode 100644 konversation/src/colorsappearance_preferences.ui create mode 100644 konversation/src/commit.h create mode 100644 konversation/src/common.cpp create mode 100644 konversation/src/common.h create mode 100644 konversation/src/config/Makefile.am create mode 100644 konversation/src/config/konversation.kcfg create mode 100644 konversation/src/config/preferences.cpp create mode 100644 konversation/src/config/preferences.h create mode 100644 konversation/src/config/preferences_base.kcfgc create mode 100644 konversation/src/connectionbehavior_preferences.ui create mode 100644 konversation/src/connectionmanager.cpp create mode 100644 konversation/src/connectionmanager.h create mode 100644 konversation/src/connectionsettings.cpp create mode 100644 konversation/src/connectionsettings.h create mode 100644 konversation/src/dcc_preferences.cpp create mode 100644 konversation/src/dcc_preferences.h create mode 100644 konversation/src/dcc_preferencesui.ui create mode 100644 konversation/src/dccchat.cpp create mode 100644 konversation/src/dccchat.h create mode 100644 konversation/src/dcccommon.cpp create mode 100644 konversation/src/dcccommon.h create mode 100644 konversation/src/dccrecipientdialog.cpp create mode 100644 konversation/src/dccrecipientdialog.h create mode 100644 konversation/src/dccresumedialog.cpp create mode 100644 konversation/src/dccresumedialog.h create mode 100644 konversation/src/dcctransfer.cpp create mode 100644 konversation/src/dcctransfer.h create mode 100644 konversation/src/dcctransferdetailedinfopanel.cpp create mode 100644 konversation/src/dcctransferdetailedinfopanel.h create mode 100644 konversation/src/dcctransferdetailedinfopanelui.ui create mode 100644 konversation/src/dcctransfermanager.cpp create mode 100644 konversation/src/dcctransfermanager.h create mode 100644 konversation/src/dcctransferpanel.cpp create mode 100644 konversation/src/dcctransferpanel.h create mode 100644 konversation/src/dcctransferpanelitem.cpp create mode 100644 konversation/src/dcctransferpanelitem.h create mode 100644 konversation/src/dcctransferrecv.cpp create mode 100644 konversation/src/dcctransferrecv.h create mode 100644 konversation/src/dcctransfersend.cpp create mode 100644 konversation/src/dcctransfersend.h create mode 100644 konversation/src/decoder.h create mode 100644 konversation/src/editnotifydialog.cpp create mode 100644 konversation/src/editnotifydialog.h create mode 100644 konversation/src/emoticon.cpp create mode 100644 konversation/src/emoticon.h create mode 100644 konversation/src/eventsrc create mode 100644 konversation/src/fontappearance_preferences.ui create mode 100644 konversation/src/generalbehavior_preferences.ui create mode 100644 konversation/src/guess_ja.cpp create mode 100644 konversation/src/guess_ja.h create mode 100644 konversation/src/highlight.cpp create mode 100644 konversation/src/highlight.h create mode 100644 konversation/src/highlight_preferences.cpp create mode 100644 konversation/src/highlight_preferences.h create mode 100644 konversation/src/highlight_preferencesui.ui create mode 100644 konversation/src/highlightviewitem.cpp create mode 100644 konversation/src/highlightviewitem.h create mode 100644 konversation/src/identity.cpp create mode 100644 konversation/src/identity.h create mode 100644 konversation/src/identitydialog.cpp create mode 100644 konversation/src/identitydialog.h create mode 100644 konversation/src/ignore.cpp create mode 100644 konversation/src/ignore.h create mode 100644 konversation/src/ignore_preferences.cpp create mode 100644 konversation/src/ignore_preferences.h create mode 100644 konversation/src/ignore_preferencesui.ui create mode 100644 konversation/src/ignorelistviewitem.cpp create mode 100644 konversation/src/ignorelistviewitem.h create mode 100644 konversation/src/images.cpp create mode 100644 konversation/src/images.h create mode 100644 konversation/src/inputfilter.cpp create mode 100644 konversation/src/inputfilter.h create mode 100644 konversation/src/insertchardialog.cpp create mode 100644 konversation/src/insertchardialog.h create mode 100644 konversation/src/irccharsets.cpp create mode 100644 konversation/src/irccharsets.h create mode 100644 konversation/src/irccolorchooser.cpp create mode 100644 konversation/src/irccolorchooser.h create mode 100644 konversation/src/irccolorchooserui.ui create mode 100644 konversation/src/ircinput.cpp create mode 100644 konversation/src/ircinput.h create mode 100644 konversation/src/ircqueue.cpp create mode 100644 konversation/src/ircqueue.h create mode 100644 konversation/src/ircview.cpp create mode 100644 konversation/src/ircview.h create mode 100644 konversation/src/ircviewbox.cpp create mode 100644 konversation/src/ircviewbox.h create mode 100644 konversation/src/joinchanneldialog.cpp create mode 100644 konversation/src/joinchanneldialog.h create mode 100644 konversation/src/joinchannelui.ui create mode 100644 konversation/src/konsolepanel.cpp create mode 100644 konversation/src/konsolepanel.h create mode 100644 konversation/src/konvdcop.cpp create mode 100644 konversation/src/konvdcop.h create mode 100755 konversation/src/konversation-0.19-appearance.pl create mode 100644 konversation/src/konversation-0.19-colorcodes.pl create mode 100755 konversation/src/konversation-0.19-colors.pl create mode 100644 konversation/src/konversation-0.19-custombrowser.pl create mode 100644 konversation/src/konversation-0.19-notifylists.pl create mode 100755 konversation/src/konversation-0.19-sortorder.pl create mode 100755 konversation/src/konversation-0.19-tabplacement.pl create mode 100644 konversation/src/konversation-0.20-customfonts.pl create mode 100644 konversation/src/konversation-0.20-quickbuttons.pl create mode 100644 konversation/src/konversation.desktop create mode 100644 konversation/src/konversation.upd create mode 100644 konversation/src/konversationapplication.cpp create mode 100644 konversation/src/konversationapplication.h create mode 100644 konversation/src/konversationmainwindow.cpp create mode 100644 konversation/src/konversationmainwindow.h create mode 100644 konversation/src/konversationsound.cpp create mode 100644 konversation/src/konversationsound.h create mode 100644 konversation/src/konversationstatusbar.cpp create mode 100644 konversation/src/konversationstatusbar.h create mode 100644 konversation/src/konversationui.rc create mode 100644 konversation/src/konvibookmarkhandler.cpp create mode 100644 konversation/src/konvibookmarkhandler.h create mode 100644 konversation/src/konvibookmarkmenu.cpp create mode 100644 konversation/src/konvibookmarkmenu.h create mode 100644 konversation/src/konviconfigdialog.cpp create mode 100644 konversation/src/konviconfigdialog.h create mode 100644 konversation/src/konviface.h create mode 100644 konversation/src/konvirc.protocol create mode 100644 konversation/src/konvirc6.protocol create mode 100644 konversation/src/konvisettingsdialog.cpp create mode 100644 konversation/src/konvisettingsdialog.h create mode 100644 konversation/src/konvisettingspage.h create mode 100644 konversation/src/linkaddressbook/Makefile.am create mode 100644 konversation/src/linkaddressbook/addressbook.cpp create mode 100644 konversation/src/linkaddressbook/addressbook.h create mode 100644 konversation/src/linkaddressbook/addressbook_base.cpp create mode 100644 konversation/src/linkaddressbook/addressbook_base.h create mode 100644 konversation/src/linkaddressbook/addresseeitem.cpp create mode 100644 konversation/src/linkaddressbook/addresseeitem.h create mode 100644 konversation/src/linkaddressbook/kimiface.h create mode 100644 konversation/src/linkaddressbook/linkaddressbookui.cpp create mode 100644 konversation/src/linkaddressbook/linkaddressbookui.h create mode 100644 konversation/src/linkaddressbook/linkaddressbookui_base.ui create mode 100644 konversation/src/linkaddressbook/nicklisttooltip.cpp create mode 100644 konversation/src/linkaddressbook/nicklisttooltip.h create mode 100644 konversation/src/linkaddressbook/nicksonlinetooltip.cpp create mode 100644 konversation/src/linkaddressbook/nicksonlinetooltip.h create mode 100644 konversation/src/log_preferences.ui create mode 100644 konversation/src/logfilereader.cpp create mode 100644 konversation/src/logfilereader.h create mode 100644 konversation/src/main.cpp create mode 100644 konversation/src/modebutton.cpp create mode 100644 konversation/src/modebutton.h create mode 100644 konversation/src/multilineedit.cpp create mode 100644 konversation/src/multilineedit.h create mode 100644 konversation/src/multilinetextedit.cpp create mode 100644 konversation/src/multilinetextedit.h create mode 100644 konversation/src/nick.cpp create mode 100644 konversation/src/nick.h create mode 100644 konversation/src/nickinfo.cpp create mode 100644 konversation/src/nickinfo.h create mode 100644 konversation/src/nicklistbehavior_preferences.cpp create mode 100644 konversation/src/nicklistbehavior_preferences.h create mode 100644 konversation/src/nicklistbehavior_preferencesui.ui create mode 100644 konversation/src/nicklistview.cpp create mode 100644 konversation/src/nicklistview.h create mode 100644 konversation/src/nicksonline.cpp create mode 100644 konversation/src/nicksonline.h create mode 100644 konversation/src/nicksonlineitem.cpp create mode 100644 konversation/src/nicksonlineitem.h create mode 100644 konversation/src/notificationhandler.cpp create mode 100644 konversation/src/notificationhandler.h create mode 100644 konversation/src/osd.cpp create mode 100644 konversation/src/osd.h create mode 100644 konversation/src/osd_preferences.cpp create mode 100644 konversation/src/osd_preferences.h create mode 100644 konversation/src/osd_preferencesui.ui create mode 100644 konversation/src/outputfilter.cpp create mode 100644 konversation/src/outputfilter.h create mode 100644 konversation/src/query.cpp create mode 100644 konversation/src/query.h create mode 100644 konversation/src/queuetuner.cpp create mode 100644 konversation/src/queuetuner.h create mode 100644 konversation/src/queuetunerbase.ui create mode 100644 konversation/src/quickbutton.cpp create mode 100644 konversation/src/quickbutton.h create mode 100644 konversation/src/quickbuttons_preferences.cpp create mode 100644 konversation/src/quickbuttons_preferences.h create mode 100644 konversation/src/quickbuttons_preferencesui.ui create mode 100644 konversation/src/quickconnectdialog.cpp create mode 100644 konversation/src/quickconnectdialog.h create mode 100644 konversation/src/rawlog.cpp create mode 100644 konversation/src/rawlog.h create mode 100644 konversation/src/replycodes.h create mode 100644 konversation/src/scriptlauncher.cpp create mode 100644 konversation/src/scriptlauncher.h create mode 100644 konversation/src/searchbar.cpp create mode 100644 konversation/src/searchbar.h create mode 100644 konversation/src/searchbarbase.ui create mode 100644 konversation/src/server.cpp create mode 100644 konversation/src/server.h create mode 100644 konversation/src/serverdialog.cpp create mode 100644 konversation/src/serverdialog.h create mode 100644 konversation/src/servergroupdialog.cpp create mode 100644 konversation/src/servergroupdialog.h create mode 100644 konversation/src/servergroupdialogui.ui create mode 100644 konversation/src/servergroupsettings.cpp create mode 100644 konversation/src/servergroupsettings.h create mode 100644 konversation/src/serverison.cpp create mode 100644 konversation/src/serverison.h create mode 100644 konversation/src/serverlistdialog.cpp create mode 100644 konversation/src/serverlistdialog.h create mode 100644 konversation/src/serverlistview.cpp create mode 100644 konversation/src/serverlistview.h create mode 100644 konversation/src/serversettings.cpp create mode 100644 konversation/src/serversettings.h create mode 100644 konversation/src/ssllabel.cpp create mode 100644 konversation/src/ssllabel.h create mode 100644 konversation/src/sslsocket.cpp create mode 100644 konversation/src/sslsocket.h create mode 100644 konversation/src/statuspanel.cpp create mode 100644 konversation/src/statuspanel.h create mode 100644 konversation/src/tabnotifications_preferences.ui create mode 100644 konversation/src/tabs_preferences.cpp create mode 100644 konversation/src/tabs_preferences.h create mode 100644 konversation/src/tabs_preferencesui.ui create mode 100644 konversation/src/theme_preferences.cpp create mode 100644 konversation/src/theme_preferences.h create mode 100644 konversation/src/theme_preferencesui.ui create mode 100644 konversation/src/topiccombobox.cpp create mode 100644 konversation/src/topiccombobox.h create mode 100644 konversation/src/topiclabel.cpp create mode 100644 konversation/src/topiclabel.h create mode 100644 konversation/src/trayicon.cpp create mode 100644 konversation/src/trayicon.h create mode 100644 konversation/src/unicode.cpp create mode 100644 konversation/src/urlcatcher.cpp create mode 100644 konversation/src/urlcatcher.h create mode 100644 konversation/src/valuelistviewitem.cpp create mode 100644 konversation/src/valuelistviewitem.h create mode 100644 konversation/src/version.h create mode 100644 konversation/src/viewcontainer.cpp create mode 100644 konversation/src/viewcontainer.h create mode 100644 konversation/src/viewtree.cpp create mode 100644 konversation/src/viewtree.h create mode 100644 konversation/src/viewtreeitem.cpp create mode 100644 konversation/src/viewtreeitem.h create mode 100644 konversation/src/warnings_preferences.cpp create mode 100644 konversation/src/warnings_preferences.h create mode 100644 konversation/src/warnings_preferencesui.ui create mode 100644 konversation/src/watchednicknames_preferences.cpp create mode 100644 konversation/src/watchednicknames_preferences.h create mode 100644 konversation/src/watchednicknames_preferencesui.ui create mode 100644 po/Makefile.am create mode 100644 po/ar/Makefile.am create mode 100644 po/ar/konversation.po create mode 100644 po/bg/Makefile.am create mode 100644 po/bg/konversation.po create mode 100644 po/ca/Makefile.am create mode 100644 po/ca/konversation.po create mode 100644 po/da/Makefile.am create mode 100644 po/da/konversation.po create mode 100644 po/de/Makefile.am create mode 100644 po/de/konversation.po create mode 100644 po/el/Makefile.am create mode 100644 po/el/konversation.po create mode 100644 po/en_GB/Makefile.am create mode 100644 po/en_GB/konversation.po create mode 100644 po/es/Makefile.am create mode 100644 po/es/konversation.po create mode 100644 po/et/Makefile.am create mode 100644 po/et/konversation.po create mode 100644 po/fi/Makefile.am create mode 100644 po/fi/konversation.po create mode 100644 po/fr/Makefile.am create mode 100644 po/fr/konversation.po create mode 100644 po/gl/Makefile.am create mode 100644 po/gl/konversation.po create mode 100644 po/he/Makefile.am create mode 100644 po/he/konversation.po create mode 100644 po/hu/Makefile.am create mode 100644 po/hu/konversation.po create mode 100644 po/it/Makefile.am create mode 100644 po/it/konversation.po create mode 100644 po/ja/Makefile.am create mode 100644 po/ja/konversation.po create mode 100644 po/ka/Makefile.am create mode 100644 po/ka/konversation.po create mode 100644 po/ko/Makefile.am create mode 100644 po/ko/konversation.po create mode 100644 po/pa/Makefile.am create mode 100644 po/pa/konversation.po create mode 100644 po/pt/Makefile.am create mode 100644 po/pt/konversation.po create mode 100644 po/ru/Makefile.am create mode 100644 po/ru/konversation.po create mode 100644 po/sr/Makefile.am create mode 100644 po/sr/konversation.po create mode 100644 po/sr@Latn/Makefile.am create mode 100644 po/sr@Latn/konversation.po create mode 100644 po/sv/Makefile.am create mode 100644 po/sv/konversation.po create mode 100644 po/tr/Makefile.am create mode 100644 po/tr/konversation.po create mode 100644 po/zh_CN/Makefile.am create mode 100644 po/zh_CN/konversation.po create mode 100644 po/zh_TW/Makefile.am create mode 100644 po/zh_TW/konversation.po create mode 100644 stamp-h.in create mode 100644 subdirs diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..258b1ba --- /dev/null +++ b/AUTHORS @@ -0,0 +1,7 @@ +Dario Abatianni +Peter Simonsson +Eike Hein +Shintaro Matsuoka +Eli MacKenzie +İsmail Dönmez +John Tapsell diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..9fe1a71 --- /dev/null +++ b/COPYING @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Steet, Fifth Floor, Cambridge, MA 02110-1301, 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 diff --git a/COPYING-DOCS b/COPYING-DOCS new file mode 100644 index 0000000..4a0fe1c --- /dev/null +++ b/COPYING-DOCS @@ -0,0 +1,397 @@ + GNU Free Documentation License + Version 1.2, November 2002 + + + Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (Thus, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document 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. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation 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. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..3bc1a72 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1333 @@ +Changes from 1.0.1 to 1.1: +We are extremely pleased to announce Konversation's newest major release, v1.1. +Konversation 1.1 is a special release for us in multiple ways: It's our farewell +to KDE 3, by way of being the last major release built upon that venerable +platform. It's also our biggest release yet, in terms of the number and +magnitude of the changes. + +The additions and improvements in this release are both user-visible and under +the hood. Some of the highlights are rewritten connection handling (robustness +and correctness improvements, better support for IRC URLs, bookmarking and +more), redone DCC with better UI and Passive/Reverse DCC support, a redone away +system with the addition of auto-away support, redone and much more useful +remember / marker line support, a new outbound traffic scheduler that is capable +of aggressive throttling to avoid flooding while smartly reordering messages to +improve latencies, great convenience additions like a "Next Active Tab" shortcut, +and much, much more, along with a large number of bugfixes and tweaks to round +things out. Note: All fixes made since RC1 are marked with a "[New since RC1]" +label in the changelog. + +We're confident that this release is the best and most robust version of +Konversation published so far, and upgrading comes highly recommended to all +users. Enjoy! + + +Text views +* Added an option to hide the scrollbar in chat windows. +* Don't scroll to bottom if the view was scrolled up before resizing. +* Fixed chat views occassionally not being scrolled to the bottom at their + inception with long backlog appends. +* Fixed an off-by-one error in scrollback culling. +* Fixed a bug that lead to single leading whitespace characters in lines being + omitted from display in chat windows. +* Now preserving trailing whitespace in raw log tabs. +* Fixed display of '<' and '>' in backlog lines. +* Fixed copy/paste with shortcuts other than the default Ctrl+C/V ones. +* Fixed onotice display. +* Fixed middle-click-to-open-in-new-tab on chat window URLs when Konqueror + wasn't running. +* Fixed superfluous closing parenthesis being inserted after links in lines + which contain multiple links followed by closing parenthesis. +* Fixed URLs with encoded hash mark %23 being incorrectly passed off to handler. +* Fixed variable expansion causing certain URLs to be corrupted when pasted. +* Added a "Save Link As" item to the context menu of links in the chat window. +* Have the "Save as..." dialog suggest a file name. +* Implemented Shift+Click to "Save as..." URLs.. +* Made the channel links context menu work in server status views. +* Fixed nickname links in chat view messages created as a result of '/msg + ' commands erroneously prepending '->' to nicknames. +* Fixed operations on nicknames containing "\" characters from the nickname + context menu. +* Fixed query view context menus operating on the wrong nickname under certain + circumstances. +* Fixed a bug that caused the "Send File..." action in the generic query context + menu to pick the wrong recipient after hovering the user's own nick in the + chat display. +* Fixed date display not using the locale's date format. +* Fixed IRC color parsing so that the colors gets reset to default if no color + numbers were given. +* Fixed a bug that could cause the text selection in a chat window to be messed + up when new text was appended. + +Marker/Remember Lines +* Konversation now distinguishes between manually and automatically inserted + marker lines, making the "show line in all chat windows" preference less + confusing. +* The automatically inserted remember lines when chat windows are hidden are now + "sliding", i.e. there is only one per chat window, and it moves. +* Automatically inserted remember lines will now optionally only be inserted + when there's actually new text being appended to the chat window (enabled by + default). +* The automatic remember line will now also be inserted when the window has lost + focus. +* Added an action to clear all marker lines in a chat window. +* Improved marker lines-related preferences and terminology. +* Improved the appearance of marker lines in the chat window. +* Made the (marker line-related and other) identity default settings consistent + between the initial identity and additional newly created identities. +* Fixed hidden join/part/quit events marking tabs as dirty, allowing multiple + consecutive remember lines to appear. +* Fixed crash when minimizing or closing the application window prior to any tab + switch when the auto-insertion of remember lines is enabled. + +Input line +* Fixed input line contents rather than actual sent text being appended to the + input history upon a multi-line paste edit. +* Special characters and IRC color codes will now be inserted at the cursor + position rather than the end of the input line contents. + +Nickname list +* Implemented an additional "Sort by activity" nicklist sorting mode. +* Added Oxygen nicklist icon theme by Nuno Pinheiro. +* The list of nickname list themes is now sorted alphabetically. +* Fixed race condition when removing a nicklist theme (listview would be + repopulated before deletion was complete). +* Fixed using the wrong palette for the disabled text color in the nickname + list. +* Fixed moving back from the custom alternate background color to system colors + in the channel nickname listviews when disabling the "Use custom colors for + lists, [...]" preference. +* Cleanups in the nicklist item code. + +Tab bar / Tree list +* Added option to add and remove a channel from its network's auto-join list + from the tab context menu. +* Added option to close tabs using middle-mouse. +* Slightly sped up tab switching by eliminating some redundant UI action state + updates. +* Channel tabs will no longer close when kicked, but rather grey out on the tab + bar and offer context menu actions to rejoin. +* Channel and query tabs will now grey out on the tab bar when disconnected and + no higher priority notification is present. Channel tabs will only ungrey if + and when the channel is successfully rejoined after reconnect; query tabs + ungrey immediately once reconnected. +* Display tooltips for truncated treelist items. +* Fixed forwarding keyboard events received by the treelist to Konsole widgets + and focus adjustment thereafter as well as generally after switching to + Konsole tabs by other means. +* Fixed treelist scrollbar not picking up on new palette when the KDE color + scheme changes. +* Fixed a bug that could cause a crash when the view treelist would receive + keypress events during application shutdown. +* [New since RC1] Fixed a corner case where a server status item could become a + child item of another server status item when dragging it below an special + application pane item such as DCC Status or Watched Nicks Online. +* [New since RC1] Fixed a crash when using the mouse wheel on the list within + ~150ms of a drag and drop operation. + +System Tray icon +* Remember and recreate minimized-to-tray state across sessions. +* Added option for hidden-to-tray startup. +* Reload tray icons when the icon theme changes at runtime. +* Added option to not blink the systray icon, but just light it up. + +Channel Settings Dialog +* Added a search line to the ban list. +* Fixed sorting the ban list by time set. +* Made the ban list's "Time Set" column use KDE locale settings for the date + format. +* Fixed OK'ing/Cancel'ing/closing the Channel Settings Dialog not dealing with + open ban list in-line edits correctly. +* Reset topic editbox when the channel options dialog has been dismissed with + cancel. +* Fixed incorrect time display in the topic history list in the Channel Settings + dialog. + +Server List Dialogs +* Moved the "Show at application startup" option for the Server List dialog to + the dialog itself. +* Auto-correct hostnames and passwords entered with preceding or trailing spaces + in the Server List dialog. +* Don't allow impossible ports to be set for servers. +* Sensible default focus in the server list dialog. +* Fixed unresponsive, defective Server List dialog window appearing at + application startup using the Beryl or Compiz compositing window managers. + +Interface Misc +* Added a "Next Active Tab" keyboard shortcut to jump to the next active tab with + the highest priority notification. +* Added a Find Previous standard action. +* Have the "Insert Character" dialog pick up on text view font changes. +* Show correct number of colors in the color chooser dialog. +* Made "Alternate Background" colorchooser disable when unneeded. +* Fixed crash when changing the KDE color scheme while a non-chat tab is open. +* The encoding selection now allows returning to the used identity's default + encoding setting. +* Update actions on charset changes. +* Added Notifications Toggle and Encoding sub-menu to the window menu. +* Moved "Hide Nicklist" menu action from Edit to Settings. +* Fixed the "Automatically join channel on invite" setting not to show an + inquiring dialog anyway. +* Fixed saving the state of the invitation dialog option in the Warning Dialogs + preferences. +* Added a warning dialog for quitting with active DCC file transfers. +* Return focus to the text display widget after closing the search bar in a log + reader view. +* Made pressing Return or Enter in the Log File Viewer's size spinbox apply the + setting, just as pressing the Return button. +* Fixed a bug where the SSL padlock icon would be shown on a non-SSL connection + (and clicking would cause a crash). +* Empty topic labels will no longer show empty tooltips, but rather none at all. +* Added a sample 12-hour clock format string to the timestamp format combobox. +* Timestamp format list is no longer localized. +* Robustness improvements and less UI quirks around channel password handling. +* Improved general layout and consistency of tab, chat view, query and topic + context menus. Added some missing icons. +* Fixed some bugs of UI actions not being appropriately as their context + changes. +* Fixed enabled state of "Close All Open Queries" action not being updated + correctly when queries are closed by way of closing a status view tab. +* The window caption is now properly being reset when the last tab is closed. +* Made units in spinboxen in the identity and app preferences UI more + consistent. +* Minor fixes to accelerators and tabbing order in various dialogs. + +Commands +* Support command aliases in network connect commands. +* Turned parameter-less '/away' into a toggle: Sets away state with default + message initially, and unsets away state if already away. +* Added an '/aunaway' command to complement '/aaway' (previously, there was only + '/aback'). +* Added support for '/kill'. +* A '/join' command for an already-joined channel will now focus it. +* Added an '/encoding' command as an alias to '/charset'. +* '/charset' and '/encoding' now accept 'latin-1' as an alias for 'iso-8859-1'. +* Improved messages for the '/charset' and '/encoding' commands. +* Rewrote /me parsing to be less hackish and display usage info with an empty + parameter. +* '/msg ' is no longer treated as equivalent to '/query '. +* '/msg ' will now error out when lacking a message parameter. +* '/query [message]' will now error out when recipient is a channel. +* Added a '/queuetuner' command to bring up the outbound traffic scheduler's + tuning/debug pane. + +Notifications +* Seperated query messages and messages containing the user's nickname into two + distinct KNotify events. +* Made the tab notification color of private messages configurable independently + from normal messages. +* Don't highlight own nick on topic created by messages. +* Fixed disabling notifications for a tab not cancelling highlight sounds. +* Fixed a race condition where a highlight's autotext reply would outrun the + original line's tab notification. +* Fixed actions in queries and DCC chats producing message notification events + (rather than the correct private message ones). +* Changed the OSD screensaver check logic to work in KDE 4. +* [New since RC1] Fixed on screen display occassionally reverting to the default + position when using the settings dialog to change unrelated settings. + +Connection handling +* Improved behavior with regard to reusing existing connections in connection + attempts that provide an initial channel to join, such as command line + arguments, the DCOP interface, the bookmark system or irc:// links). + Previously, the application would have inconsistently either reused an + existing or created a new connection. +* Better dialog messages in the interactive variant of the decision to either + reuse or create a new connection (from the Server List dialog and the Quick + Connect dialog). +* Improved and more consistent display of connection names (i.e. network or + server host name) throughout the application. +* Much improved irc:// URL support for connection intanciation, with support + added for IPv6 host names and many of the features proposed by the Mirashi + specification. +* Eliminated redundant irc:// URL parsing codepaths in favor of a single one. +* Added support for irc:// URLs to the chat views. +* Removed "konversationircprotocolhandler" shell script. The Konversation + executable now understands irc:// URLs directly. +* Initiating connections from command line arguments and options now works also + when the application is already running. +* Fixed a bug that would cause a connection initiated from command line options + not to get past the identity validation stage when the configuration file was + unitialized and empty. +* The server list dialog will now always be closed when starting Konversation + with command line arguments to initiate a connection, consistent with the + configuration-based auto-connect behavior. +* Providing a channel in the creation of a new connection (i.e. via command line + arguments, the DCOP interface, the Quick Connect dialog, the bookmark system + or irc:// links) now consistently pre-empts the stored auto-join channel list + if the target of the connection is a network or the hostname is found to be + part of a configured network. Previously, this would only work for Quick + Connect and the bookmark system (which caused the infamous Sabayon user flood + in #kde due to their "Get Support" desktop link connecting to Freenode, which + in an unconfigured Konversation has #kde in its auto-join list). +* Connections now have globally unique IDs. +* The DCOP interface now understands connection IDs in addition to host names. +* The scripting systems now uses globally unique connection IDs rather than + server host names to refer to connections, fixing a bug where scripted + responses were being handed to all connections sharing a hostname (which was + actually intentional in the absence of connection IDs, but undesirable for + users). +* Improved iteration behavior over a network's server list on connection losses. +* The "Reconnect" action now works also when Konversation doesn't consider the + connection to be in a disconnected state. +* Improved the server status view messages related to reconnection attempts. +* Consistently apply the "Reconnect delay" setting (previously confusingly named + "Reconnect timeout"), which wasn't done before. +* Fixed a bug that could cause the connection process to claim that a DNS lookup + was successful when it actually wasn't. +* Fixed opening bookmarks with spaces in the target address name (which may be a + network name, and networks may have spaces in their name). +* Properly update the state of the "Add/Remove to Watched Nicknames" nickname + context menu actions when the connection isn't to a config-backed network, in + which case there's no way to store and make use of those list entries. +* Fixed a crash when quitting the application with a resident connection that + disconnected due to an SSL error. +* Fixed crashes in the DCOP interface if no connection was present. +* Make the "Reconnect" action available even while ostensibly in the process of + connecting. +* Fix possible crash when closing all views and subsequently creating a new + connection. +* Fixed crash upon auto-connect at application startup. +* Improved the naming of preferences related to automatic reconnection attempts + to be less confusing. +* Made it possible to set the number of automatic reconnection attempts to + unlimited. +* Provided better default values to the preferences related to automatic + reconnection attempts. +* Fixed crash when opening a Konsole tab and Konsole was not installed. +* Fixed allowing the user to create an infinite loop of showing the SSL + connection details dialog upon being presented with the invalid certificate + multiple choice dialog at connection time by checking "Do not ask again" and + then clicking "Details". + +Identities +* Made it possible to set a Quit message independently from the Part message. +* Saving a newly-created identity is no longer allowed without entering a real + name. +* Apply switching the identity in the identity dialog as opened from the network + dialog to the network's settings. +* Have the Edit/Delete/Up/Down buttons for the nickname list of an Identity + correctly change state according to the selection + +Away system +* Added per-identity support for automatic away on a configurable amount of user + desktop inactivity and/or screensaver activation, along with support for + automatic return on activity. +* Fixed the "Global Away" toggle to make sense and update its state properly. +* Turned parameter-less '/away' into a toggle: Sets away state with default + message initially, and unsets away state if already away. +* Added an '/aunaway' command to complement '/aaway' (previously, there was only + '/aback'). +* Broadly rewrote away management related code for improved robustness and less + duplication and hacks (e.g. no more abuse of multiServerCommand for global + away). + +DCC +* Massive DCC refactoring and improved reliability. +* Passive DCC support (Reverse DCC RECV, SEND). +* Replaced the DCC Transfer Details dialog with a retractable transfer details + pane directly in the DCC Status tab. +* Added DCC transfer average speed reading to the DCC transfer details panel. +* The DCC Status tab now remembers its column widths across sessions. +* Fixed duplicated quotation marks around file names in DCC transfer status + messages. +* Fixed "Open File" DCC dialog remembering the last viewed location incorrectly. +* Added an "Open Folder" button to the DCC transfer details panel. +* Added check for whether the URL is well-formed before initiating a DCC send. + Fixes a bug of dragging a nickname link in the chat view onto the query chat + view drop target starting a DCC transfer that cannot succeed. +* Ported the DCC code away from relying on server group IDs to refer to + connections, made it use connection IDs instead. Fixes potential bugs with + multiple concurrent connections to the same network. +* Fixed queued DCC transfer items not picking up on download destination + directory changes. +* Fixed bug leading to crash upon initiating DCC Chat when "Focus new tabs" was + enabled. +* [New since RC1] New transfer items added to the DCC panel's transfer list are no + longer automatically selected, meaning work on other items in the list occuring + at the same time no longer gets interrupted. +* [New since RC1] The "Filename:" line in the DCC panel's detailed info pane is + now using text squeezing to avoid an increase in minimum window width with long + file names. +* [New since RC1] Failed receives now longer show 833TB/s as their transfer + speed. + +Blowfish support +* Fixed FiSH-style +p prefix to send clear text to channel despite an encryption + key being set. +* Text encoding is now being applied to the cleartext, rather than the + ciphertext. This fixes using characters outside the ASCII range with blowfish + encryption. +* Fixed CTCP (and thus DCC) requests to nicknames for whom an encryption key is + set. +* Added support for encrypted topics. +* If an encryption key is set, a lock icon will now be shown next to the input + box. +* Added a '/showkey ' command to show the encryption key for the + target in a popup dialog. + +Auto-replace +* Improved auto-replace behavior with multiple matches in one line (fixes + multiple Wikipedia links). +* Fixed bug that could cause auto-replace to replace the wrong group of the + matching string. +* Auto-replace is now case-sensitive in regular expression mode. +* Added regular expression editor button to auto-replace preferences. +* Fixed conditional enabling of the RegExpEditor button in the auto-replace + preferences page. + +Ignore +* Fixed being asked twice whether to close a query upon ignoring the opponent. +* Fixed crash when opting to close a query upon chosing to ignore the opponent + from the context menu of his nickname. + +Watched Nicknames +* Improved robustness of the Watched Nicknames Online system. +* The "Offline" branches in the "Watched Nicks Online" list will now be omitted + when there are no offline nicks for the respective network. +* Fixed display of WHOIS spam prompted by the Watch List's WHOIS activity. +* Connections to non-config-backed targets no longer show in Watched Nicks + Online. +* [New since RC1] Actually honor the preference to enable/disable the Watched + Nicknames Online system, and apply it at runtime. +* [New since RC1] Make sure the periodic Watched Nicknames Online check actually + starts running within the same session after adding the first nickname to the + list. +* [New since RC1] Fixed a crash on quit with the Watched Nicks Online tab open and + there being an open connection to a network that nicks are being watched for. + +Channel List +* IRC markup is now removed from content in the Channel List view. +* Speed improvements in Channel List views. +* Fixed keyboard accelerator collisions in Channel List views. +* Allow higher values than 99 in the min/max users filter spin boxes in Channel + List views. + +Under the Hood / Protocol +* Rewrote the outbound queue scheduling system to be smart enough to reorder + outbound traffic to reduce interactive latency while aggressively throttling + the rate to prevent flooding. Use '/queuetuner' to tweak. +* Rearranged when and how auto-who is triggered upon channel join a bit, to + avoid excessive flooding on multiple concurrent joins in some cases. +* Auto-Who reliability improvements. +* Fixed auto-join with very many channels (the auto-join command would exceed + the maximum buffer length; it is now split into multiple commands as needed). +* Fixed bugs around rejoining channels after reconnects related to the cause of + the disconnect, channel passwords and picking the actual list of joined + channels over the network's auto-join list. +* Improved behavioral consistency in situations where the auto-join list is + preempted by a transitory auto-join channel (bookmarks, etc.). +* Fixed bug that caused the topic state not to be cleared properly prior to + rejoining channels during reconnects. +* Fixed onotice payload being cut off after the first word. +* Changed RPL_WHOISOPERATOR handling to internationalize the common case ("is an + IRC Operator") and otherwise passthrough the string sent by the server. +* Fixed parsing of alternate invite format on Asuka ircds (QuakeNet). +* Added support for PRIVMSG from the server. +* Support RPL_UMODEIS. +* Announce 'k' channel mode (i.e. channel key) changes in non-raw mode as well. +* The command part of CTCP requests is now always converted to uppercase before + sending, as some clients don't like lower- or mixed-case commands as the user + may have entered them. +* Display mode for your nick and channels you're not in. +* Fixed per-channel encoding settings for the channels of a network being lost + when the network is renamed. +* Fixed crash when receiving actions for channels the client is not attending. +* Made newline handling in the DCOP interface more robust, fixing a potential + security problem (CVE-2007-4400). +* A few speed optimizations and memory leak fixes. +* [New since RC1] Fixed a crash on quit during KDE logout or when quitting by + DCOP. + +Included scripts +* Support for KMPlayer in the 'media' script (based on the window caption, as + KMPlayer has no proper appropriate DCOP interface). +* Added KPlayer support to the 'media' script (also caption-based). +* Added support for Audacious to the 'media' script. +* Fixed problems in disk space calculation in the 'sysinfo' script caused by + wrapped df(1) output. +* Added KDE 4 support to the 'sysinfo' script. +* Removed some bashisms from the 'sysinfo' script. +* Rewrote 'weather' script for increased reliability in error handling and + better readability. +* Removed broken 'qurl' script in favor of new 'tinyurl' one. +* Fixed the 'fortune' script not working properly when variable expansion is + turned off in the preferences. +* [New since RC1] Fixed a bug in the 'media' script that caused it to break when + querying Audacious with audtool not being available. + +Packaging +* [New since RC1] Standards compliancy fixes in the application .desktop file and + the nicklist icon theme .desktop files. + +Build +* Fixed build with --enable-final. + +------------------------------------------------------------------------------- + +Changes from 1.0 to 1.0.1 +We are pleased to announce the immediate availability of Konversation 1.0.1, +a maintenance release featuring notable improvements for users of right-to- +left languages (including new Arabic and Hebrew translations), further re- +finement of the user interface and application functionality, and fixes for +minor defects found in the previous release. + +* A bug that caused left-to-right text contained in lines determined to be + right-to-left text to appear reversed has been fixed. +* Whether a line is treated as right-to-left vs. left-to-right text is now + determined by the amount of each type of character in the line, improving + the user experience in chats involving bi-directional text considerably. +* The "Edit Network" dialog has been refined for clarity and ease of use. +* A warning dialog to prevent accidentally quitting Konversation has been + added. +* The Auto Replace list can now be sorted. +* The '/media' script command now sports improved player recognition, enhan- + ced and easier configurability, the ability to distinguish between audio + and video media as well as newly added support for kdetv. New '/audio' and + '/video' command aliases have been added to expose these new abilities. +* The lower boundary of the default DCC port range has been raised from 1025 + to 1026 to avoid conflicts with the commonly blocked Windows RPC port 1025. +* Dismissing an OSD notification by clicking on it will now also cancel the + systray notification flash. +* A new configuration file option [OSD]OSDCheckDesktopLock has been added, + allowing to manually disable the screensaver check in non-KDE environments + that do not support it, causing the OSD not to be displayed. +* A bug that could lead to the "Switch to" sub-menu in the context menus of + tabs not to be updated properly upon switching tabs has been fixed. +* A bug that caused the 'irc setBack' DCOP call not to function has been + fixed. +* A bug that caused ampersands in the names of tabs not to be displayed and + an immediately following character to be used as keyboard accelerator has + been fixed. +* A bug that caused ignoring nicknames with '[' or ']' characters in them to + fail has been fixed. +* Command aliases containing regular expression syntax can no longer cause + built-in commands not to function. +* A bug that caused the Konversation irc:// protocol handler not to function + has been fixed. Its compatibility with systems that do not use the GNU bash + shell as default shell has been improved. +* A notable number of code quality improvements suggested by KDEs automated + quality control service EBN have been implemented. + +------------------------------------------------------------------------------- + +Changes from 0.19 to 1.0 +We are extremely pleased to announce the immediate availability of Konversation +1.0, a significant milestone in the lifetime of the Konversation project. This +release includes major new functionality as well as a large amount of +improvements to existing functionality, with an emphasis on user interface +polish and overall reliability. Notable new features include a vertical treelist +of tabs as an alternative to the traditional tab bar, auto-replacement of words +in incoming and outgoing messages, an improved Channel Settings dialog now +featuring a ban list, an optional expanding input box and many improvements to +both DCC file transfers and DCC chats. Enjoy! + + +User Interface +* It is now possible to place the tabs on the left side of the application +window. + This has been implemented as a treelist of tabs. The treelist supports all of + the cosmetic and interactive properties of the original horizontal tab bar, + including colored notifications, LED icons, (hover) close buttons with delayed + activation, reordering, drag'n'drop and mouse wheel cruising. And a few tricks + of its own. +* Connection status tabs now feature specific context menu entries to disconnect + and reconnect, as well as to join a channel on that connection. +* The automatic resizing of tabs in the tab bar first implemented in version + 0.19 is now optional. +* The grouping behavior of Channel List and Raw Log tabs in the tab bar has been + improved. +* Disabling notification for a tab will now unset the active notification. +* The enabled/disabled state of the notifications for connection status tabs +will + now be remembered across sessions for configured networks. +* The speed of switching tabs in quick succession with the auto-spellchecking + preference enabled has been improved. +* Using custom fonts in the user interface is now optional. The font used by the + tab bar is now configurable. +* Events in the connection status tabs are now logged into separate logfiles. +* The Channel Settings dialog now includes a Ban List tab that allows viewing, + adding and removing bans in a channel. The dialog can now be opened from the + menu bar and chat window context menu in addition to the button in the topic + area. +* Mode and topic handling in the Channel Settings dialog and the channel mode + buttons have been overhauled to make them more robust and reliable. +* The number of Quick Buttons to show below the nickname list in channel tabs is + now configurable. Additional buttons may be added or existing buttons removed. +* Konversation now supports auto-replacing words in incoming and outgoing + messages. Regular expressions are supported. The auto-replace configuration +can + be found in the preferences dialog. The static Wiki link feature found in +older + versions has been retired in favor of an auto-replace rule. +* The search bar has been redesigned to provide a better user experience. +* The "Find Next" action will now open the search bar when there is no active + search, matching the behavior of Konqueror and other KDE applications. +* The sorting of the nick completion list has been improved to put the last + active user for a given completion prefix at the beginning of the list. +* The tab completion of the user's own nickname has been reenabled. +* The nick completion feature has been significantly cleaned up and made more + reliable. A bug that could lead to an application crash during nick completion + has been fixed. +* An option to expand the vertical size of the input box automatically when the + text entered grows beyond the length of a single line has been added. +* The behavior of the input box on pasting text including leading or trailing + newline characters has been improved never to cause lines being sent without + user acknowledgement. +* The input box of connection status, channel and query tabs will now be +disabled + and the nickname list of channel tabs cleared when the respective server + connection is closed. +* Konversation can now optionally insert a remember line whenever a tab is +hidden, + either by switching to a different tab or minimizing the window. +* Multiple consecutive remember lines will no longer be inserted. +* Remember lines can now also be inserted into the chat windows of connection + status and DCC Chat tabs. +* The Colored Nicknames feature will now always assign the same color to the +same + nickname. +* The number of backlog lines to show in the chat window is now configurable. +* The recognition of URLs in the chat window has been improved to cope better + with URLs containing or being surrounded by parenthesis and to exclude +trailing + dots and commas. +* Channel links following mode characters or surrounded by interpunctuation are + now properly recognized in the chat window. +* The context menus for URLs and channel links in the topic area now match the + context menus in the chat window. +* Multiple ignore or unignore actions ordered at the same time will no longer be + shown on separate lines in the chat window. +* The nickname context menus in the chat window, topic are and the nickname list + will now show "Ignore", "Unignore" and "Add to Watched Nicknames" entries as + applicable. +* A bug that could lead to the chat window nickname context menu actions ceasing + to function after the targeted user left the channel has been fixed. +* The Server List dialog now allows connecting to a specific server in a network + even when a connection to that network has been previously established. If +that + connection is active, a dialog box will verify whether to disconnect from the + current server and connect to the chosen one instead, otherwise the connection + will simply be reestablished using the newly chosen server. +* The Quick Connect feature will now properly warn when the identity to be used + in the connection attempt is not set up properly. +* The appearance and behavior of the warning about an incorrectly set-up +identity + have been improved. A prior connection attempt will now be automatically +resumed + after the identity settings have been corrected. +* Many of the pages in the Konversation preferences dialog have been redesigned + and rewritten for improved consistency, reliability and clarity. The general + layout of the dialog has been improved as well. +* The naming of certain actions in the Configure Shortcuts dialog has been + improved to make them easier to recognize outside of their normal context in + the application interface. +* Numerous improvements to keyboard navigation have been made. +* The nickname list now longer allows drag'n'drop of channel or user links from + the chat window onto list entries, as a DCC transfer of those data sources + cannot succeed. +* The preference to show or hide the real names of users in the nickname list +will + now be applied immediately. +* The columns of the nickname list will no longer resize erratically when the + preferences to show or hide real names and hostmasks are changed at runtime. +* A bug that could lead to nicknames being sent as messages when double-clicking + a selection of multiple nicknames in the nickname list has been fixed. +* The placement of actions in the application menus has been improved. +* The shown/hidden state of the application menubar will now be remembered +across + sessions. When the menubar is hidden, a menu action to show it again will now +be + added to the chat window context menu. +* The "Close All Open Queries" menu action is now be disabled properly when +there + are no open queries. +* A bug that could lead to the "Close All Open Queries" menu action failing to + properly close all open queries has been fixed. +* A bug that could lead to an application crash when closing the tab after +choosing + to ignore someone in a query has been fixed. +* The "Hide Nicklist" menu action will now be disabled properly when the tab +shown + does not have a nickname list has been fixed. +* The actions in the "Insert" menu will now be disabled properly when the +current + tab does not support them. +* The default double-click action in the "Watched Nicks Online" tab is now to +open + a query to the respective contact. +* The sorting in the Watched Nicks Online tab has been improved: Offline users +are + now always sorted at the bottom. +* Several bugs in the "Watched Nicknames Online" tab that could lead to +application + crashes have been fixed. +* Several errors in the chat window status messages produced by the Watched +Nicks + Online system have been corrected. +* A bug that could lead the the columns in the "Watched Nicks Online" list +resizing + erratically has been fixed. +* A bug that could lead to the status bar not being cleared properly when the +last + tab was closed or the application window lost focus after a link was + launched from the chat window has been fixed. +* The display of temporary and static info texts in the status bar has been + improved not to interfere with each other and provide more useful information. + Also, the status bar lag info section is now updated more consistently to +avoid + jumping around of the other status bar sections. +* A bug that could lead to a wrong nickname count being shown in the status bar + of channel tabs has been fixed. +* Repeated triggering of the "Open URL Catcher" menu action will now properly + show and hide the URL Catcher tab. +* The warning about pasting text with multiple lines can now be properly +disabled + and reenabled from the Warning Dialogs preferences page. +* A bug that could lead to IRC bookmarks showing up as actions in the Configure + Shortcuts dialog has been fixed. +* A bug that could lead to changes of the global KDE icon set not being applied + to the tab bar close buttons immediately has been fixed. +* A bug that caused the application window to change its horizontal size after + opening a Query to a user with a very long hostmask has been fixed. The DCC + Chat and query tabs now use the same heading style as channel tabs. +* A bug that could lead to the topic and nickname list areas not keeping their + size properly across tab switches has been fixed. +* A bug that could lead to certain types of KNotify event notifications not + being executed properly when the system tray icon was enabled has been fixed. +* A bug that could lead to ampersands in network names being shown as + underscores in the menu under certain circumstances has been fixed. +* A bug that could lead to an application crash when trying to access + non-existing tabs via the Alt+number keyboard shortcuts has been fixed. +* A bug that could lead to the toolbar being hidden after it was edited has been + fixed. +* A bug that could lead to the chat window context menu not being cancelled + properly when clicking outside of it has been fixed. +* A bug that could lead to heavy disk seeking when the splitters separating + the topic area and the nickname list from the chat window were moved has been + fixed. +* The option to only show the application in the system tray at all times has + been retired in favor of the standard KDE mechanic of minimizing into the + system tray. + +Commands +* The 'Now Playing' script invoked via the /media command alias now features + support for XMMS and KSCD as well as improved support for untagged media files + playing in Amarok. Support for non-ASCII encodings in file names and meta tags + has been improved as well. +* New "/hop" and "/dehop" commands to grant or remove half-op status from a user + have been added. +* A new "/devoice" command has been added. +* A new "/kickban" command to ban and immediately kick a user has been added. It + supports the same parameters as the "/ban" command plus an additional "kickban + reason" parameter. +* Commands to grant or remove status for users will now be applied to the user's + own nickname when no nickname parameter is given. +* The "/unignore" command now supports the same simple nickname-only format as + the "/ignore" command. +* If given no parameter, the "/away" command will now set the away state with + the default away message. The "/back" and "/unaway" commands can be used to + unset the away state. +* You may now use "%nick" as a placeholder for your own nickname in the auto- + connect commands for a network. +* A bug that could lead to the auto-connect commands for a network not being + executed correctly has been fixed. + +DCC +* DCC file transfers now support file names containing spaces on send, receive + and resume. The automatic replacement of spaces with underscores in file names + can now be optionally disabled in the DCC preferences. +* File names are no longer being needlessly lower-cased during DCC transfers. +* The DCC file transfer and DCC Chat info messages shown in the chat window have + been significantly improved to provide more useful information while being +less + excessively verbose. +* DCC Chats will now be logged properly. +* It is now possible to select multiple files in the DCC Status tab. +* The default size of the buffer used in DCC transfers has been increased to + 8192kb for improved DCC performance. +* The DCC Status tab will no longer show a speed of '?' for completed, failed or + aborted transfers. +* Bugs that could lead to the IP used for DCC transfers not being retrieved from + the server correctly upon reconnect or in general on certain servers have been + fixed. +* A bug that could lead to the progress bar of a transfer in the DCC Status tab + being rendered at a wrong position has been fixed. +* A bug that could lead to Konversation's CPU usage spiking to 100% after a DCC + Chat was closed from the remote side has been fixed. +* Several bugs that could lead to application crashes in DCC Chat tabs after the + server connection from which the DCC Chat originated was closed have been +fixed. + +Technology +* Konversation will now properly split up very long lines into multiple messages + by calculating the length of the message preamble and the number of bytes of +the + text payload. Encodings that use multiple or variable numbers of bytes per + character are accounted for. +* The Disconnect and Reconnect menu actions and the respective input box +commands + have been rewritten for increased reliability. Their state will now be updated + properly, and they will quit the IRC server in the correct manner. +* A previous away state will now be recreated upon reconnection to a server. +* The Quick Connect feature will now no longer join the auto-join channels of + the configured network that the quick connect server was recognized as being a + part of. +* The "Konversation" and "KonvDCOPIdentity" DCOP objects have been renamed to + "irc" and "identity", respectively. Several bugs in the DCOP API have been + fixed, and deprecated interfaces removed. +* Processing of the user lists of newly joined channels has been rewritten to + fix several bugs, including improved compatibility with the Bip IRC proxy and + other servers. +* The lag calculation and timeout handling code has been rewritten for improved + reliability and performance. +* Recognition of the half-op user status has been improved. +* The detection of text being typed into the input box to prevent focussing new + tabs at inconvenient times has been improved to work correctly with non-ASCII + characters. +* The handling of channel user limits in the Channel Settings dialog is now more + reliable. +* Support for mode flags encountered on UnrealIRCD servers has been improved. +* Support for RPL_DATASTR on UnrealIRCD servers has been improved. +* A bug that could lead to the mode flags displayed for users not being updated + properly after they were kicked from a channel has been fixed. +* A bug that could lead to iterating over a configured network's servers failing + after a connection failure has been fixed. +* A bug that could lead to Konversation connecting to the wrong server in a + network when choosing to connect to a specific server from the Server List +dialog + has been fixed. +* A dialog will now ask the user for an additional nickname when all nicknames + configured in the identity where tried unsuccessfully during a connection + attempt. This replaces the previous behavior of repeatedly appending +underscores + to the last nickname, which eventually ran into the nickname length limit on +the + server. +* A bug that could lead to unnecessary nick changes immediately after connecting + to a server has been fixed. +* A bug that could lead to Konversation trying to auto-identify multiple times + upon connect on certain servers has been fixed. +* A bug that could lead to Konversation not picking up on users leaving a + channel without providing a part or quit message on UnrealIRCD servers has +been + fixed. +* Changes to the list of auto-join channels for a network will now be applied + immediately. +* The auto-reconnect preference will now be properly applied at runtime. +* Konversation will no longer enable IDENTIFY-MSG mode on servers that support +it, + but continues to be able to process messages with IDENTIFY-MSG prefixes in +case + an involved IRC proxy chose to enable IDENTIFY-MSG mode. +* The broken default for the Custom Web Browser preference has been fixed. +* Konversation will no longer allow Konsole tabs to be opened in KDE + environments in which the use of terminals is prohibited by the KIOSK +framework. +* A bug that could lead to an application crash when a Konsole tab was closed + from the Konsole component's context menu has been fixed. +* A bug that could lead to an application crash when a channel was joined while + the application window was hidden has been fixed. + +------------------------------------------------------------------------------- + +Changes from 0.18 to 0.19 +We are extremely pleased to announce the immediate release of Konversation 0.19. +The focus +of this release is on extending and improving upon established functionality. +Most notable +in this regard are significantly improved management of IRC networks and servers +all across +the application, a redesigned tab bar and better support for common IRC +commands. A long +list of further additions and improvements has us confident of this being the +best version +of Konversation yet. Enjoy! + + +User Interface +* The Server List dialog has been rewritten to allow direct manipulation of a +network's + servers and features more intelligent sorting behavior. Reordering networks +via drag + and drop is now possible. A behavioral audit of all actions in the dialog +resulted in + numerous improvements. +* A redesigned tab bar sports highly configurable text- and LED icon-based +notifications + as well as more intelligent scaling behavior under space-critical conditions. +* Tabs are now intelligently grouped around their respective connection status +tab. +* Status tab labels now display the user-configured network name where +appropriate. +* The Find Text dialog has been replaced by a search bar that no longer +interrupts your + workflow. +* Channel links in the chat area now feature a context menu for quick access to +common + actions. +* Usage of the status bar has been extended to show context-relevant information +as the + cursor passes over various interface elements. The lag information segment is +now + only shown where appropriate. +* A channel's topic can now be cleared by setting an empty text in the Channel +Options + dialog. +* The Channel Options dialog has been redesigned to allow editing the current +topic + while browsing a channel's topic history. +* The Watched Nicknames interface has been fully integrated with network +management. +* Pressing the Arrow Down key in the input line now preserves any input entered +by + adding it to the history. +* Commands may now be sent as regular messages by typing Ctrl+Enter. +* The multi-line paste editor window now highlights whitespace characters and +prepends + the existing content of the input line. +* The Colored Nicknames feature has been improved to better handle nickname +changes and + immediately apply any changes to the color palette. +* Some previously not configurable notification events have been made +configurable. +* Users leaving a server will now be announced in any query you have open with +them. +* Query tab labels will now update when a user you have a query open with +changes + his/her name. +* The DCC file transfer dialogs have seen a number of cosmetic improvements. +Among other + things, in the event of a file being renamed on save, the local file name is +now shown + across the application. +* Various status and error messages have been rewritten for improved consistency +and + clarity. +* The KDE standard text font will now be correctly set as initial default chat +font. +* It is now possible to skip displaying a server's MOTD on connect. +* If the application is set to display a server's MOTD in a fixed-width font and +the + previously configured default chat font is already a fixed-width font, the +chat font + will now be used rather than the global KDE default fixed-width font. +* The state of the automatic spell checking functionality is now remembered +across + sessions and set for all tabs. +* Networks no longer lose their channel history when their settings are changed. +* The Server List dialog will no longer close when a connection attempt fails +due to + the identity not being set up correctly. +* After changing your nickname using the optional drop-down menu to the left of +the + input line, focus will now be returned to the input line. +* The configuration dialog has been rewritten to correctly update the button +state of + its primary actions and improve consistency with the KDE style guide. +* The vertical and horizontal splitters in channel tabs now behave better when +the + application window is resized and correctly retain their positions across +sessions. +* The OSD preview in the OSD settings page is now always shown correctly. +* The OSD will no longer be shown when the desktop is locked. +* A bug that prevented copying text from the chat area under certain +circumstances has + been fixed. +* Keyboard search in the channel nickname list has been fixed. +* A number of issues affecting nickname context menus in the chat area have been +fixed. +* A bug leading to a wrong operator count in the status bar has been fixed. +* It is no longer possible to add nameless networks or hostless servers in the +respon- + sible management dialogs. +* Bugs that led to parts of the interface not reacting to KDE color scheme +changes have + been fixed. +* The status bar now correctly reacts to KDE font size changes. +* A bug that led to the application window resizing on overly long status bar +contents + has been fixed. +* A bug that led to multiple remember lines being inserted into the frontmost +tab when + away mode was activated has been fixed. +* A bug that led to wrong link addresses being opened from the chat area has +been fixed. +* Bugs that led to wrong URLs being produced by dragging a link from the chat +area to + the input line have been fixed. +* Channel names are now better recognized as such by the chat area. + + +Bookmarking +* Bookmark titles now default to the channel name. +* Bookmarks now store the network name rather than the server address where +available. +* Bookmarks now support IPv6 addresses. + + +Commands +* The '/server' command now recognizes a greater variety of address notations +including + network names. +* The '/names' command now always succeeds in returning the user list of a +channel. +* The '/topic' command now always succeeds in returning the topic of a channel. +* A '/dns' command has been added that facilitates resolving the host name of a +user on + the server as well as generic host names. Reverse resolve is supported on KDE +3.5.1+. +* An '/unignore' command has been added. +* A '/disconnect' command has been added. +* A '/reconnect' command has been added that disconnects and then reconnects the +respec- + tive server. +* A '/setkey' command has been added to set the Blowfish encryption/decryption +key for + the respective context. +* The '/list' command now correctly opens the Channel List tab. +* A bug in parsing the arguments of the '/join' command has been fixed. +* Usage information and error reporting for various commands has been rewritten +for + improved consistency and clarity. +* A bug that led to a 'clear' command being sent to the server when using the +'/clear' + command to clear the contents of a query tab has been fixed. + + +Miscellaneous +* The 'media' script has been rewritten and now features improved compatibility +with + common character sets, greatly enhanced support for the Kaffeine media player +and + newly added support for the Yammi media player. +* The 'sysinfo' script has been rewritten to produce more concise output and +better + handle a variety of storage scenarios. +* The convenience feature expanding [[term]] into a Wikipedia link is now +localizable + and generates a link that performs an intelligent lookup for the term in the +Wiki- + pedia rather than assume a correct direct link. + + +Technology +* Konversation now depends on KDE 3.4+. +* The preferences storage system has been rewritten to facilitate easier +maintenance + and faster development in future release cycles. +* Localized support for a long list of IRC protocol primitives has been added. +* The application will now correctly iterate over a network's servers on +successive + failed connection attempts. +* When the '/server' command or the Quick Connect dialog is used to connect to a + server that has previously been added to a network in the Server List dialog, +it + will be recognized as being part of the network and the respective identity + settings will be applied. +* The automated reply to a highlight event can now reference the groups of the +matched + pattern by the identifiers %1-%9 and the entire match by the identifier %0. +* The CABAP IDENTIFY-MSG technology is now supported. +* Compatibility with the Unreal IRC server has been improved. +* Initial support for Blowfish encryption (compatible with mIRCryption and FiSH) +has + been added. Note that Diffie-Hellman key exchange (DHX) is not yet supported. +* The Watched Nicknames reporting has been made more reliable. +* Socket handling in the DCC file transfer feature has been improved. +* Alpha-blending of icons in the channel nickname list has been fixed. +* Support for the iso-2022-jp encoding has been enhanced. +* The custom web browser feature will now automatically append the URL as a +parameter + to the specified command when the %u identifier is missing. +* Channel modes are now correctly cleared and updated in the internal +representation + on rejoin. +* A bug that led to an infinite loop during a connection attempt when all +nicknames + configured in the identity were in use has been fixed. +* A bug that could lead to a crash when opening the log file for a closed +connection has + been fixed. + +------------------------------------------------------------------------------- + +Changes from 0.17 to 0.18 +- All nicks were blue when colored nicks are disabled with some setups +- /cycle now works as expected +- /gauge script was not working correctly when given a bigger than 100 argument +- /mail script has been added +- Button to invoke Regular Expression Editor (if installed) in Settings -> +Highlight. +- Complete command line argument system for connection +- An option to disable clickable nicks . Add ClickableNicks=false to +konversationrc to disable it. +- Fixed a big memory leak in message processing +- Nicklist slider now correctly resizes in all channels when its resized and +correctly restores on startup +- [[foo]] is now a link to http://en.wikipedia.org/wiki/foo . We will expand +this to local wikipedia's in a later release [Update: Now fixed in 0.19] + + +Changes from 0.16 to 0.17 +- Add an option to hide realnames in nicklist +- Show away users as disabled ala Xchat +- Remove sort by away status +- Fix whois replies for normal users on safe channels ( IRCNet alike ) +- Fix whois replies from ircd-hybrid ( Efnet alike ) +- Better handling of quiet bans ( especially Freenode ) +- KDE color scheme is now honered in topic widget +- Enable clickable nicks even if colored nicks are off +- Per identity pre-shell command support with a GUI +- Bookmarking support +- Detect Japanese encoding correctly while trying to auto-detect Unicode + +Changes from 0.15 to 0.16 +- Dropping URLs onto nick on nicklist or onto query initiates DCC send +- You can now do SSL connections from Quick Connect Dialog +- Nicklist Icon Themes +- New topic widget +- Added a channel dialog +- Made the nickname box optional +- Fix DCC resume when its set to auto-accept +- Calculate DCC CPS more accurately +- Colored nicks support +- Added dcop functions to set away and added alt+a shortcut to toggle away +- Clicking nicks in channel text will now open a query and similarly, + clicking #foo will now join channel #foo +- Nicks in channel view now have a context menu as in nicklistview +- Tab at begining of line inserts last completed nick +- A media script added to replace amarok,juk,noatun,kaffeine scripts. + Use /media instead of using /amarok,/juk etc. +- Links can now be dragged & dropped from channels +- Midde clicking urls now opens them in new tab in konqueror ( if konqueror is +used for links ) +- Improved unicode detection +- Fix unicode detection for strings containing color markup +- /omsg,/onotice support +- Added an option to use an IPv4 interface for IPv6 dcc sends +- A new /google script added to search Google using Google SOAP api +- Redesigned settings page +- A new application icon +- Lots of optimizations all around + +Changes from 0.14 to 0.15 +- Ported socket code to KNetwork. Weird connection problems should be gone now +- Get default username/ident information from system +- Support for bouncer prefixes in nick completion +- Dcc port range support +- Scripts now works with /script or /exec script +- Improved bidi support. +- Cleaned up settings dialog +- Added an option how to get own IP for DCC send/chat +- "Open Watched Nicks Online panel on startup" option +- Support encoding settings per channel +- SSL Support +- KIO-fied local I/O on DCC send/receive +- OSD Positioning Support +- New network based server settings +- Added an option to stay in systray all the time +- Full irc:/ url support (channel name & password now supported in url) +- /charset support +- auto /WHO support +- display away status of nicks in nick list + +Changes from 0.13 to 0.14 +- Added irc "pseudo" command /prefs for changing settings without settings +dialog. +- Measure away time and make it available via placeholder (%t) +- (Very much) Improved OSD. +- New application icons by luciash d' being . Thanks! +- Added /server command for connecting to a server. +- After the connection is lost and the old nickname is still in use, + the nickbutton in the channelwindows is updated to the new nick. +- Now you can read utf8 encoded messages even if your locale is not unicode +- "Do not show this dialog again" preferences now works correctly +- Added an "Insert Remember Line" feature. + The user can mark the position in the channel where he stopped + reading(because he is away for a short time). + When he comes back, he can scroll back to this mark and read + what he missed. +- Added the possibility to execute commands on server connection(for + authentication and such things). Can be configured in the "Edit Server" + dialog. +- Added further timestamps for am/pm (BR 79612) +- Added QuickConnect dialog by Michael Goettsche. (Thanks once again) +- Properly receive a logout/shutdown request and terminate konversation, + instead of minimizing to the systray. +- Make OSD switchable on/off via DCOP. Thanks to Michael Goettsche! (BR 75870) +- Dates can now be shown, next to the timestamp. Patch by Michael Goettsche + (BR 82785) (thanks!) +- Added DCC auto-resume feature by Michael Goettsche (BR 81740) (thanks!) +- Added systray notification +- Added shell like nick completion mode (aka uga mode) +- Implemented a cleaner way of handling tab shortcuts +- Implemented DCC Chat +- Hilight mailto: links +- Topic line can now be hidden +- Added an away nickname +- Added /aaway, /ame and /amsg +- Added "Open URL" context menu to channel list entries +- Implemented slower / faster blinking of tabs for more / less important events +- Less important events like Join, Part and Nickchanges can now be hidden +- Custom CTCP Version Reply Support +- Added a shortcut to close all open queries +- Added a patch by Thomas Nagy to cycle tabs with mouse scroll wheel (thanks!) +- Added logfile reader +- Added patch by Gary Cramblitt to enhance DCC panel (thanks!) +- Added patch by Gary Cramblitt to select custom web browser command (thanks!) +- When the server goes offline, now all associated tabs get crossed out +- Added a multi line pasting editor +- Nicks Online is now a tabbed panel, rather than separate window. +- Added sound support to the highlight list +- Added regular expression support to the highlight list^ +- Follow the style guide when the tray icon is enabled by minimizing to tray +when + the close button is clicked. +- Auto text feature on highlight events +- DCC resume offers to rename a transfer now +- Added patch by Ruud Nabben to enable hiding of IRC colors (thanks!) +- Various small fixes and additions + +Changes from 0.12 to 0.13 +- Added an option to hide hostmasks in channel nick lists +- Autojoin on invite with user interaction implemented +- Added URL catcher interface +- Added user interface for "don't show again" dialogs +- Added slovenian translation by Barko (thanks!) +- Added korean translation by Hye-Shik Chang (thanks!) +- Added option to place tabs on top +- Color configuration is now in preferences dialog +- Quick buttons configuration is now in preferences dialog +- Notify list is now in preferences dialog +- Option for a background image added +- Added /quote command for raw server messages +- Added Copy URL into clipboard for URL catcher +- Added option for reconnect on too long lag +- Added "Server list" menu entry to "File" menu +- Applied a patch by Peter Simonsson (thanks!) +- Patch added Color picker, IRC colors and KNotify events +- Added support for command aliases +- Encodings are now on per-identity basis +- Added indicator to show own away state +- Added system tray icon patch by Frauke Oster (thanks!) +- Channel list update is now more CPU friendly +- Tell the user why the channel list could not be opened +- Channel list now sorts correctly when number column is clicked +- Applied a patch by Christian Muehlhaeuser to enable bigger mode changes +(thanks) +- Applied a patch by Christian Muehlhaeuser to right-align close widgets +(thanks) +- Info button on dcc panel now works +- Added /unban command +- Applied a patch by Christian Muehlhaeuser for OSD functions (thanks) +- Applied a patch by Sascha Cunz for extended user modes beyond @ and + (thanks) +- Applied a patch by Steve Wollkind to close visible tab via shortcut (thanks) + +Changes from 0.11 to 0.12 +- Now handles multi server mode in one single window +- Fixed the wrong Ops counter +- Added /notify command and respective dcop calls +- Added support for /oper command +- Implemented /ban command and menu items +- Added shortcut (F3) for search dialog +- History does not get cleared on cursor up/down anymore +- Added context menu to copy URLs immediately +- Added paragraph spacing +- Added hostmask column to nick list +- Implemented background hostmask scanning +- Recognises now who set the first topic +- Added nickname sorting options +- Sorting now has up/down arrows +- Added channel list panel +- Added russian translation by Stanislav Karchebny (thanks!) +- Applied some patches by Stanislav Karchebny +- Added PgUp/PgDown support to Channels, Queries and Status views +- Added rename button to identity page to overcome QComboBox limitations +- Tabs now blink in the last highlight color to indicate important text +- Tabs don't get to front anymore while the user is typing in an input line +- Added shortcut editor dialog +- Added konsole panel (thanks to Mickael Marchand) + +Changes from 0.10 to 0.11 +- Added a patch by Bart Verwilst to provide automatic service registration +(thanks!) +- Added "Hide Menu" function +- Improved server connection code to stop konversation freezes at startup +- Server lag calculation after reconnect fixed +- Implemented own async lookup class to throw out broken QDns +- Added prelimnary application icons +- Send File in dcc panel now works +- Added Send File context menu item in text views +- Added dialog for Resume / Overwrite DCC Get files +- Added large paste warning dialog +- Close Buttons on tabs are now an option +- Added context menu on tabs with close item +- Added ALT+1 - ALT+9 for switching tabs +- Applied a big patch by Alex Zepeda. Thanks! +- First working DCOP implementation +- Implemented a simple search dialog +- Added a raw log pane + +Changes from 0.9 to 0.10 +- Font encodings are now set via KCharsets +- Implemented different identities +- Added double click actions to nick list and notify list +- Added support for ASCII-BEL +- Added custom spacing and margin +- Added close buttons for the tabs +- Redesign of the color configuration dialog +- Switched to kapp->config() to properly remember dialog status +- Color code parsing now works with QRegExp +- CTCP-Ping now works +- Removed files that are no longer needed +- Updated German translation + +Changes from 0.8 to 0.9 +- Added strikeout support (untested yet) +- Added Swedish translation, done by Karolina Lindqvist (thanks!) +- Added optional timestamps to chat windows +- Quick Buttons and Channel Mode Buttons can now be hidden +- Added support for multi channel joins +- Added #include "sourcefile.moc" to all Q_OBJECTS to speed up compiles +- Added support for autoconnect to server +- Inserted a QSplitter between channel text and nick list +- Added support for background colors +- Reduced flickering on blinking tabs +- Added experimental support for foreign language characters +- Added ignore list functionality +- Added away / unaway messages +- DCC folder can now be selected vial GUI +- Applied a patch by Barak Bloch to fix foreign character set behaviour +(thanks!) +- Updated German translation + +Changes from 0.7 to 0.8: +- DCCs can now be opened (started) using the 'open' button +- DCCs can now be aborted using the 'abort' button +- Added support for /users reply +- Added support for /invite and 341 reply +- Added support for 401 error reply +- Added /smsg for "silent messages" +- Text and Nicklist-Fonts can now be selected via GUI +- Changed server ping response again to make dalnet ircd happy +- Fixed nicklist sorting in channels +- Switched to kdevelop 2.1.4 to hopefully fix some compile problems +- Made Notices appear a bit different +- DCC recipient list now gets sorted +- Made text widget not scroll when scroll bar isn't completely down +- Parsed WHOIS messages into human readable form +- Pasting multiline text into input lines now behaves as expected +- Hilights now honor the sending nick, too (patch by Suran. Thanks!) +- You can now hilight all your own lines independently +- Fixed the problem in the appearance dialog with font names +- Added DCC error dialogs +- Quit/Nickchange/Kicks are now only reported in channels where the nick +actually is in +- Fixed bug with lockups on defective logfiles +- Added support for EUR currency symbol +- Added keyboard handling to navigate between pages +- Code cleanup in nick list +- Added first support for custom colors in nick list +- Added application dsescription for the 'About' dialog +- Major restructuring of the server status panel diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..28fadaa --- /dev/null +++ b/INSTALL @@ -0,0 +1,181 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..2369f25 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,5 @@ +AUTOMAKE_OPTIONS = foreign 1.6.1 + +include admin/deps.am +include admin/Doxyfile.am +SUBDIRS=$(TOPSUBDIRS) diff --git a/Makefile.am.in b/Makefile.am.in new file mode 100644 index 0000000..e46b27c --- /dev/null +++ b/Makefile.am.in @@ -0,0 +1,4 @@ +AUTOMAKE_OPTIONS = foreign 1.6.1 + +include admin/deps.am +include admin/Doxyfile.am diff --git a/README b/README new file mode 100644 index 0000000..2b8703d --- /dev/null +++ b/README @@ -0,0 +1,4 @@ +Konversation website: http://konversation.kde.org/ +Konversation wiki: http://konversation.kde.org/wiki +Bug tracker: http://bugs.kde.org/ +IRC channel: #konversation on irc.freenode.org diff --git a/TODO b/TODO new file mode 100644 index 0000000..5f60c7b --- /dev/null +++ b/TODO @@ -0,0 +1,3 @@ +See http://konversation.kde.org/wiki/Developer_Central and the +KDE bug tracker (http://bugs.kde.org) for a list of outstanding +todo items and discussion of future development. diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..403f21c --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +konversation version 1.1 diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..c5a2f25 --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,12643 @@ +## -*- autoconf -*- + +dnl This file is part of the KDE libraries/packages +dnl Copyright (C) 1997 Janos Farkas (chexum@shadow.banki.hu) +dnl (C) 1997,98,99 Stephan Kulow (coolo@kde.org) + +dnl This file is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Library General Public +dnl License as published by the Free Software Foundation; either +dnl version 2 of the License, or (at your option) any later version. + +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Library General Public License for more details. + +dnl You should have received a copy of the GNU Library General Public License +dnl along with this library; see the file COPYING.LIB. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +dnl Boston, MA 02110-1301, USA. + +dnl IMPORTANT NOTE: +dnl Please do not modify this file unless you expect your modifications to be +dnl carried into every other module in the repository. +dnl +dnl Single-module modifications are best placed in configure.in for kdelibs +dnl and kdebase or configure.in.in if present. + +# KDE_PATH_X_DIRECT +dnl Internal subroutine of AC_PATH_X. +dnl Set ac_x_includes and/or ac_x_libraries. +AC_DEFUN([KDE_PATH_X_DIRECT], +[ +AC_REQUIRE([KDE_CHECK_LIB64]) + +if test "$ac_x_includes" = NO; then + # Guess where to find include files, by looking for this one X11 .h file. + test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h + + # First, try using that file with no special directory specified. +AC_TRY_CPP([#include <$x_direct_test_include>], +[# We can compile using X headers with no special include directory. +ac_x_includes=], +[# Look for the header file in a standard set of common directories. +# Check X11 before X11Rn because it is often a symlink to the current release. + for ac_dir in \ + /usr/X11/include \ + /usr/X11R6/include \ + /usr/X11R5/include \ + /usr/X11R4/include \ + \ + /usr/include/X11 \ + /usr/include/X11R6 \ + /usr/include/X11R5 \ + /usr/include/X11R4 \ + \ + /usr/local/X11/include \ + /usr/local/X11R6/include \ + /usr/local/X11R5/include \ + /usr/local/X11R4/include \ + \ + /usr/local/include/X11 \ + /usr/local/include/X11R6 \ + /usr/local/include/X11R5 \ + /usr/local/include/X11R4 \ + \ + /usr/X386/include \ + /usr/x386/include \ + /usr/XFree86/include/X11 \ + \ + /usr/include \ + /usr/local/include \ + /usr/unsupported/include \ + /usr/athena/include \ + /usr/local/x11r5/include \ + /usr/lpp/Xamples/include \ + \ + /usr/openwin/include \ + /usr/openwin/share/include \ + ; \ + do + if test -r "$ac_dir/$x_direct_test_include"; then + ac_x_includes=$ac_dir + break + fi + done]) +fi # $ac_x_includes = NO + +if test "$ac_x_libraries" = NO; then + # Check for the libraries. + + test -z "$x_direct_test_library" && x_direct_test_library=Xt + test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc + + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS="$LIBS" + LIBS="-l$x_direct_test_library $LIBS" +AC_TRY_LINK([#include ], [${x_direct_test_function}(1)], +[LIBS="$ac_save_LIBS" +# We can link X programs with no special library path. +ac_x_libraries=], +[LIBS="$ac_save_LIBS" +# First see if replacing the include by lib works. +# Check X11 before X11Rn because it is often a symlink to the current release. +for ac_dir in `echo "$ac_x_includes" | sed s/include/lib${kdelibsuff}/` \ + /usr/X11/lib${kdelibsuff} \ + /usr/X11R6/lib${kdelibsuff} \ + /usr/X11R5/lib${kdelibsuff} \ + /usr/X11R4/lib${kdelibsuff} \ + \ + /usr/lib${kdelibsuff}/X11 \ + /usr/lib${kdelibsuff}/X11R6 \ + /usr/lib${kdelibsuff}/X11R5 \ + /usr/lib${kdelibsuff}/X11R4 \ + \ + /usr/local/X11/lib${kdelibsuff} \ + /usr/local/X11R6/lib${kdelibsuff} \ + /usr/local/X11R5/lib${kdelibsuff} \ + /usr/local/X11R4/lib${kdelibsuff} \ + \ + /usr/local/lib${kdelibsuff}/X11 \ + /usr/local/lib${kdelibsuff}/X11R6 \ + /usr/local/lib${kdelibsuff}/X11R5 \ + /usr/local/lib${kdelibsuff}/X11R4 \ + \ + /usr/X386/lib${kdelibsuff} \ + /usr/x386/lib${kdelibsuff} \ + /usr/XFree86/lib${kdelibsuff}/X11 \ + \ + /usr/lib${kdelibsuff} \ + /usr/local/lib${kdelibsuff} \ + /usr/unsupported/lib${kdelibsuff} \ + /usr/athena/lib${kdelibsuff} \ + /usr/local/x11r5/lib${kdelibsuff} \ + /usr/lpp/Xamples/lib${kdelibsuff} \ + /lib/usr/lib${kdelibsuff}/X11 \ + \ + /usr/openwin/lib${kdelibsuff} \ + /usr/openwin/share/lib${kdelibsuff} \ + ; \ +do +dnl Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl; do + if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done]) +fi # $ac_x_libraries = NO +]) + + +dnl ------------------------------------------------------------------------ +dnl Find a file (or one of more files in a list of dirs) +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([AC_FIND_FILE], +[ +$3=NO +for i in $2; +do + for j in $1; + do + echo "configure: __oline__: $i/$j" >&AC_FD_CC + if test -r "$i/$j"; then + echo "taking that" >&AC_FD_CC + $3=$i + break 2 + fi + done +done +]) + +dnl KDE_FIND_PATH(program-name, variable-name, list-of-dirs, +dnl if-not-found, test-parameter, prepend-path) +dnl +dnl Look for program-name in list-of-dirs+$PATH. +dnl If prepend-path is set, look in $PATH+list-of-dirs instead. +dnl If found, $variable-name is set. If not, if-not-found is evaluated. +dnl test-parameter: if set, the program is executed with this arg, +dnl and only a successful exit code is required. +AC_DEFUN([KDE_FIND_PATH], +[ + AC_MSG_CHECKING([for $1]) + if test -n "$$2"; then + kde_cv_path="$$2"; + else + kde_cache=`echo $1 | sed 'y%./+-%__p_%'` + + AC_CACHE_VAL(kde_cv_path_$kde_cache, + [ + kde_cv_path="NONE" + kde_save_IFS=$IFS + IFS=':' + dirs="" + for dir in $PATH; do + dirs="$dirs $dir" + done + if test -z "$6"; then dnl Append dirs in PATH (default) + dirs="$3 $dirs" + else dnl Prepend dirs in PATH (if 6th arg is set) + dirs="$dirs $3" + fi + IFS=$kde_save_IFS + + for dir in $dirs; do + if test -x "$dir/$1"; then + if test -n "$5" + then + evalstr="$dir/$1 $5 2>&1 " + if eval $evalstr; then + kde_cv_path="$dir/$1" + break + fi + else + kde_cv_path="$dir/$1" + break + fi + fi + done + + eval "kde_cv_path_$kde_cache=$kde_cv_path" + + ]) + + eval "kde_cv_path=\"`echo '$kde_cv_path_'$kde_cache`\"" + + fi + + if test -z "$kde_cv_path" || test "$kde_cv_path" = NONE; then + AC_MSG_RESULT(not found) + $4 + else + AC_MSG_RESULT($kde_cv_path) + $2=$kde_cv_path + + fi +]) + +AC_DEFUN([KDE_MOC_ERROR_MESSAGE], +[ + AC_MSG_ERROR([No Qt meta object compiler (moc) found! +Please check whether you installed Qt correctly. +You need to have a running moc binary. +configure tried to run $ac_cv_path_moc and the test didn't +succeed. If configure shouldn't have tried this one, set +the environment variable MOC to the right one before running +configure. +]) +]) + +AC_DEFUN([KDE_UIC_ERROR_MESSAGE], +[ + AC_MSG_WARN([No Qt ui compiler (uic) found! +Please check whether you installed Qt correctly. +You need to have a running uic binary. +configure tried to run $ac_cv_path_uic and the test didn't +succeed. If configure shouldn't have tried this one, set +the environment variable UIC to the right one before running +configure. +]) +]) + + +AC_DEFUN([KDE_CHECK_UIC_FLAG], +[ + AC_MSG_CHECKING([whether uic supports -$1 ]) + kde_cache=`echo $1 | sed 'y% .=/+-%____p_%'` + AC_CACHE_VAL(kde_cv_prog_uic_$kde_cache, + [ + cat >conftest.ui < +EOT + ac_uic_testrun="$UIC_PATH -$1 $2 conftest.ui >/dev/null" + if AC_TRY_EVAL(ac_uic_testrun); then + eval "kde_cv_prog_uic_$kde_cache=yes" + else + eval "kde_cv_prog_uic_$kde_cache=no" + fi + rm -f conftest* + ]) + + if eval "test \"`echo '$kde_cv_prog_uic_'$kde_cache`\" = yes"; then + AC_MSG_RESULT([yes]) + : + $3 + else + AC_MSG_RESULT([no]) + : + $4 + fi +]) + + +dnl ------------------------------------------------------------------------ +dnl Find the meta object compiler and the ui compiler in the PATH, +dnl in $QTDIR/bin, and some more usual places +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([AC_PATH_QT_MOC_UIC], +[ + AC_REQUIRE([KDE_CHECK_PERL]) + qt_bindirs="" + for dir in $kde_qt_dirs; do + qt_bindirs="$qt_bindirs $dir/bin $dir/src/moc" + done + qt_bindirs="$qt_bindirs /usr/bin /usr/X11R6/bin /usr/local/qt/bin" + if test ! "$ac_qt_bindir" = "NO"; then + qt_bindirs="$ac_qt_bindir $qt_bindirs" + fi + + KDE_FIND_PATH(moc, MOC, [$qt_bindirs], [KDE_MOC_ERROR_MESSAGE]) + if test -z "$UIC_NOT_NEEDED"; then + KDE_FIND_PATH(uic, UIC_PATH, [$qt_bindirs], [UIC_PATH=""]) + if test -z "$UIC_PATH" ; then + KDE_UIC_ERROR_MESSAGE + exit 1 + else + UIC=$UIC_PATH + + if test $kde_qtver = 3; then + KDE_CHECK_UIC_FLAG(L,[/nonexistent],ac_uic_supports_libpath=yes,ac_uic_supports_libpath=no) + KDE_CHECK_UIC_FLAG(nounload,,ac_uic_supports_nounload=yes,ac_uic_supports_nounload=no) + + if test x$ac_uic_supports_libpath = xyes; then + UIC="$UIC -L \$(kde_widgetdir)" + fi + if test x$ac_uic_supports_nounload = xyes; then + UIC="$UIC -nounload" + fi + fi + fi + else + UIC="echo uic not available: " + fi + + AC_SUBST(MOC) + AC_SUBST(UIC) + + UIC_TR="i18n" + if test $kde_qtver = 3; then + UIC_TR="tr2i18n" + fi + + AC_SUBST(UIC_TR) +]) + +AC_DEFUN([KDE_1_CHECK_PATHS], +[ + KDE_1_CHECK_PATH_HEADERS + + KDE_TEST_RPATH= + + if test -n "$USE_RPATH"; then + + if test -n "$kde_libraries"; then + KDE_TEST_RPATH="-R $kde_libraries" + fi + + if test -n "$qt_libraries"; then + KDE_TEST_RPATH="$KDE_TEST_RPATH -R $qt_libraries" + fi + + if test -n "$x_libraries"; then + KDE_TEST_RPATH="$KDE_TEST_RPATH -R $x_libraries" + fi + + KDE_TEST_RPATH="$KDE_TEST_RPATH $KDE_EXTRA_RPATH" + fi + +AC_MSG_CHECKING([for KDE libraries installed]) +ac_link='$LIBTOOL_SHELL --silent --mode=link ${CXX-g++} -o conftest $CXXFLAGS $all_includes $CPPFLAGS $LDFLAGS $all_libraries conftest.$ac_ext $LIBS -lkdecore $LIBQT $KDE_TEST_RPATH 1>&5' + +if AC_TRY_EVAL(ac_link) && test -s conftest; then + AC_MSG_RESULT(yes) +else + AC_MSG_ERROR([your system fails at linking a small KDE application! +Check, if your compiler is installed correctly and if you have used the +same compiler to compile Qt and kdelibs as you did use now. +For more details about this problem, look at the end of config.log.]) +fi + +if eval `KDEDIR= ./conftest 2>&5`; then + kde_result=done +else + kde_result=problems +fi + +KDEDIR= ./conftest 2> /dev/null >&5 # make an echo for config.log +kde_have_all_paths=yes + +KDE_SET_PATHS($kde_result) + +]) + +AC_DEFUN([KDE_SET_PATHS], +[ + kde_cv_all_paths="kde_have_all_paths=\"yes\" \ + kde_htmldir=\"$kde_htmldir\" \ + kde_appsdir=\"$kde_appsdir\" \ + kde_icondir=\"$kde_icondir\" \ + kde_sounddir=\"$kde_sounddir\" \ + kde_datadir=\"$kde_datadir\" \ + kde_locale=\"$kde_locale\" \ + kde_cgidir=\"$kde_cgidir\" \ + kde_confdir=\"$kde_confdir\" \ + kde_kcfgdir=\"$kde_kcfgdir\" \ + kde_mimedir=\"$kde_mimedir\" \ + kde_toolbardir=\"$kde_toolbardir\" \ + kde_wallpaperdir=\"$kde_wallpaperdir\" \ + kde_templatesdir=\"$kde_templatesdir\" \ + kde_bindir=\"$kde_bindir\" \ + kde_servicesdir=\"$kde_servicesdir\" \ + kde_servicetypesdir=\"$kde_servicetypesdir\" \ + kde_moduledir=\"$kde_moduledir\" \ + kde_styledir=\"$kde_styledir\" \ + kde_widgetdir=\"$kde_widgetdir\" \ + xdg_appsdir=\"$xdg_appsdir\" \ + xdg_menudir=\"$xdg_menudir\" \ + xdg_directorydir=\"$xdg_directorydir\" \ + kde_result=$1" +]) + +AC_DEFUN([KDE_SET_DEFAULT_PATHS], +[ +if test "$1" = "default"; then + + if test -z "$kde_htmldir"; then + kde_htmldir='\${datadir}/doc/HTML' + fi + if test -z "$kde_appsdir"; then + kde_appsdir='\${datadir}/applnk' + fi + if test -z "$kde_icondir"; then + kde_icondir='\${datadir}/icons' + fi + if test -z "$kde_sounddir"; then + kde_sounddir='\${datadir}/sounds' + fi + if test -z "$kde_datadir"; then + kde_datadir='\${datadir}/apps' + fi + if test -z "$kde_locale"; then + kde_locale='\${datadir}/locale' + fi + if test -z "$kde_cgidir"; then + kde_cgidir='\${exec_prefix}/cgi-bin' + fi + if test -z "$kde_confdir"; then + kde_confdir='\${datadir}/config' + fi + if test -z "$kde_kcfgdir"; then + kde_kcfgdir='\${datadir}/config.kcfg' + fi + if test -z "$kde_mimedir"; then + kde_mimedir='\${datadir}/mimelnk' + fi + if test -z "$kde_toolbardir"; then + kde_toolbardir='\${datadir}/toolbar' + fi + if test -z "$kde_wallpaperdir"; then + kde_wallpaperdir='\${datadir}/wallpapers' + fi + if test -z "$kde_templatesdir"; then + kde_templatesdir='\${datadir}/templates' + fi + if test -z "$kde_bindir"; then + kde_bindir='\${exec_prefix}/bin' + fi + if test -z "$kde_servicesdir"; then + kde_servicesdir='\${datadir}/services' + fi + if test -z "$kde_servicetypesdir"; then + kde_servicetypesdir='\${datadir}/servicetypes' + fi + if test -z "$kde_moduledir"; then + if test "$kde_qtver" = "2"; then + kde_moduledir='\${libdir}/kde2' + else + kde_moduledir='\${libdir}/kde3' + fi + fi + if test -z "$kde_styledir"; then + kde_styledir='\${libdir}/kde3/plugins/styles' + fi + if test -z "$kde_widgetdir"; then + kde_widgetdir='\${libdir}/kde3/plugins/designer' + fi + if test -z "$xdg_appsdir"; then + xdg_appsdir='\${datadir}/applications/kde' + fi + if test -z "$xdg_menudir"; then + xdg_menudir='\${sysconfdir}/xdg/menus' + fi + if test -z "$xdg_directorydir"; then + xdg_directorydir='\${datadir}/desktop-directories' + fi + + KDE_SET_PATHS(defaults) + +else + + if test $kde_qtver = 1; then + AC_MSG_RESULT([compiling]) + KDE_1_CHECK_PATHS + else + AC_MSG_ERROR([path checking not yet supported for KDE 2]) + fi + +fi +]) + +AC_DEFUN([KDE_CHECK_PATHS_FOR_COMPLETENESS], +[ if test -z "$kde_htmldir" || test -z "$kde_appsdir" || + test -z "$kde_icondir" || test -z "$kde_sounddir" || + test -z "$kde_datadir" || test -z "$kde_locale" || + test -z "$kde_cgidir" || test -z "$kde_confdir" || + test -z "$kde_kcfgdir" || + test -z "$kde_mimedir" || test -z "$kde_toolbardir" || + test -z "$kde_wallpaperdir" || test -z "$kde_templatesdir" || + test -z "$kde_bindir" || test -z "$kde_servicesdir" || + test -z "$kde_servicetypesdir" || test -z "$kde_moduledir" || + test -z "$kde_styledir" || test -z "kde_widgetdir" || + test -z "$xdg_appsdir" || test -z "$xdg_menudir" || test -z "$xdg_directorydir" || + test "x$kde_have_all_paths" != "xyes"; then + kde_have_all_paths=no + fi +]) + +AC_DEFUN([KDE_MISSING_PROG_ERROR], +[ + AC_MSG_ERROR([The important program $1 was not found! +Please check whether you installed KDE correctly. +]) +]) + +AC_DEFUN([KDE_MISSING_ARTS_ERROR], +[ + AC_MSG_ERROR([The important program $1 was not found! +Please check whether you installed aRts correctly or use +--without-arts to compile without aRts support (this will remove functionality). +]) +]) + +AC_DEFUN([KDE_SET_DEFAULT_BINDIRS], +[ + kde_default_bindirs="/usr/bin /usr/local/bin /opt/local/bin /usr/X11R6/bin /opt/kde/bin /opt/kde3/bin /usr/kde/bin /usr/local/kde/bin" + test -n "$KDEDIR" && kde_default_bindirs="$KDEDIR/bin $kde_default_bindirs" + if test -n "$KDEDIRS"; then + kde_save_IFS=$IFS + IFS=: + for dir in $KDEDIRS; do + kde_default_bindirs="$dir/bin $kde_default_bindirs " + done + IFS=$kde_save_IFS + fi +]) + +AC_DEFUN([KDE_SUBST_PROGRAMS], +[ + AC_ARG_WITH(arts, + AC_HELP_STRING([--without-arts],[build without aRts [default=no]]), + [build_arts=$withval], + [build_arts=yes] + ) + AM_CONDITIONAL(include_ARTS, test "$build_arts" '!=' "no") + if test "$build_arts" = "no"; then + AC_DEFINE(WITHOUT_ARTS, 1, [Defined if compiling without arts]) + fi + + KDE_SET_DEFAULT_BINDIRS + kde_default_bindirs="$exec_prefix/bin $prefix/bin $kde_libs_prefix/bin $kde_default_bindirs" + KDE_FIND_PATH(dcopidl, DCOPIDL, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(dcopidl)]) + KDE_FIND_PATH(dcopidl2cpp, DCOPIDL2CPP, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(dcopidl2cpp)]) + if test "$build_arts" '!=' "no"; then + KDE_FIND_PATH(mcopidl, MCOPIDL, [$kde_default_bindirs], [KDE_MISSING_ARTS_ERROR(mcopidl)]) + KDE_FIND_PATH(artsc-config, ARTSCCONFIG, [$kde_default_bindirs], [KDE_MISSING_ARTS_ERROR(artsc-config)]) + fi + KDE_FIND_PATH(meinproc, MEINPROC, [$kde_default_bindirs]) + + kde32ornewer=1 + kde33ornewer=1 + if test -n "$kde_qtver" && test "$kde_qtver" -lt 3; then + kde32ornewer= + kde33ornewer= + else + if test "$kde_qtver" = "3"; then + if test "$kde_qtsubver" -le 1; then + kde32ornewer= + fi + if test "$kde_qtsubver" -le 2; then + kde33ornewer= + fi + if test "$KDECONFIG" != "compiled"; then + if test `$KDECONFIG --version | grep KDE | sed 's/KDE: \(...\).*/\1/'` = 3.2; then + kde33ornewer= + fi + fi + fi + fi + + if test -n "$kde32ornewer"; then + KDE_FIND_PATH(kconfig_compiler, KCONFIG_COMPILER, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(kconfig_compiler)]) + KDE_FIND_PATH(dcopidlng, DCOPIDLNG, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(dcopidlng)]) + fi + if test -n "$kde33ornewer"; then + KDE_FIND_PATH(makekdewidgets, MAKEKDEWIDGETS, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(makekdewidgets)]) + AC_SUBST(MAKEKDEWIDGETS) + fi + KDE_FIND_PATH(xmllint, XMLLINT, [${prefix}/bin ${exec_prefix}/bin], [XMLLINT=""]) + + if test -n "$MEINPROC" -a "$MEINPROC" != "compiled"; then + kde_sharedirs="/usr/share/kde /usr/local/share /usr/share /opt/kde3/share /opt/kde/share $prefix/share" + test -n "$KDEDIR" && kde_sharedirs="$KDEDIR/share $kde_sharedirs" + AC_FIND_FILE(apps/ksgmltools2/customization/kde-chunk.xsl, $kde_sharedirs, KDE_XSL_STYLESHEET) + if test "$KDE_XSL_STYLESHEET" = "NO"; then + KDE_XSL_STYLESHEET="" + else + KDE_XSL_STYLESHEET="$KDE_XSL_STYLESHEET/apps/ksgmltools2/customization/kde-chunk.xsl" + fi + fi + + DCOP_DEPENDENCIES='$(DCOPIDL)' + if test -n "$kde32ornewer"; then + KCFG_DEPENDENCIES='$(KCONFIG_COMPILER)' + DCOP_DEPENDENCIES='$(DCOPIDL) $(DCOPIDLNG)' + AC_SUBST(KCONFIG_COMPILER) + AC_SUBST(KCFG_DEPENDENCIES) + AC_SUBST(DCOPIDLNG) + fi + AC_SUBST(DCOPIDL) + AC_SUBST(DCOPIDL2CPP) + AC_SUBST(DCOP_DEPENDENCIES) + AC_SUBST(MCOPIDL) + AC_SUBST(ARTSCCONFIG) + AC_SUBST(MEINPROC) + AC_SUBST(KDE_XSL_STYLESHEET) + AC_SUBST(XMLLINT) +])dnl + +AC_DEFUN([AC_CREATE_KFSSTND], +[ +AC_REQUIRE([AC_CHECK_RPATH]) + +AC_MSG_CHECKING([for KDE paths]) +kde_result="" +kde_cached_paths=yes +AC_CACHE_VAL(kde_cv_all_paths, +[ + KDE_SET_DEFAULT_PATHS($1) + kde_cached_paths=no +]) +eval "$kde_cv_all_paths" +KDE_CHECK_PATHS_FOR_COMPLETENESS +if test "$kde_have_all_paths" = "no" && test "$kde_cached_paths" = "yes"; then + # wrong values were cached, may be, we can set better ones + kde_result= + kde_htmldir= kde_appsdir= kde_icondir= kde_sounddir= + kde_datadir= kde_locale= kde_cgidir= kde_confdir= kde_kcfgdir= + kde_mimedir= kde_toolbardir= kde_wallpaperdir= kde_templatesdir= + kde_bindir= kde_servicesdir= kde_servicetypesdir= kde_moduledir= + kde_have_all_paths= + kde_styledir= + kde_widgetdir= + xdg_appsdir = xdg_menudir= xdg_directorydir= + KDE_SET_DEFAULT_PATHS($1) + eval "$kde_cv_all_paths" + KDE_CHECK_PATHS_FOR_COMPLETENESS + kde_result="$kde_result (cache overridden)" +fi +if test "$kde_have_all_paths" = "no"; then + AC_MSG_ERROR([configure could not run a little KDE program to test the environment. +Since it had compiled and linked before, it must be a strange problem on your system. +Look at config.log for details. If you are not able to fix this, look at +http://www.kde.org/faq/installation.html or any www.kde.org mirror. +(If you're using an egcs version on Linux, you may update binutils!) +]) +else + rm -f conftest* + AC_MSG_RESULT($kde_result) +fi + +bindir=$kde_bindir + +KDE_SUBST_PROGRAMS + +]) + +AC_DEFUN([AC_SUBST_KFSSTND], +[ +AC_SUBST(kde_htmldir) +AC_SUBST(kde_appsdir) +AC_SUBST(kde_icondir) +AC_SUBST(kde_sounddir) +AC_SUBST(kde_datadir) +AC_SUBST(kde_locale) +AC_SUBST(kde_confdir) +AC_SUBST(kde_kcfgdir) +AC_SUBST(kde_mimedir) +AC_SUBST(kde_wallpaperdir) +AC_SUBST(kde_bindir) +dnl X Desktop Group standards +AC_SUBST(xdg_appsdir) +AC_SUBST(xdg_menudir) +AC_SUBST(xdg_directorydir) +dnl for KDE 2 +AC_SUBST(kde_templatesdir) +AC_SUBST(kde_servicesdir) +AC_SUBST(kde_servicetypesdir) +AC_SUBST(kde_moduledir) +AC_SUBST(kdeinitdir, '$(kde_moduledir)') +AC_SUBST(kde_styledir) +AC_SUBST(kde_widgetdir) +if test "$kde_qtver" = 1; then + kde_minidir="$kde_icondir/mini" +else +# for KDE 1 - this breaks KDE2 apps using minidir, but +# that's the plan ;-/ + kde_minidir="/dev/null" +fi +dnl AC_SUBST(kde_minidir) +dnl AC_SUBST(kde_cgidir) +dnl AC_SUBST(kde_toolbardir) +]) + +AC_DEFUN([KDE_MISC_TESTS], +[ + dnl Checks for libraries. + AC_CHECK_LIB(util, main, [LIBUTIL="-lutil"]) dnl for *BSD + AC_SUBST(LIBUTIL) + AC_CHECK_LIB(compat, main, [LIBCOMPAT="-lcompat"]) dnl for *BSD + AC_SUBST(LIBCOMPAT) + kde_have_crypt= + AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"; kde_have_crypt=yes], + AC_CHECK_LIB(c, crypt, [kde_have_crypt=yes], [ + AC_MSG_WARN([you have no crypt in either libcrypt or libc. +You should install libcrypt from another source or configure with PAM +support]) + kde_have_crypt=no + ])) + AC_SUBST(LIBCRYPT) + if test $kde_have_crypt = yes; then + AC_DEFINE_UNQUOTED(HAVE_CRYPT, 1, [Defines if your system has the crypt function]) + fi + AC_CHECK_SOCKLEN_T + AC_CHECK_LIB(dnet, dnet_ntoa, [X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"]) + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + AC_CHECK_LIB(dnet_stub, dnet_ntoa, + [X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"]) + fi + AC_CHECK_FUNC(inet_ntoa) + if test $ac_cv_func_inet_ntoa = no; then + AC_CHECK_LIB(nsl, inet_ntoa, X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl") + fi + AC_CHECK_FUNC(connect) + if test $ac_cv_func_connect = no; then + AC_CHECK_LIB(socket, connect, X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS", , + $X_EXTRA_LIBS) + fi + + AC_CHECK_FUNC(remove) + if test $ac_cv_func_remove = no; then + AC_CHECK_LIB(posix, remove, X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix") + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + AC_CHECK_FUNC(shmat, , + AC_CHECK_LIB(ipc, shmat, X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc")) + + # more headers that need to be explicitly included on darwin + AC_CHECK_HEADERS(sys/types.h stdint.h) + + # sys/bitypes.h is needed for uint32_t and friends on Tru64 + AC_CHECK_HEADERS(sys/bitypes.h) + + # darwin requires a poll emulation library + AC_CHECK_LIB(poll, poll, LIB_POLL="-lpoll") + + # for some image handling on Mac OS X + AC_CHECK_HEADERS(Carbon/Carbon.h) + + # CoreAudio framework + AC_CHECK_HEADER(CoreAudio/CoreAudio.h, [ + AC_DEFINE(HAVE_COREAUDIO, 1, [Define if you have the CoreAudio API]) + FRAMEWORK_COREAUDIO="-Wl,-framework,CoreAudio" + ]) + + AC_CHECK_RES_INIT + AC_SUBST(LIB_POLL) + AC_SUBST(FRAMEWORK_COREAUDIO) + LIBSOCKET="$X_EXTRA_LIBS" + AC_SUBST(LIBSOCKET) + AC_SUBST(X_EXTRA_LIBS) + AC_CHECK_LIB(ucb, killpg, [LIBUCB="-lucb"]) dnl for Solaris2.4 + AC_SUBST(LIBUCB) + + case $host in dnl this *is* LynxOS specific + *-*-lynxos* ) + AC_MSG_CHECKING([LynxOS header file wrappers]) + [CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__"] + AC_MSG_RESULT(disabled) + AC_CHECK_LIB(bsd, gethostbyname, [LIBSOCKET="-lbsd"]) dnl for LynxOS + ;; + esac + + KDE_CHECK_TYPES + KDE_CHECK_LIBDL + KDE_CHECK_STRLCPY + KDE_CHECK_PIE_SUPPORT + +# darwin needs this to initialize the environment +AC_CHECK_HEADERS(crt_externs.h) +AC_CHECK_FUNC(_NSGetEnviron, [AC_DEFINE(HAVE_NSGETENVIRON, 1, [Define if your system needs _NSGetEnviron to set up the environment])]) + +AH_VERBATIM(_DARWIN_ENVIRON, +[ +#if defined(HAVE_NSGETENVIRON) && defined(HAVE_CRT_EXTERNS_H) +# include +# include +# define environ (*_NSGetEnviron()) +#endif +]) + +AH_VERBATIM(_AIX_STRINGS_H_BZERO, +[ +/* + * AIX defines FD_SET in terms of bzero, but fails to include + * that defines bzero. + */ + +#if defined(_AIX) +#include +#endif +]) + +AC_CHECK_FUNCS([vsnprintf snprintf]) + +AH_VERBATIM(_TRU64,[ +/* + * On HP-UX, the declaration of vsnprintf() is needed every time ! + */ + +#if !defined(HAVE_VSNPRINTF) || defined(hpux) +#if __STDC__ +#include +#include +#else +#include +#endif +#ifdef __cplusplus +extern "C" +#endif +int vsnprintf(char *str, size_t n, char const *fmt, va_list ap); +#ifdef __cplusplus +extern "C" +#endif +int snprintf(char *str, size_t n, char const *fmt, ...); +#endif +]) + +]) + +dnl ------------------------------------------------------------------------ +dnl Find the header files and libraries for X-Windows. Extended the +dnl macro AC_PATH_X +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([K_PATH_X], +[ +AC_REQUIRE([KDE_MISC_TESTS])dnl +AC_REQUIRE([KDE_CHECK_LIB64]) + +AC_ARG_ENABLE( + embedded, + AC_HELP_STRING([--enable-embedded],[link to Qt-embedded, don't use X]), + kde_use_qt_emb=$enableval, + kde_use_qt_emb=no +) + +AC_ARG_ENABLE( + qtopia, + AC_HELP_STRING([--enable-qtopia],[link to Qt-embedded, link to the Qtopia Environment]), + kde_use_qt_emb_palm=$enableval, + kde_use_qt_emb_palm=no +) + +AC_ARG_ENABLE( + mac, + AC_HELP_STRING([--enable-mac],[link to Qt/Mac (don't use X)]), + kde_use_qt_mac=$enableval, + kde_use_qt_mac=no +) + +# used to disable x11-specific stuff on special platforms +AM_CONDITIONAL(include_x11, test "$kde_use_qt_emb" = "no" && test "$kde_use_qt_mac" = "no") + +if test "$kde_use_qt_emb" = "no" && test "$kde_use_qt_mac" = "no"; then + +AC_MSG_CHECKING(for X) + +AC_CACHE_VAL(kde_cv_have_x, +[# One or both of the vars are not set, and there is no cached value. +if test "{$x_includes+set}" = set || test "$x_includes" = NONE; then + kde_x_includes=NO +else + kde_x_includes=$x_includes +fi +if test "{$x_libraries+set}" = set || test "$x_libraries" = NONE; then + kde_x_libraries=NO +else + kde_x_libraries=$x_libraries +fi + +# below we use the standard autoconf calls +ac_x_libraries=$kde_x_libraries +ac_x_includes=$kde_x_includes + +KDE_PATH_X_DIRECT +dnl AC_PATH_X_XMKMF picks /usr/lib as the path for the X libraries. +dnl Unfortunately, if compiling with the N32 ABI, this is not the correct +dnl location. The correct location is /usr/lib32 or an undefined value +dnl (the linker is smart enough to pick the correct default library). +dnl Things work just fine if you use just AC_PATH_X_DIRECT. +dnl Solaris has a similar problem. AC_PATH_X_XMKMF forces x_includes to +dnl /usr/openwin/include, which doesn't work. /usr/include does work, so +dnl x_includes should be left alone. +case "$host" in +mips-sgi-irix6*) + ;; +*-*-solaris*) + ;; +*) + _AC_PATH_X_XMKMF + if test -z "$ac_x_includes"; then + ac_x_includes="." + fi + if test -z "$ac_x_libraries"; then + ac_x_libraries="/usr/lib${kdelibsuff}" + fi +esac +#from now on we use our own again + +# when the user already gave --x-includes, we ignore +# what the standard autoconf macros told us. +if test "$kde_x_includes" = NO; then + kde_x_includes=$ac_x_includes +fi + +# for --x-libraries too +if test "$kde_x_libraries" = NO; then + kde_x_libraries=$ac_x_libraries +fi + +if test "$kde_x_includes" = NO; then + AC_MSG_ERROR([Can't find X includes. Please check your installation and add the correct paths!]) +fi + +if test "$kde_x_libraries" = NO; then + AC_MSG_ERROR([Can't find X libraries. Please check your installation and add the correct paths!]) +fi + +# Record where we found X for the cache. +kde_cv_have_x="have_x=yes \ + kde_x_includes=$kde_x_includes kde_x_libraries=$kde_x_libraries" +])dnl + +eval "$kde_cv_have_x" + +if test "$have_x" != yes; then + AC_MSG_RESULT($have_x) + no_x=yes +else + AC_MSG_RESULT([libraries $kde_x_libraries, headers $kde_x_includes]) +fi + +if test -z "$kde_x_includes" || test "x$kde_x_includes" = xNONE; then + X_INCLUDES="" + x_includes="."; dnl better than nothing :- + else + x_includes=$kde_x_includes + X_INCLUDES="-I$x_includes" +fi + +if test -z "$kde_x_libraries" || test "x$kde_x_libraries" = xNONE || test "$kde_x_libraries" = "/usr/lib"; then + X_LDFLAGS="" + x_libraries="/usr/lib"; dnl better than nothing :- + else + x_libraries=$kde_x_libraries + X_LDFLAGS="-L$x_libraries" +fi +all_includes="$X_INCLUDES" +all_libraries="$X_LDFLAGS $LDFLAGS_AS_NEEDED $LDFLAGS_NEW_DTAGS" + +# Check for libraries that X11R6 Xt/Xaw programs need. +ac_save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS $X_LDFLAGS" +# SM needs ICE to (dynamically) link under SunOS 4.x (so we have to +# check for ICE first), but we must link in the order -lSM -lICE or +# we get undefined symbols. So assume we have SM if we have ICE. +# These have to be linked with before -lX11, unlike the other +# libraries we check for below, so use a different variable. +# --interran@uluru.Stanford.EDU, kb@cs.umb.edu. +AC_CHECK_LIB(ICE, IceConnectionNumber, + [LIBSM="-lSM -lICE"], , $X_EXTRA_LIBS) +LDFLAGS="$ac_save_LDFLAGS" + +LIB_X11='-lX11 $(LIBSOCKET)' + +AC_MSG_CHECKING(for libXext) +AC_CACHE_VAL(kde_cv_have_libXext, +[ +kde_ldflags_safe="$LDFLAGS" +kde_libs_safe="$LIBS" + +LDFLAGS="$LDFLAGS $X_LDFLAGS $USER_LDFLAGS" +LIBS="-lXext -lX11 $LIBSOCKET" + +AC_TRY_LINK([ +#include +#ifdef STDC_HEADERS +# include +#endif +], +[ +printf("hello Xext\n"); +], +kde_cv_have_libXext=yes, +kde_cv_have_libXext=no +) + +LDFLAGS=$kde_ldflags_safe +LIBS=$kde_libs_safe +]) + +AC_MSG_RESULT($kde_cv_have_libXext) + +if test "$kde_cv_have_libXext" = "no"; then + AC_MSG_ERROR([We need a working libXext to proceed. Since configure +can't find it itself, we stop here assuming that make wouldn't find +them either.]) +fi + +LIB_XEXT="-lXext" +QTE_NORTTI="" + +elif test "$kde_use_qt_emb" = "yes"; then + dnl We're using QT Embedded + CPPFLAGS=-DQWS + CXXFLAGS="$CXXFLAGS -fno-rtti" + QTE_NORTTI="-fno-rtti -DQWS" + X_PRE_LIBS="" + LIB_X11="" + LIB_XEXT="" + LIB_XRENDER="" + LIBSM="" + X_INCLUDES="" + X_LDFLAGS="" + x_includes="" + x_libraries="" +elif test "$kde_use_qt_mac" = "yes"; then + dnl We're using QT/Mac (I use QT_MAC so that qglobal.h doesn't *have* to + dnl be included to get the information) --Sam + CXXFLAGS="$CXXFLAGS -DQT_MAC -no-cpp-precomp" + CFLAGS="$CFLAGS -DQT_MAC -no-cpp-precomp" + X_PRE_LIBS="" + LIB_X11="" + LIB_XEXT="" + LIB_XRENDER="" + LIBSM="" + X_INCLUDES="" + X_LDFLAGS="" + x_includes="" + x_libraries="" +fi +AC_SUBST(X_PRE_LIBS) +AC_SUBST(LIB_X11) +AC_SUBST(LIB_XRENDER) +AC_SUBST(LIBSM) +AC_SUBST(X_INCLUDES) +AC_SUBST(X_LDFLAGS) +AC_SUBST(x_includes) +AC_SUBST(x_libraries) +AC_SUBST(QTE_NORTTI) +AC_SUBST(LIB_XEXT) + +]) + +AC_DEFUN([KDE_PRINT_QT_PROGRAM], +[ +AC_REQUIRE([KDE_USE_QT]) +cat > conftest.$ac_ext < +#include +EOF +if test "$kde_qtver" = "2"; then +cat >> conftest.$ac_ext < +#include +#include +EOF + +if test $kde_qtsubver -gt 0; then +cat >> conftest.$ac_ext <> conftest.$ac_ext < +#include +#include +EOF +fi + +echo "#if ! ($kde_qt_verstring)" >> conftest.$ac_ext +cat >> conftest.$ac_ext <> conftest.$ac_ext <> conftest.$ac_ext <> conftest.$ac_ext <> conftest.$ac_ext <&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +fi + +rm -f conftest* +CXXFLAGS="$ac_cxxflags_safe" +LDFLAGS="$ac_ldflags_safe" +LIBS="$ac_libs_safe" + +LD_LIBRARY_PATH="$ac_LD_LIBRARY_PATH_safe" +export LD_LIBRARY_PATH +LIBRARY_PATH="$ac_LIBRARY_PATH" +export LIBRARY_PATH +AC_LANG_RESTORE +]) + +if test "$kde_cv_qt_direct" = "yes"; then + AC_MSG_RESULT(yes) + $1 +else + AC_MSG_RESULT(no) + $2 +fi +]) + +dnl ------------------------------------------------------------------------ +dnl Try to find the Qt headers and libraries. +dnl $(QT_LDFLAGS) will be -Lqtliblocation (if needed) +dnl and $(QT_INCLUDES) will be -Iqthdrlocation (if needed) +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([AC_PATH_QT_1_3], +[ +AC_REQUIRE([K_PATH_X]) +AC_REQUIRE([KDE_USE_QT]) +AC_REQUIRE([KDE_CHECK_LIB64]) + +dnl ------------------------------------------------------------------------ +dnl Add configure flag to enable linking to MT version of Qt library. +dnl ------------------------------------------------------------------------ + +AC_ARG_ENABLE( + mt, + AC_HELP_STRING([--disable-mt],[link to non-threaded Qt (deprecated)]), + kde_use_qt_mt=$enableval, + [ + if test $kde_qtver = 3; then + kde_use_qt_mt=yes + else + kde_use_qt_mt=no + fi + ] +) + +USING_QT_MT="" + +dnl ------------------------------------------------------------------------ +dnl If we not get --disable-qt-mt then adjust some vars for the host. +dnl ------------------------------------------------------------------------ + +KDE_MT_LDFLAGS= +KDE_MT_LIBS= +if test "x$kde_use_qt_mt" = "xyes"; then + KDE_CHECK_THREADING + if test "x$kde_use_threading" = "xyes"; then + CPPFLAGS="$USE_THREADS -DQT_THREAD_SUPPORT $CPPFLAGS" + KDE_MT_LDFLAGS="$USE_THREADS" + KDE_MT_LIBS="$LIBPTHREAD" + else + kde_use_qt_mt=no + fi +fi +AC_SUBST(KDE_MT_LDFLAGS) +AC_SUBST(KDE_MT_LIBS) + +kde_qt_was_given=yes + +dnl ------------------------------------------------------------------------ +dnl If we haven't been told how to link to Qt, we work it out for ourselves. +dnl ------------------------------------------------------------------------ +if test -z "$LIBQT_GLOB"; then + if test "x$kde_use_qt_emb" = "xyes"; then + LIBQT_GLOB="libqte.*" + else + LIBQT_GLOB="libqt.*" + fi +fi + +dnl ------------------------------------------------------------ +dnl If we got --enable-embedded then adjust the Qt library name. +dnl ------------------------------------------------------------ +if test "x$kde_use_qt_emb" = "xyes"; then + qtlib="qte" +else + qtlib="qt" +fi + +kde_int_qt="-l$qtlib" + +if test -z "$LIBQPE"; then +dnl ------------------------------------------------------------ +dnl If we got --enable-palmtop then add -lqpe to the link line +dnl ------------------------------------------------------------ + if test "x$kde_use_qt_emb" = "xyes"; then + if test "x$kde_use_qt_emb_palm" = "xyes"; then + LIB_QPE="-lqpe" + else + LIB_QPE="" + fi + else + LIB_QPE="" + fi +fi + +dnl ------------------------------------------------------------------------ +dnl If we got --enable-qt-mt then adjust the Qt library name for the host. +dnl ------------------------------------------------------------------------ + +if test "x$kde_use_qt_mt" = "xyes"; then + LIBQT="-l$qtlib-mt" + kde_int_qt="-l$qtlib-mt" + LIBQT_GLOB="lib$qtlib-mt.*" + USING_QT_MT="using -mt" +else + LIBQT="-l$qtlib" +fi + +if test $kde_qtver != 1; then + + AC_REQUIRE([AC_FIND_PNG]) + AC_REQUIRE([AC_FIND_JPEG]) + LIBQT="$LIBQT $LIBPNG $LIBJPEG" +fi + +if test $kde_qtver = 3; then + AC_REQUIRE([KDE_CHECK_LIBDL]) + LIBQT="$LIBQT $LIBDL" +fi + +AC_MSG_CHECKING([for Qt]) + +if test "x$kde_use_qt_emb" != "xyes" && test "x$kde_use_qt_mac" != "xyes"; then +LIBQT="$LIBQT $X_PRE_LIBS -lXext -lX11 $LIBSM $LIBSOCKET" +fi +ac_qt_includes=NO ac_qt_libraries=NO ac_qt_bindir=NO +qt_libraries="" +qt_includes="" +AC_ARG_WITH(qt-dir, + AC_HELP_STRING([--with-qt-dir=DIR],[where the root of Qt is installed ]), + [ ac_qt_includes="$withval"/include + ac_qt_libraries="$withval"/lib${kdelibsuff} + ac_qt_bindir="$withval"/bin + ]) + +AC_ARG_WITH(qt-includes, + AC_HELP_STRING([--with-qt-includes=DIR],[where the Qt includes are. ]), + [ + ac_qt_includes="$withval" + ]) + +kde_qt_libs_given=no + +AC_ARG_WITH(qt-libraries, + AC_HELP_STRING([--with-qt-libraries=DIR],[where the Qt library is installed.]), + [ ac_qt_libraries="$withval" + kde_qt_libs_given=yes + ]) + +AC_CACHE_VAL(ac_cv_have_qt, +[#try to guess Qt locations + +qt_incdirs="" +for dir in $kde_qt_dirs; do + qt_incdirs="$qt_incdirs $dir/include $dir" +done +if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) +fi +if test "$PKG_CONFIG" != "no" ; then + if $PKG_CONFIG --exists qt-mt ; then + qt_incdirs="$qt_incdirs `$PKG_CONFIG --variable=includedir qt-mt`" + fi +fi +qt_incdirs="$QTINC $qt_incdirs /usr/local/qt/include /usr/include/qt /usr/include /usr/X11R6/include/X11/qt /usr/X11R6/include/qt /usr/X11R6/include/qt2 /usr/include/qt3 $x_includes" +if test ! "$ac_qt_includes" = "NO"; then + qt_incdirs="$ac_qt_includes $qt_incdirs" +fi + +if test "$kde_qtver" != "1"; then + kde_qt_header=qstyle.h +else + kde_qt_header=qglobal.h +fi + +AC_FIND_FILE($kde_qt_header, $qt_incdirs, qt_incdir) +ac_qt_includes="$qt_incdir" + +qt_libdirs="" +for dir in $kde_qt_dirs; do + qt_libdirs="$qt_libdirs $dir/lib${kdelibsuff} $dir/lib $dir" +done +if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) +fi +if test "$PKG_CONFIG" != "no" ; then + if $PKG_CONFIG --exists qt-mt ; then + qt_libdirs="$qt_incdirs `$PKG_CONFIG --variable=libdir qt-mt`" + fi +fi +qt_libdirs="$QTLIB $qt_libdirs /usr/X11R6/lib /usr/lib /usr/local/qt/lib $x_libraries" +if test ! "$ac_qt_libraries" = "NO"; then + qt_libdir=$ac_qt_libraries +else + qt_libdirs="$ac_qt_libraries $qt_libdirs" + # if the Qt was given, the chance is too big that libqt.* doesn't exist + qt_libdir=NONE + for dir in $qt_libdirs; do + try="ls -1 $dir/${LIBQT_GLOB}" + if test -n "`$try 2> /dev/null`"; then qt_libdir=$dir; break; else echo "tried $dir" >&AC_FD_CC ; fi + done +fi +for a in $qt_libdir/lib`echo ${kde_int_qt} | sed 's,^-l,,'`_incremental.*; do + if test -e "$a"; then + LIBQT="$LIBQT ${kde_int_qt}_incremental" + break + fi +done + +ac_qt_libraries="$qt_libdir" + +AC_LANG_SAVE +AC_LANG_CPLUSPLUS + +ac_cxxflags_safe="$CXXFLAGS" +ac_ldflags_safe="$LDFLAGS" +ac_libs_safe="$LIBS" + +CXXFLAGS="$CXXFLAGS -I$qt_incdir $all_includes" +LDFLAGS="$LDFLAGS -L$qt_libdir $all_libraries $USER_LDFLAGS $KDE_MT_LDFLAGS" +LIBS="$LIBS $LIBQT $KDE_MT_LIBS" + +KDE_PRINT_QT_PROGRAM + +if AC_TRY_EVAL(ac_link) && test -s conftest; then + rm -f conftest* +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC + ac_qt_libraries="NO" +fi +rm -f conftest* +CXXFLAGS="$ac_cxxflags_safe" +LDFLAGS="$ac_ldflags_safe" +LIBS="$ac_libs_safe" + +AC_LANG_RESTORE +if test "$ac_qt_includes" = NO || test "$ac_qt_libraries" = NO; then + ac_cv_have_qt="have_qt=no" + ac_qt_notfound="" + missing_qt_mt="" + if test "$ac_qt_includes" = NO; then + if test "$ac_qt_libraries" = NO; then + ac_qt_notfound="(headers and libraries)"; + else + ac_qt_notfound="(headers)"; + fi + else + if test "x$kde_use_qt_mt" = "xyes"; then + missing_qt_mt=" +Make sure that you have compiled Qt with thread support!" + ac_qt_notfound="(library $qtlib-mt)"; + else + ac_qt_notfound="(library $qtlib)"; + fi + fi + + AC_MSG_ERROR([Qt ($kde_qt_minversion) $ac_qt_notfound not found. Please check your installation! +For more details about this problem, look at the end of config.log.$missing_qt_mt]) +else + have_qt="yes" +fi +]) + +eval "$ac_cv_have_qt" + +if test "$have_qt" != yes; then + AC_MSG_RESULT([$have_qt]); +else + ac_cv_have_qt="have_qt=yes \ + ac_qt_includes=$ac_qt_includes ac_qt_libraries=$ac_qt_libraries" + AC_MSG_RESULT([libraries $ac_qt_libraries, headers $ac_qt_includes $USING_QT_MT]) + + qt_libraries="$ac_qt_libraries" + qt_includes="$ac_qt_includes" +fi + +if test ! "$kde_qt_libs_given" = "yes" && test ! "$kde_qtver" = 3; then + KDE_CHECK_QT_DIRECT(qt_libraries= ,[]) +fi + +AC_SUBST(qt_libraries) +AC_SUBST(qt_includes) + +if test "$qt_includes" = "$x_includes" || test -z "$qt_includes"; then + QT_INCLUDES="" +else + QT_INCLUDES="-I$qt_includes" + all_includes="$QT_INCLUDES $all_includes" +fi + +if test "$qt_libraries" = "$x_libraries" || test -z "$qt_libraries"; then + QT_LDFLAGS="" +else + QT_LDFLAGS="-L$qt_libraries" + all_libraries="$QT_LDFLAGS $all_libraries" +fi +test -z "$KDE_MT_LDFLAGS" || all_libraries="$all_libraries $KDE_MT_LDFLAGS" + +AC_SUBST(QT_INCLUDES) +AC_SUBST(QT_LDFLAGS) +AC_PATH_QT_MOC_UIC + +KDE_CHECK_QT_JPEG + +if test "x$kde_use_qt_emb" != "xyes" && test "x$kde_use_qt_mac" != "xyes"; then +LIB_QT="$kde_int_qt $LIBJPEG_QT "'$(LIBZ) $(LIBPNG) -lXext $(LIB_X11) $(LIBSM)' +else +LIB_QT="$kde_int_qt $LIBJPEG_QT "'$(LIBZ) $(LIBPNG)' +fi +test -z "$KDE_MT_LIBS" || LIB_QT="$LIB_QT $KDE_MT_LIBS" +for a in $qt_libdir/lib`echo ${kde_int_qt} | sed 's,^-l,,'`_incremental.*; do + if test -e "$a"; then + LIB_QT="$LIB_QT ${kde_int_qt}_incremental" + break + fi +done + +AC_SUBST(LIB_QT) +AC_SUBST(LIB_QPE) + +AC_SUBST(kde_qtver) +]) + +AC_DEFUN([AC_PATH_QT], +[ +AC_PATH_QT_1_3 +]) + +AC_DEFUN([KDE_CHECK_UIC_PLUGINS], +[ +AC_REQUIRE([AC_PATH_QT_MOC_UIC]) + +if test x$ac_uic_supports_libpath = xyes; then + +AC_MSG_CHECKING([if UIC has KDE plugins available]) +AC_CACHE_VAL(kde_cv_uic_plugins, +[ +cat > actest.ui << EOF + +NewConnectionDialog + + + + testInput + + + + +EOF + + + +kde_cv_uic_plugins=no +kde_line="$UIC_PATH -L $kde_widgetdir" +if test x$ac_uic_supports_nounload = xyes; then + kde_line="$kde_line -nounload" +fi +kde_line="$kde_line -impl actest.h actest.ui > actest.cpp" +if AC_TRY_EVAL(kde_line); then + # if you're trying to debug this check and think it's incorrect, + # better check your installation. The check _is_ correct - your + # installation is not. + if test -f actest.cpp && grep klineedit actest.cpp > /dev/null; then + kde_cv_uic_plugins=yes + fi +fi +rm -f actest.ui actest.cpp +]) + +AC_MSG_RESULT([$kde_cv_uic_plugins]) +if test "$kde_cv_uic_plugins" != yes; then + AC_MSG_ERROR([ +you need to install kdelibs first. + +If you did install kdelibs, then the Qt version that is picked up by +this configure is not the same version you used to compile kdelibs. +The Qt Plugin installed by kdelibs is *ONLY* loadable if it is the +_same Qt version_, compiled with the _same compiler_ and the same Qt +configuration settings. +]) +fi +fi +]) + +AC_DEFUN([KDE_CHECK_FINAL], +[ + AC_ARG_ENABLE(final, + AC_HELP_STRING([--enable-final], + [build size optimized apps (experimental - needs lots of memory)]), + kde_use_final=$enableval, kde_use_final=no) + + if test "x$kde_use_final" = "xyes"; then + KDE_USE_FINAL_TRUE="" + KDE_USE_FINAL_FALSE="#" + else + KDE_USE_FINAL_TRUE="#" + KDE_USE_FINAL_FALSE="" + fi + AC_SUBST(KDE_USE_FINAL_TRUE) + AC_SUBST(KDE_USE_FINAL_FALSE) +]) + +AC_DEFUN([KDE_CHECK_CLOSURE], +[ + AC_ARG_ENABLE(closure, + AC_HELP_STRING([--enable-closure],[delay template instantiation]), + kde_use_closure=$enableval, kde_use_closure=no) + + KDE_NO_UNDEFINED="" + if test "x$kde_use_closure" = "xyes"; then + KDE_USE_CLOSURE_TRUE="" + KDE_USE_CLOSURE_FALSE="#" +# CXXFLAGS="$CXXFLAGS $REPO" + else + KDE_USE_CLOSURE_TRUE="#" + KDE_USE_CLOSURE_FALSE="" + KDE_NO_UNDEFINED="" + fi + AC_SUBST(KDE_USE_CLOSURE_TRUE) + AC_SUBST(KDE_USE_CLOSURE_FALSE) + AC_SUBST(KDE_NO_UNDEFINED) +]) + +dnl Check if the linker supports --enable-new-dtags and --as-needed +AC_DEFUN([KDE_CHECK_NEW_LDFLAGS], +[ + AC_ARG_ENABLE(new_ldflags, + AC_HELP_STRING([--enable-new-ldflags], + [enable the new linker flags]), + kde_use_new_ldflags=$enableval, + kde_use_new_ldflags=no) + + LDFLAGS_AS_NEEDED="" + LDFLAGS_NEW_DTAGS="" + if test "x$kde_use_new_ldflags" = "xyes"; then + LDFLAGS_NEW_DTAGS="" + KDE_CHECK_COMPILER_FLAG([Wl,--enable-new-dtags], + [LDFLAGS_NEW_DTAGS="-Wl,--enable-new-dtags"],) + + KDE_CHECK_COMPILER_FLAG([Wl,--as-needed], + [LDFLAGS_AS_NEEDED="-Wl,--as-needed"],) + fi + AC_SUBST(LDFLAGS_AS_NEEDED) + AC_SUBST(LDFLAGS_NEW_DTAGS) +]) + +AC_DEFUN([KDE_CHECK_NMCHECK], +[ + AC_ARG_ENABLE(nmcheck,AC_HELP_STRING([--enable-nmcheck],[enable automatic namespace cleanness check]), + kde_use_nmcheck=$enableval, kde_use_nmcheck=no) + + if test "$kde_use_nmcheck" = "yes"; then + KDE_USE_NMCHECK_TRUE="" + KDE_USE_NMCHECK_FALSE="#" + else + KDE_USE_NMCHECK_TRUE="#" + KDE_USE_NMCHECK_FALSE="" + fi + AC_SUBST(KDE_USE_NMCHECK_TRUE) + AC_SUBST(KDE_USE_NMCHECK_FALSE) +]) + +AC_DEFUN([KDE_EXPAND_MAKEVAR], [ +savex=$exec_prefix +test "x$exec_prefix" = xNONE && exec_prefix=$prefix +tmp=$$2 +while $1=`eval echo "$tmp"`; test "x$$1" != "x$tmp"; do tmp=$$1; done +exec_prefix=$savex +]) + +dnl ------------------------------------------------------------------------ +dnl Now, the same with KDE +dnl $(KDE_LDFLAGS) will be the kdeliblocation (if needed) +dnl and $(kde_includes) will be the kdehdrlocation (if needed) +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([AC_BASE_PATH_KDE], +[ +AC_REQUIRE([KDE_CHECK_STL]) +AC_REQUIRE([AC_PATH_QT])dnl +AC_REQUIRE([KDE_CHECK_LIB64]) + +AC_CHECK_RPATH +AC_MSG_CHECKING([for KDE]) + +if test "${prefix}" != NONE; then + kde_includes=${includedir} + KDE_EXPAND_MAKEVAR(ac_kde_includes, includedir) + + kde_libraries=${libdir} + KDE_EXPAND_MAKEVAR(ac_kde_libraries, libdir) + +else + ac_kde_includes= + ac_kde_libraries= + kde_libraries="" + kde_includes="" +fi + +AC_CACHE_VAL(ac_cv_have_kde, +[#try to guess kde locations + +if test "$kde_qtver" = 1; then + kde_check_header="ksock.h" + kde_check_lib="libkdecore.la" +else + kde_check_header="ksharedptr.h" + kde_check_lib="libkio.la" +fi + +if test -z "$1"; then + +kde_incdirs="$kde_libs_prefix/include /usr/lib/kde/include /usr/local/kde/include /usr/local/include /usr/kde/include /usr/include/kde /usr/include /opt/kde3/include /opt/kde/include $x_includes $qt_includes" +test -n "$KDEDIR" && kde_incdirs="$KDEDIR/include $KDEDIR/include/kde $KDEDIR $kde_incdirs" +kde_incdirs="$ac_kde_includes $kde_incdirs" +AC_FIND_FILE($kde_check_header, $kde_incdirs, kde_incdir) +ac_kde_includes="$kde_incdir" + +if test -n "$ac_kde_includes" && test ! -r "$ac_kde_includes/$kde_check_header"; then + AC_MSG_ERROR([ +in the prefix, you've chosen, are no KDE headers installed. This will fail. +So, check this please and use another prefix!]) +fi + +kde_libdirs="$kde_libs_prefix/lib${kdelibsuff} /usr/lib/kde/lib${kdelibsuff} /usr/local/kde/lib${kdelibsuff} /usr/kde/lib${kdelibsuff} /usr/lib${kdelibsuff}/kde /usr/lib${kdelibsuff}/kde3 /usr/lib${kdelibsuff} /usr/X11R6/lib${kdelibsuff} /usr/local/lib${kdelibsuff} /opt/kde3/lib${kdelibsuff} /opt/kde/lib${kdelibsuff} /usr/X11R6/kde/lib${kdelibsuff}" +test -n "$KDEDIR" && kde_libdirs="$KDEDIR/lib${kdelibsuff} $KDEDIR $kde_libdirs" +kde_libdirs="$ac_kde_libraries $libdir $kde_libdirs" +AC_FIND_FILE($kde_check_lib, $kde_libdirs, kde_libdir) +ac_kde_libraries="$kde_libdir" + +kde_widgetdir=NO +dnl this might be somewhere else +AC_FIND_FILE("kde3/plugins/designer/kdewidgets.la", $kde_libdirs, kde_widgetdir) + +if test -n "$ac_kde_libraries" && test ! -r "$ac_kde_libraries/$kde_check_lib"; then +AC_MSG_ERROR([ +in the prefix, you've chosen, are no KDE libraries installed. This will fail. +So, check this please and use another prefix!]) +fi + +if test -n "$kde_widgetdir" && test ! -r "$kde_widgetdir/kde3/plugins/designer/kdewidgets.la"; then +AC_MSG_ERROR([ +I can't find the designer plugins. These are required and should have been installed +by kdelibs]) +fi + +if test -n "$kde_widgetdir"; then + kde_widgetdir="$kde_widgetdir/kde3/plugins/designer" +fi + + +if test "$ac_kde_includes" = NO || test "$ac_kde_libraries" = NO || test "$kde_widgetdir" = NO; then + ac_cv_have_kde="have_kde=no" +else + ac_cv_have_kde="have_kde=yes \ + ac_kde_includes=$ac_kde_includes ac_kde_libraries=$ac_kde_libraries" +fi + +else dnl test -z $1, e.g. from kdelibs + + ac_cv_have_kde="have_kde=no" + +fi +])dnl + +eval "$ac_cv_have_kde" + +if test "$have_kde" != "yes"; then + if test "${prefix}" = NONE; then + ac_kde_prefix="$ac_default_prefix" + else + ac_kde_prefix="$prefix" + fi + if test "$exec_prefix" = NONE; then + ac_kde_exec_prefix="$ac_kde_prefix" + AC_MSG_RESULT([will be installed in $ac_kde_prefix]) + else + ac_kde_exec_prefix="$exec_prefix" + AC_MSG_RESULT([will be installed in $ac_kde_prefix and $ac_kde_exec_prefix]) + fi + + kde_libraries="${libdir}" + kde_includes="${includedir}" + +else + ac_cv_have_kde="have_kde=yes \ + ac_kde_includes=$ac_kde_includes ac_kde_libraries=$ac_kde_libraries" + AC_MSG_RESULT([libraries $ac_kde_libraries, headers $ac_kde_includes]) + + kde_libraries="$ac_kde_libraries" + kde_includes="$ac_kde_includes" +fi +AC_SUBST(kde_libraries) +AC_SUBST(kde_includes) + +if test "$kde_includes" = "$x_includes" || test "$kde_includes" = "$qt_includes" || test "$kde_includes" = "/usr/include"; then + KDE_INCLUDES="" +else + KDE_INCLUDES="-I$kde_includes" + all_includes="$KDE_INCLUDES $all_includes" +fi + +KDE_DEFAULT_CXXFLAGS="-DQT_CLEAN_NAMESPACE -DQT_NO_ASCII_CAST -DQT_NO_STL -DQT_NO_COMPAT -DQT_NO_TRANSLATION" + +KDE_LDFLAGS="-L$kde_libraries" +if test ! "$kde_libraries" = "$x_libraries" && test ! "$kde_libraries" = "$qt_libraries" ; then + all_libraries="$KDE_LDFLAGS $all_libraries" +fi + +AC_SUBST(KDE_LDFLAGS) +AC_SUBST(KDE_INCLUDES) + +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + +all_libraries="$all_libraries $USER_LDFLAGS" +all_includes="$all_includes $USER_INCLUDES" +AC_SUBST(all_includes) +AC_SUBST(all_libraries) + +if test -z "$1"; then +KDE_CHECK_UIC_PLUGINS +fi + +ac_kde_libraries="$kde_libdir" + +AC_SUBST(AUTODIRS) + + +]) + +AC_DEFUN([KDE_CHECK_EXTRA_LIBS], +[ +AC_MSG_CHECKING(for extra includes) +AC_ARG_WITH(extra-includes,AC_HELP_STRING([--with-extra-includes=DIR],[adds non standard include paths]), + kde_use_extra_includes="$withval", + kde_use_extra_includes=NONE +) +kde_extra_includes= +if test -n "$kde_use_extra_includes" && \ + test "$kde_use_extra_includes" != "NONE"; then + + ac_save_ifs=$IFS + IFS=':' + for dir in $kde_use_extra_includes; do + kde_extra_includes="$kde_extra_includes $dir" + USER_INCLUDES="$USER_INCLUDES -I$dir" + done + IFS=$ac_save_ifs + kde_use_extra_includes="added" +else + kde_use_extra_includes="no" +fi +AC_SUBST(USER_INCLUDES) + +AC_MSG_RESULT($kde_use_extra_includes) + +kde_extra_libs= +AC_MSG_CHECKING(for extra libs) +AC_ARG_WITH(extra-libs,AC_HELP_STRING([--with-extra-libs=DIR],[adds non standard library paths]), + kde_use_extra_libs=$withval, + kde_use_extra_libs=NONE +) +if test -n "$kde_use_extra_libs" && \ + test "$kde_use_extra_libs" != "NONE"; then + + ac_save_ifs=$IFS + IFS=':' + for dir in $kde_use_extra_libs; do + kde_extra_libs="$kde_extra_libs $dir" + KDE_EXTRA_RPATH="$KDE_EXTRA_RPATH -R $dir" + USER_LDFLAGS="$USER_LDFLAGS -L$dir" + done + IFS=$ac_save_ifs + kde_use_extra_libs="added" +else + kde_use_extra_libs="no" +fi + +AC_SUBST(USER_LDFLAGS) + +AC_MSG_RESULT($kde_use_extra_libs) + +]) + +AC_DEFUN([KDE_1_CHECK_PATH_HEADERS], +[ + AC_MSG_CHECKING([for KDE headers installed]) + AC_LANG_SAVE + AC_LANG_CPLUSPLUS +cat > conftest.$ac_ext < +#endif +#include +#include "confdefs.h" +#include + +int main() { + printf("kde_htmldir=\\"%s\\"\n", KApplication::kde_htmldir().data()); + printf("kde_appsdir=\\"%s\\"\n", KApplication::kde_appsdir().data()); + printf("kde_icondir=\\"%s\\"\n", KApplication::kde_icondir().data()); + printf("kde_sounddir=\\"%s\\"\n", KApplication::kde_sounddir().data()); + printf("kde_datadir=\\"%s\\"\n", KApplication::kde_datadir().data()); + printf("kde_locale=\\"%s\\"\n", KApplication::kde_localedir().data()); + printf("kde_cgidir=\\"%s\\"\n", KApplication::kde_cgidir().data()); + printf("kde_confdir=\\"%s\\"\n", KApplication::kde_configdir().data()); + printf("kde_mimedir=\\"%s\\"\n", KApplication::kde_mimedir().data()); + printf("kde_toolbardir=\\"%s\\"\n", KApplication::kde_toolbardir().data()); + printf("kde_wallpaperdir=\\"%s\\"\n", + KApplication::kde_wallpaperdir().data()); + printf("kde_bindir=\\"%s\\"\n", KApplication::kde_bindir().data()); + printf("kde_partsdir=\\"%s\\"\n", KApplication::kde_partsdir().data()); + printf("kde_servicesdir=\\"/tmp/dummy\\"\n"); + printf("kde_servicetypesdir=\\"/tmp/dummy\\"\n"); + printf("kde_moduledir=\\"/tmp/dummy\\"\n"); + printf("kde_styledir=\\"/tmp/dummy\\"\n"); + printf("kde_widgetdir=\\"/tmp/dummy\\"\n"); + printf("xdg_appsdir=\\"/tmp/dummy\\"\n"); + printf("xdg_menudir=\\"/tmp/dummy\\"\n"); + printf("xdg_directorydir=\\"/tmp/dummy\\"\n"); + printf("kde_kcfgdir=\\"/tmp/dummy\\"\n"); + return 0; + } +EOF + + ac_save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$all_includes $CPPFLAGS" + if AC_TRY_EVAL(ac_compile); then + AC_MSG_RESULT(yes) + else + AC_MSG_ERROR([your system is not able to compile a small KDE application! +Check, if you installed the KDE header files correctly. +For more details about this problem, look at the end of config.log.]) + fi + CPPFLAGS=$ac_save_CPPFLAGS + + AC_LANG_RESTORE +]) + +AC_DEFUN([KDE_CHECK_KDEQTADDON], +[ +AC_MSG_CHECKING(for kde-qt-addon) +AC_CACHE_VAL(kde_cv_have_kdeqtaddon, +[ + kde_ldflags_safe="$LDFLAGS" + kde_libs_safe="$LIBS" + kde_cxxflags_safe="$CXXFLAGS" + + LIBS="-lkde-qt-addon $LIBQT $LIBS" + CXXFLAGS="$CXXFLAGS -I$prefix/include -I$prefix/include/kde $all_includes" + LDFLAGS="$LDFLAGS $all_libraries $USER_LDFLAGS" + + AC_TRY_LINK([ + #include + ], + [ + QDomDocument doc; + ], + kde_cv_have_kdeqtaddon=yes, + kde_cv_have_kdeqtaddon=no + ) + + LDFLAGS=$kde_ldflags_safe + LIBS=$kde_libs_safe + CXXFLAGS=$kde_cxxflags_safe +]) + +AC_MSG_RESULT($kde_cv_have_kdeqtaddon) + +if test "$kde_cv_have_kdeqtaddon" = "no"; then + AC_MSG_ERROR([Can't find libkde-qt-addon. You need to install it first. +It is a separate package (and CVS module) named kde-qt-addon.]) +fi +]) + +AC_DEFUN([KDE_CREATE_LIBS_ALIASES], +[ + AC_REQUIRE([KDE_MISC_TESTS]) + AC_REQUIRE([KDE_CHECK_LIBDL]) + AC_REQUIRE([K_PATH_X]) + +if test $kde_qtver = 3; then + case $host in + *cygwin*) lib_kded="-lkdeinit_kded" ;; + *) lib_kded="" ;; + esac + AC_SUBST(LIB_KDED, $lib_kded) + AC_SUBST(LIB_KDECORE, "-lkdecore") + AC_SUBST(LIB_KDEUI, "-lkdeui") + AC_SUBST(LIB_KIO, "-lkio") + AC_SUBST(LIB_KJS, "-lkjs") + AC_SUBST(LIB_SMB, "-lsmb") + AC_SUBST(LIB_KAB, "-lkab") + AC_SUBST(LIB_KABC, "-lkabc") + AC_SUBST(LIB_KHTML, "-lkhtml") + AC_SUBST(LIB_KSPELL, "-lkspell") + AC_SUBST(LIB_KPARTS, "-lkparts") + AC_SUBST(LIB_KDEPRINT, "-lkdeprint") + AC_SUBST(LIB_KUTILS, "-lkutils") + AC_SUBST(LIB_KDEPIM, "-lkdepim") + AC_SUBST(LIB_KIMPROXY, "-lkimproxy") + AC_SUBST(LIB_KNEWSTUFF, "-lknewstuff") + AC_SUBST(LIB_KDNSSD, "-lkdnssd") + AC_SUBST(LIB_KUNITTEST, "-lkunittest") +# these are for backward compatibility + AC_SUBST(LIB_KSYCOCA, "-lkio") + AC_SUBST(LIB_KFILE, "-lkio") +elif test $kde_qtver = 2; then + AC_SUBST(LIB_KDECORE, "-lkdecore") + AC_SUBST(LIB_KDEUI, "-lkdeui") + AC_SUBST(LIB_KIO, "-lkio") + AC_SUBST(LIB_KSYCOCA, "-lksycoca") + AC_SUBST(LIB_SMB, "-lsmb") + AC_SUBST(LIB_KFILE, "-lkfile") + AC_SUBST(LIB_KAB, "-lkab") + AC_SUBST(LIB_KHTML, "-lkhtml") + AC_SUBST(LIB_KSPELL, "-lkspell") + AC_SUBST(LIB_KPARTS, "-lkparts") + AC_SUBST(LIB_KDEPRINT, "-lkdeprint") +else + AC_SUBST(LIB_KDECORE, "-lkdecore -lXext $(LIB_QT)") + AC_SUBST(LIB_KDEUI, "-lkdeui $(LIB_KDECORE)") + AC_SUBST(LIB_KFM, "-lkfm $(LIB_KDECORE)") + AC_SUBST(LIB_KFILE, "-lkfile $(LIB_KFM) $(LIB_KDEUI)") + AC_SUBST(LIB_KAB, "-lkab $(LIB_KIMGIO) $(LIB_KDECORE)") +fi +]) + +AC_DEFUN([AC_PATH_KDE], +[ + AC_BASE_PATH_KDE + AC_ARG_ENABLE(path-check,AC_HELP_STRING([--disable-path-check],[don't try to find out, where to install]), + [ + if test "$enableval" = "no"; + then ac_use_path_checking="default" + else ac_use_path_checking="" + fi + ], + [ + if test "$kde_qtver" = 1; + then ac_use_path_checking="" + else ac_use_path_checking="default" + fi + ] + ) + + AC_CREATE_KFSSTND($ac_use_path_checking) + + AC_SUBST_KFSSTND + KDE_CREATE_LIBS_ALIASES +]) + +dnl KDE_CHECK_FUNC_EXT(, [headers], [sample-use], [C prototype], [autoheader define], [call if found]) +AC_DEFUN([KDE_CHECK_FUNC_EXT], +[ +AC_MSG_CHECKING(for $1) +AC_CACHE_VAL(kde_cv_func_$1, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +save_CXXFLAGS="$CXXFLAGS" +kde_safe_LIBS="$LIBS" +LIBS="$LIBS $X_EXTRA_LIBS" +AC_TRY_COMPILE([ +$2 +], +[ +$3 +], +kde_cv_func_$1=yes, +kde_cv_func_$1=no) +CXXFLAGS="$save_CXXFLAGS" +LIBS="$kde_safe_LIBS" +AC_LANG_RESTORE +]) + +AC_MSG_RESULT($kde_cv_func_$1) + +AC_MSG_CHECKING([if $1 needs custom prototype]) +AC_CACHE_VAL(kde_cv_proto_$1, +[ +if test "x$kde_cv_func_$1" = xyes; then + kde_cv_proto_$1=no +else + case "$1" in + setenv|unsetenv|usleep|random|srandom|seteuid|mkstemps|mkstemp|revoke|vsnprintf|strlcpy|strlcat) + kde_cv_proto_$1="yes - in libkdefakes" + ;; + *) + kde_cv_proto_$1=unknown + ;; + esac +fi + +if test "x$kde_cv_proto_$1" = xunknown; then + +AC_LANG_SAVE +AC_LANG_CPLUSPLUS + kde_safe_libs=$LIBS + LIBS="$LIBS $X_EXTRA_LIBS" + AC_TRY_LINK([ +$2 + +extern "C" $4; +], +[ +$3 +], +[ kde_cv_func_$1=yes + kde_cv_proto_$1=yes ], + [kde_cv_proto_$1="$1 unavailable"] +) +LIBS=$kde_safe_libs +AC_LANG_RESTORE +fi +]) +AC_MSG_RESULT($kde_cv_proto_$1) + +if test "x$kde_cv_func_$1" = xyes; then + AC_DEFINE(HAVE_$5, 1, [Define if you have $1]) + $6 +fi +if test "x$kde_cv_proto_$1" = xno; then + AC_DEFINE(HAVE_$5_PROTO, 1, + [Define if you have the $1 prototype]) +fi + +AH_VERBATIM([_HAVE_$5_PROTO], +[ +#if !defined(HAVE_$5_PROTO) +#ifdef __cplusplus +extern "C" { +#endif +$4; +#ifdef __cplusplus +} +#endif +#endif +]) +]) + +AC_DEFUN([AC_CHECK_SETENV], +[ + KDE_CHECK_FUNC_EXT(setenv, [ +#include +], + [setenv("VAR", "VALUE", 1);], + [int setenv (const char *, const char *, int)], + [SETENV]) +]) + +AC_DEFUN([AC_CHECK_UNSETENV], +[ + KDE_CHECK_FUNC_EXT(unsetenv, [ +#include +], + [unsetenv("VAR");], + [void unsetenv (const char *)], + [UNSETENV]) +]) + +AC_DEFUN([AC_CHECK_GETDOMAINNAME], +[ + KDE_CHECK_FUNC_EXT(getdomainname, [ +#include +#include +#include +], + [ +char buffer[200]; +getdomainname(buffer, 200); +], + [#include + int getdomainname (char *, size_t)], + [GETDOMAINNAME]) +]) + +AC_DEFUN([AC_CHECK_GETHOSTNAME], +[ + KDE_CHECK_FUNC_EXT(gethostname, [ +#include +#include +], + [ +char buffer[200]; +gethostname(buffer, 200); +], + [int gethostname (char *, unsigned int)], + [GETHOSTNAME]) +]) + +AC_DEFUN([AC_CHECK_USLEEP], +[ + KDE_CHECK_FUNC_EXT(usleep, [ +#include +], + [ +usleep(200); +], + [int usleep (unsigned int)], + [USLEEP]) +]) + + +AC_DEFUN([AC_CHECK_RANDOM], +[ + KDE_CHECK_FUNC_EXT(random, [ +#include +], + [ +random(); +], + [long int random(void)], + [RANDOM]) + + KDE_CHECK_FUNC_EXT(srandom, [ +#include +], + [ +srandom(27); +], + [void srandom(unsigned int)], + [SRANDOM]) + +]) + +AC_DEFUN([AC_CHECK_INITGROUPS], +[ + KDE_CHECK_FUNC_EXT(initgroups, [ +#include +#include +#include +], + [ +char buffer[200]; +initgroups(buffer, 27); +], + [int initgroups(const char *, gid_t)], + [INITGROUPS]) +]) + +AC_DEFUN([AC_CHECK_MKSTEMPS], +[ + KDE_CHECK_FUNC_EXT(mkstemps, [ +#include +#include +], + [ +mkstemps("/tmp/aaaXXXXXX", 6); +], + [int mkstemps(char *, int)], + [MKSTEMPS]) +]) + +AC_DEFUN([AC_CHECK_MKSTEMP], +[ + KDE_CHECK_FUNC_EXT(mkstemp, [ +#include +#include +], + [ +mkstemp("/tmp/aaaXXXXXX"); +], + [int mkstemp(char *)], + [MKSTEMP]) +]) + +AC_DEFUN([AC_CHECK_MKDTEMP], +[ + KDE_CHECK_FUNC_EXT(mkdtemp, [ +#include +#include +], + [ +mkdtemp("/tmp/aaaXXXXXX"); +], + [char *mkdtemp(char *)], + [MKDTEMP]) +]) + + +AC_DEFUN([AC_CHECK_RES_INIT], +[ + AC_MSG_CHECKING([if res_init needs -lresolv]) + kde_libs_safe="$LIBS" + LIBS="$LIBS $X_EXTRA_LIBS -lresolv" + AC_TRY_LINK( + [ +#include +#include +#include +#include + ], + [ + res_init(); + ], + [ + LIBRESOLV="-lresolv" + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_RES_INIT, 1, [Define if you have the res_init function]) + ], + [ AC_MSG_RESULT(no) ] + ) + LIBS=$kde_libs_safe + AC_SUBST(LIBRESOLV) + + KDE_CHECK_FUNC_EXT(res_init, + [ +#include +#include +#include +#include + ], + [res_init()], + [int res_init(void)], + [RES_INIT]) +]) + +AC_DEFUN([AC_CHECK_STRLCPY], +[ + KDE_CHECK_FUNC_EXT(strlcpy, [ +#include +], +[ char buf[20]; + strlcpy(buf, "KDE function test", sizeof(buf)); +], + [unsigned long strlcpy(char*, const char*, unsigned long)], + [STRLCPY]) +]) + +AC_DEFUN([AC_CHECK_STRLCAT], +[ + KDE_CHECK_FUNC_EXT(strlcat, [ +#include +], +[ char buf[20]; + buf[0]='\0'; + strlcat(buf, "KDE function test", sizeof(buf)); +], + [unsigned long strlcat(char*, const char*, unsigned long)], + [STRLCAT]) +]) + +AC_DEFUN([AC_CHECK_RES_QUERY], +[ + KDE_CHECK_FUNC_EXT(res_query, [ +#include +#include +#include +#include +#include +], +[ +res_query(NULL, 0, 0, NULL, 0); +], + [int res_query(const char *, int, int, unsigned char *, int)], + [RES_QUERY]) +]) + +AC_DEFUN([AC_CHECK_DN_SKIPNAME], +[ + KDE_CHECK_FUNC_EXT(dn_skipname, [ +#include +#include +#include +#include +], +[ +dn_skipname (NULL, NULL); +], + [int dn_skipname (unsigned char *, unsigned char *)], + [DN_SKIPNAME]) +]) + + +AC_DEFUN([AC_FIND_GIF], + [AC_MSG_CHECKING([for giflib]) +AC_CACHE_VAL(ac_cv_lib_gif, +[ac_save_LIBS="$LIBS" +if test "x$kde_use_qt_emb" != "xyes" && test "x$kde_use_qt_mac" != "xyes"; then +LIBS="$all_libraries -lgif -lX11 $LIBSOCKET" +else +LIBS="$all_libraries -lgif" +fi +AC_TRY_LINK(dnl +[ +#ifdef __cplusplus +extern "C" { +#endif +int GifLastError(void); +#ifdef __cplusplus +} +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +], + [return GifLastError();], + eval "ac_cv_lib_gif=yes", + eval "ac_cv_lib_gif=no") +LIBS="$ac_save_LIBS" +])dnl +if eval "test \"`echo $ac_cv_lib_gif`\" = yes"; then + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_LIBGIF, 1, [Define if you have libgif]) +else + AC_MSG_ERROR(You need giflib30. Please install the kdesupport package) +fi +]) + +AC_DEFUN([KDE_FIND_JPEG_HELPER], +[ +AC_MSG_CHECKING([for libjpeg$2]) +AC_CACHE_VAL(ac_cv_lib_jpeg_$1, +[ +ac_save_LIBS="$LIBS" +LIBS="$all_libraries $USER_LDFLAGS -ljpeg$2 -lm" +ac_save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $all_includes $USER_INCLUDES" +AC_TRY_LINK( +[ +#ifdef __cplusplus +extern "C" { +#endif +void jpeg_CreateDecompress(); +#ifdef __cplusplus +} +#endif +], +[jpeg_CreateDecompress();], + eval "ac_cv_lib_jpeg_$1=-ljpeg$2", + eval "ac_cv_lib_jpeg_$1=no") +LIBS="$ac_save_LIBS" +CFLAGS="$ac_save_CFLAGS" +]) + +if eval "test ! \"`echo $ac_cv_lib_jpeg_$1`\" = no"; then + LIBJPEG="$ac_cv_lib_jpeg_$1" + AC_MSG_RESULT($ac_cv_lib_jpeg_$1) +else + AC_MSG_RESULT(no) + $3 +fi + +]) + +AC_DEFUN([AC_FIND_JPEG], +[ +dnl first look for libraries +KDE_FIND_JPEG_HELPER(6b, 6b, + KDE_FIND_JPEG_HELPER(normal, [], + [ + LIBJPEG= + ] + ) +) + +dnl then search the headers (can't use simply AC_TRY_xxx, as jpeglib.h +dnl requires system dependent includes loaded before it) +jpeg_incdirs="$includedir /usr/include /usr/local/include $kde_extra_includes" +AC_FIND_FILE(jpeglib.h, $jpeg_incdirs, jpeg_incdir) +test "x$jpeg_incdir" = xNO && jpeg_incdir= + +dnl if headers _and_ libraries are missing, this is no error, and we +dnl continue with a warning (the user will get no jpeg support in khtml) +dnl if only one is missing, it means a configuration error, but we still +dnl only warn +if test -n "$jpeg_incdir" && test -n "$LIBJPEG" ; then + AC_DEFINE_UNQUOTED(HAVE_LIBJPEG, 1, [Define if you have libjpeg]) +else + if test -n "$jpeg_incdir" || test -n "$LIBJPEG" ; then + AC_MSG_WARN([ +There is an installation error in jpeg support. You seem to have only one +of either the headers _or_ the libraries installed. You may need to either +provide correct --with-extra-... options, or the development package of +libjpeg6b. You can get a source package of libjpeg from http://www.ijg.org/ +Disabling JPEG support. +]) + else + AC_MSG_WARN([libjpeg not found. disable JPEG support.]) + fi + jpeg_incdir= + LIBJPEG= +fi + +AC_SUBST(LIBJPEG) +AH_VERBATIM(_AC_CHECK_JPEG, +[/* + * jpeg.h needs HAVE_BOOLEAN, when the system uses boolean in system + * headers and I'm too lazy to write a configure test as long as only + * unixware is related + */ +#ifdef _UNIXWARE +#define HAVE_BOOLEAN +#endif +]) +]) + +AC_DEFUN([KDE_CHECK_QT_JPEG], +[ +if test -n "$LIBJPEG"; then +AC_MSG_CHECKING([if Qt needs $LIBJPEG]) +AC_CACHE_VAL(kde_cv_qt_jpeg, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +ac_save_LIBS="$LIBS" +LIBS="$all_libraries $USER_LDFLAGS $LIBQT" +LIBS=`echo $LIBS | sed "s/$LIBJPEG//"` +ac_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $all_includes $USER_INCLUDES" +AC_TRY_LINK( +[#include ], + [ + int argc; + char** argv; + QApplication app(argc, argv);], + eval "kde_cv_qt_jpeg=no", + eval "kde_cv_qt_jpeg=yes") +LIBS="$ac_save_LIBS" +CXXFLAGS="$ac_save_CXXFLAGS" +AC_LANG_RESTORE +fi +]) + +if eval "test ! \"`echo $kde_cv_qt_jpeg`\" = no"; then + AC_MSG_RESULT(yes) + LIBJPEG_QT='$(LIBJPEG)' +else + AC_MSG_RESULT(no) + LIBJPEG_QT= +fi + +]) + +AC_DEFUN([AC_FIND_ZLIB], +[ +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_MSG_CHECKING([for libz]) +AC_CACHE_VAL(ac_cv_lib_z, +[ +kde_save_LIBS="$LIBS" +LIBS="$all_libraries $USER_LDFLAGS -lz $LIBSOCKET" +kde_save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $all_includes $USER_INCLUDES" +AC_TRY_LINK(dnl +[ +#include +#include +], +[ + char buf[42]; + gzFile f = (gzFile) 0; + /* this would segfault.. but we only link, don't run */ + (void) gzgets(f, buf, sizeof(buf)); + + return (strcmp(zlibVersion(), ZLIB_VERSION) == 0); +], + eval "ac_cv_lib_z='-lz'", + eval "ac_cv_lib_z=no") +LIBS="$kde_save_LIBS" +CFLAGS="$kde_save_CFLAGS" +])dnl +if test ! "$ac_cv_lib_z" = no; then + AC_DEFINE_UNQUOTED(HAVE_LIBZ, 1, [Define if you have libz]) + LIBZ="$ac_cv_lib_z" + AC_MSG_RESULT($ac_cv_lib_z) +else + AC_MSG_ERROR(not found. + Possibly configure picks up an outdated version + installed by XFree86. Remove it from your system. + + Check your installation and look into config.log) + LIBZ="" +fi +AC_SUBST(LIBZ) +]) + +AC_DEFUN([KDE_TRY_TIFFLIB], +[ +AC_MSG_CHECKING([for libtiff $1]) + +AC_CACHE_VAL(kde_cv_libtiff_$1, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +kde_save_LIBS="$LIBS" +if test "x$kde_use_qt_emb" != "xyes" && test "x$kde_use_qt_mac" != "xyes"; then +LIBS="$all_libraries $USER_LDFLAGS -l$1 $LIBJPEG $LIBZ -lX11 $LIBSOCKET -lm" +else +LIBS="$all_libraries $USER_LDFLAGS -l$1 $LIBJPEG $LIBZ -lm" +fi +kde_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $all_includes $USER_INCLUDES" + +AC_TRY_LINK(dnl +[ +#include +], + [return (TIFFOpen( "", "r") == 0); ], +[ + kde_cv_libtiff_$1="-l$1 $LIBJPEG $LIBZ" +], [ + kde_cv_libtiff_$1=no +]) + +LIBS="$kde_save_LIBS" +CXXFLAGS="$kde_save_CXXFLAGS" +AC_LANG_RESTORE +]) + +if test "$kde_cv_libtiff_$1" = "no"; then + AC_MSG_RESULT(no) + LIBTIFF="" + $3 +else + LIBTIFF="$kde_cv_libtiff_$1" + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_LIBTIFF, 1, [Define if you have libtiff]) + $2 +fi + +]) + +AC_DEFUN([AC_FIND_TIFF], +[ +AC_REQUIRE([K_PATH_X]) +AC_REQUIRE([AC_FIND_ZLIB]) +AC_REQUIRE([AC_FIND_JPEG]) +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + +KDE_TRY_TIFFLIB(tiff, [], + KDE_TRY_TIFFLIB(tiff34)) + +AC_SUBST(LIBTIFF) +]) + +AC_DEFUN([KDE_FIND_LIBEXR], +[ +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_REQUIRE([AC_FIND_ZLIB]) +AC_CACHE_VAL(ac_cv_libexr, +[ + if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + fi + + AC_MSG_CHECKING([for OpenEXR libraries]) + + if test "$PKG_CONFIG" = "no" ; then + AC_MSG_RESULT(no) + echo "*** The pkg-config script could not be found. Make sure it is" + echo "*** in your path, or set the PKG_CONFIG environment variable" + echo "*** to the full path to pkg-config." + echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." + else + if ! $PKG_CONFIG --exists OpenEXR ; then + AC_MSG_RESULT(no) + EXRSTATUS=no + else + if ! $PKG_CONFIG --atleast-version="1.1.1" OpenEXR ; then + AC_MSG_RESULT(no) + EXRSTATUS=old + else + kde_save_LIBS="$LIBS" + LIBS="$LIBS $all_libraries $USER_LDFLAGS `pkg-config --libs OpenEXR` $LIBZ" + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + kde_save_CXXFLAGS="$CXXFLAGS" + EXR_FLAGS=`$PKG_CONFIG --cflags OpenEXR` + CXXFLAGS="$CXXFLAGS $all_includes $USER_INCLUDES $EXR_FLAGS" + + AC_TRY_LINK(dnl + [ + #include + ], + [ + using namespace Imf; + RgbaInputFile file ("dummy"); + return 0; + ], + eval "ac_cv_libexr='`pkg-config --libs OpenEXR`'", + eval "ac_cv_libexr=no" + ) + LIBS="$kde_save_LIBS" + CXXFLAGS="$kde_save_CXXFLAGS" + AC_LANG_RESTORE + ])dnl + if eval "test ! \"`echo $ac_cv_libexr`\" = no"; then + AC_DEFINE_UNQUOTED(HAVE_EXR, 1, [Define if you have OpenEXR]) + LIB_EXR="$ac_cv_libexr" + AC_MSG_RESULT($ac_cv_libexr) + else + AC_MSG_RESULT(no) + LIB_EXR="" + fi + fi + fi + fi + AC_SUBST(LIB_EXR) + AC_SUBST(EXR_FLAGS) +]) + + + +AC_DEFUN([AC_FIND_PNG], +[ +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_REQUIRE([AC_FIND_ZLIB]) +AC_MSG_CHECKING([for libpng]) +AC_CACHE_VAL(ac_cv_lib_png, +[ +kde_save_LIBS="$LIBS" +if test "x$kde_use_qt_emb" != "xyes" && test "x$kde_use_qt_mac" != "xyes"; then +LIBS="$LIBS $all_libraries $USER_LDFLAGS -lpng $LIBZ -lm -lX11 $LIBSOCKET" +else +LIBS="$LIBS $all_libraries $USER_LDFLAGS -lpng $LIBZ -lm" +fi +kde_save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $all_includes $USER_INCLUDES" + +AC_TRY_LINK(dnl + [ + #include + ], + [ + png_structp png_ptr = png_create_read_struct( /* image ptr */ + PNG_LIBPNG_VER_STRING, 0, 0, 0 ); + return( png_ptr != 0 ); + ], + eval "ac_cv_lib_png='-lpng $LIBZ -lm'", + eval "ac_cv_lib_png=no" +) +LIBS="$kde_save_LIBS" +CFLAGS="$kde_save_CFLAGS" +])dnl +if eval "test ! \"`echo $ac_cv_lib_png`\" = no"; then + AC_DEFINE_UNQUOTED(HAVE_LIBPNG, 1, [Define if you have libpng]) + LIBPNG="$ac_cv_lib_png" + AC_SUBST(LIBPNG) + AC_MSG_RESULT($ac_cv_lib_png) +else + AC_MSG_RESULT(no) + LIBPNG="" + AC_SUBST(LIBPNG) +fi +]) + + +AC_DEFUN([AC_FIND_JASPER], +[ +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_REQUIRE([AC_FIND_JPEG]) +AC_MSG_CHECKING([for jasper]) +AC_CACHE_VAL(ac_cv_jasper, +[ +kde_save_LIBS="$LIBS" +LIBS="$LIBS $all_libraries $USER_LDFLAGS -ljasper $LIBJPEG -lm" +kde_save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $all_includes $USER_INCLUDES" + +AC_TRY_LINK(dnl + [ + #include + ], + [ + return( jas_init() ); + ], + eval "ac_cv_jasper='-ljasper $LIBJPEG -lm'", + eval "ac_cv_jasper=no" +) +LIBS="$kde_save_LIBS" +CFLAGS="$kde_save_CFLAGS" +])dnl +if eval "test ! \"`echo $ac_cv_jasper`\" = no"; then + AC_DEFINE_UNQUOTED(HAVE_JASPER, 1, [Define if you have jasper]) + LIB_JASPER="$ac_cv_jasper" + AC_MSG_RESULT($ac_cv_jasper) +else + AC_MSG_RESULT(no) + LIB_JASPER="" +fi +AC_SUBST(LIB_JASPER) +]) + +AC_DEFUN([AC_CHECK_BOOL], +[ + AC_DEFINE_UNQUOTED(HAVE_BOOL, 1, [You _must_ have bool]) +]) + +AC_DEFUN([AC_CHECK_GNU_EXTENSIONS], +[ +AC_MSG_CHECKING(if you need GNU extensions) +AC_CACHE_VAL(ac_cv_gnu_extensions, +[ +cat > conftest.c << EOF +#include + +#ifdef __GNU_LIBRARY__ +yes +#endif +EOF + +if (eval "$ac_cpp conftest.c") 2>&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_gnu_extensions=yes +else + ac_cv_gnu_extensions=no +fi +]) + +AC_MSG_RESULT($ac_cv_gnu_extensions) +if test "$ac_cv_gnu_extensions" = "yes"; then + AC_DEFINE_UNQUOTED(_GNU_SOURCE, 1, [Define if you need to use the GNU extensions]) +fi +]) + +AC_DEFUN([KDE_CHECK_COMPILER_FLAG], +[ +AC_MSG_CHECKING([whether $CXX supports -$1]) +kde_cache=`echo $1 | sed 'y% .=/+-,%____p__%'` +AC_CACHE_VAL(kde_cv_prog_cxx_$kde_cache, +[ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -$1" + AC_TRY_LINK([],[ return 0; ], [eval "kde_cv_prog_cxx_$kde_cache=yes"], []) + CXXFLAGS="$save_CXXFLAGS" + AC_LANG_RESTORE +]) +if eval "test \"`echo '$kde_cv_prog_cxx_'$kde_cache`\" = yes"; then + AC_MSG_RESULT(yes) + : + $2 +else + AC_MSG_RESULT(no) + : + $3 +fi +]) + +AC_DEFUN([KDE_CHECK_C_COMPILER_FLAG], +[ +AC_MSG_CHECKING([whether $CC supports -$1]) +kde_cache=`echo $1 | sed 'y% .=/+-,%____p__%'` +AC_CACHE_VAL(kde_cv_prog_cc_$kde_cache, +[ + AC_LANG_SAVE + AC_LANG_C + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -$1" + AC_TRY_LINK([],[ return 0; ], [eval "kde_cv_prog_cc_$kde_cache=yes"], []) + CFLAGS="$save_CFLAGS" + AC_LANG_RESTORE +]) +if eval "test \"`echo '$kde_cv_prog_cc_'$kde_cache`\" = yes"; then + AC_MSG_RESULT(yes) + : + $2 +else + AC_MSG_RESULT(no) + : + $3 +fi +]) + + +dnl AC_REMOVE_FORBIDDEN removes forbidden arguments from variables +dnl use: AC_REMOVE_FORBIDDEN(CC, [-forbid -bad-option whatever]) +dnl it's all white-space separated +AC_DEFUN([AC_REMOVE_FORBIDDEN], +[ __val=$$1 + __forbid=" $2 " + if test -n "$__val"; then + __new="" + ac_save_IFS=$IFS + IFS=" " + for i in $__val; do + case "$__forbid" in + *" $i "*) AC_MSG_WARN([found forbidden $i in $1, removing it]) ;; + *) # Careful to not add spaces, where there were none, because otherwise + # libtool gets confused, if we change e.g. CXX + if test -z "$__new" ; then __new=$i ; else __new="$__new $i" ; fi ;; + esac + done + IFS=$ac_save_IFS + $1=$__new + fi +]) + + +AC_DEFUN([KDE_CHECK_FOR_BAD_COMPILER], +[ + AC_MSG_CHECKING([whether $CC is blacklisted]) + + dnl In theory we have tu run this test against $CC and $CXX + dnl in C and in C++ mode, because its perfectly legal for + dnl the user to mix compiler versions, since C has a defined + dnl ABI. + dnl + dnl For now, we assume the user is not on crack. + + AC_TRY_COMPILE([ +#ifdef __GNUC__ +#if __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 0 +choke me +#endif +#endif +], , + kde_bad_compiler=no, + kde_bad_compiler=yes +) + + AC_MSG_RESULT($kde_bad_compiler) + +if test "$kde_bad_compiler" = "yes"; then + AC_MSG_ERROR([ + +This particular compiler version is blacklisted because it +is known to miscompile KDE. Please use a newer version, or +if that is not yet available, choose an older version. + +Please do not report a bug or bother us reporting this +configure error. We know about it, and we introduced +it by intention to avoid untraceable bugs or crashes in KDE. + +]) +fi + +]) + + +AC_DEFUN([KDE_CHECK_FOR_OPT_NOINLINE_MATCH], +[ + AC_CACHE_CHECK([whether system headers can cope with -O2 -fno-inline], + kde_cv_opt_noinline_match, + [ + kde_cv_opt_noinline_match=irrelevant + dnl if we don't use both -O2 and -fno-inline, this check is moot + if echo "$CFLAGS" | grep -e -O2 >/dev/null 2>/dev/null \ + && echo "$CFLAGS" | grep -e -fno-inline >/dev/null 2>/dev/null ; then + + ac_cflags_save="$CFLAGS" + CFLAGS="$CFLAGS -D_USE_GNU" + + AC_TRY_LINK([ + #include +], [ const char *pt, *et; + et = __extension__ ({ char __a0, __a1, __a2; (__builtin_constant_p ( ";," ) && ((size_t)(const void *)(( ";," )+ 1) - (size_t)(const void *)( ";," ) == 1) ? ((__a0 =((__const char *) ( ";," ))[0], __a0 == '\0') ? ((void) ( pt ),((void *)0) ) : ((__a1 = ((__const char *) ( ";," ))[1], __a1== '\0') ? (__extension__ (__builtin_constant_p ( __a0 ) && ( __a0 ) == '\0' ? (char *) __rawmemchr ( pt , __a0) : strchr( pt , __a0 ))) : ((__a2 = ((__const char *) ( ";," ))[2], __a2 == '\0') ? __strpbrk_c2 ( pt , __a0, __a1) :(((__const char *) ( ";," ))[3] == '\0' ? __strpbrk_c3 ( pt ,__a0, __a1, __a2): strpbrk ( pt , ";," ))))) : strpbrk ( pt , ";," )); }) ; +], + kde_cv_opt_noinline_match=yes, + kde_cv_opt_noinline_match=no + ) + + CFLAGS="$ac_cflags_save" + fi + ]) +]) + + +dnl AC_VALIDIFY_CXXFLAGS checks for forbidden flags the user may have given +AC_DEFUN([AC_VALIDIFY_CXXFLAGS], +[dnl +if test "x$kde_use_qt_emb" != "xyes"; then + AC_REMOVE_FORBIDDEN(CXX, [-fno-rtti -rpath]) + AC_REMOVE_FORBIDDEN(CXXFLAGS, [-fno-rtti -rpath]) +else + AC_REMOVE_FORBIDDEN(CXX, [-rpath]) + AC_REMOVE_FORBIDDEN(CXXFLAGS, [-rpath]) +fi +]) + +AC_DEFUN([AC_CHECK_COMPILERS], +[ + AC_ARG_ENABLE(debug, + AC_HELP_STRING([--enable-debug=ARG],[enables debug symbols (yes|no|full) [default=no]]), + [ + case $enableval in + yes) + kde_use_debug_code="yes" + kde_use_debug_define=no + ;; + full) + kde_use_debug_code="full" + kde_use_debug_define=no + ;; + *) + kde_use_debug_code="no" + kde_use_debug_define=yes + ;; + esac + ], + [kde_use_debug_code="no" + kde_use_debug_define=no + ]) + + dnl Just for configure --help + AC_ARG_ENABLE(dummyoption, + AC_HELP_STRING([--disable-debug], + [disables debug output and debug symbols [default=no]]), + [],[]) + + AC_ARG_ENABLE(strict, + AC_HELP_STRING([--enable-strict], + [compiles with strict compiler options (may not work!)]), + [ + if test $enableval = "no"; then + kde_use_strict_options="no" + else + kde_use_strict_options="yes" + fi + ], [kde_use_strict_options="no"]) + + AC_ARG_ENABLE(warnings,AC_HELP_STRING([--disable-warnings],[disables compilation with -Wall and similar]), + [ + if test $enableval = "no"; then + kde_use_warnings="no" + else + kde_use_warnings="yes" + fi + ], [kde_use_warnings="yes"]) + + dnl enable warnings for debug build + if test "$kde_use_debug_code" != "no"; then + kde_use_warnings=yes + fi + + AC_ARG_ENABLE(profile,AC_HELP_STRING([--enable-profile],[creates profiling infos [default=no]]), + [kde_use_profiling=$enableval], + [kde_use_profiling="no"] + ) + + dnl this prevents stupid AC_PROG_CC to add "-g" to the default CFLAGS + CFLAGS=" $CFLAGS" + + AC_PROG_CC + + AC_PROG_CPP + + if test "$GCC" = "yes"; then + if test "$kde_use_debug_code" != "no"; then + if test $kde_use_debug_code = "full"; then + CFLAGS="-g3 -fno-inline $CFLAGS" + else + CFLAGS="-g -O2 -fno-schedule-insns -fno-inline $CFLAGS" + fi + else + CFLAGS="-O2 $CFLAGS" + fi + fi + + if test "$kde_use_debug_define" = "yes"; then + CFLAGS="-DNDEBUG $CFLAGS" + fi + + + case "$host" in + *-*-sysv4.2uw*) CFLAGS="-D_UNIXWARE $CFLAGS";; + *-*-sysv5uw7*) CFLAGS="-D_UNIXWARE7 $CFLAGS";; + esac + + if test -z "$LDFLAGS" && test "$kde_use_debug_code" = "no" && test "$GCC" = "yes"; then + LDFLAGS="" + fi + + CXXFLAGS=" $CXXFLAGS" + + AC_PROG_CXX + + KDE_CHECK_FOR_BAD_COMPILER + + if test "$GXX" = "yes" || test "$CXX" = "KCC"; then + if test "$kde_use_debug_code" != "no"; then + if test "$CXX" = "KCC"; then + CXXFLAGS="+K0 -Wall -pedantic -W -Wpointer-arith -Wwrite-strings $CXXFLAGS" + else + if test "$kde_use_debug_code" = "full"; then + CXXFLAGS="-g3 -fno-inline $CXXFLAGS" + else + CXXFLAGS="-g -O2 -fno-schedule-insns -fno-inline $CXXFLAGS" + fi + fi + KDE_CHECK_COMPILER_FLAG(fno-builtin,[CXXFLAGS="-fno-builtin $CXXFLAGS"]) + + dnl convenience compiler flags + KDE_CHECK_COMPILER_FLAG(Woverloaded-virtual, [WOVERLOADED_VIRTUAL="-Woverloaded-virtual"], [WOVERLOADED_VRITUAL=""]) + AC_SUBST(WOVERLOADED_VIRTUAL) + else + if test "$CXX" = "KCC"; then + CXXFLAGS="+K3 $CXXFLAGS" + else + CXXFLAGS="-O2 $CXXFLAGS" + fi + fi + fi + + if test "$kde_use_debug_define" = "yes"; then + CXXFLAGS="-DNDEBUG -DNO_DEBUG $CXXFLAGS" + fi + + if test "$kde_use_profiling" = "yes"; then + KDE_CHECK_COMPILER_FLAG(pg, + [ + CFLAGS="-pg $CFLAGS" + CXXFLAGS="-pg $CXXFLAGS" + ]) + fi + + if test "$kde_use_warnings" = "yes"; then + if test "$GCC" = "yes"; then + CXXFLAGS="-Wall -W -Wpointer-arith $CXXFLAGS" + case $host in + *-*-linux-gnu) + CFLAGS="-std=iso9899:1990 -W -Wall -Wchar-subscripts -Wshadow -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -D_XOPEN_SOURCE=500 -D_BSD_SOURCE $CFLAGS" + CXXFLAGS="-ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wchar-subscripts $CXXFLAGS" + KDE_CHECK_COMPILER_FLAG(Wmissing-format-attribute, [CXXFLAGS="$CXXFLAGS -Wformat-security -Wmissing-format-attribute"]) + KDE_CHECK_C_COMPILER_FLAG(Wmissing-format-attribute, [CFLAGS="$CFLAGS -Wformat-security -Wmissing-format-attribute"]) + ;; + esac + KDE_CHECK_COMPILER_FLAG(Wundef,[CXXFLAGS="-Wundef $CXXFLAGS"]) + KDE_CHECK_COMPILER_FLAG(Wno-long-long,[CXXFLAGS="-Wno-long-long $CXXFLAGS"]) + dnl ### FIXME: revert for KDE 4 + KDE_CHECK_COMPILER_FLAG(Wno-non-virtual-dtor,[CXXFLAGS="$CXXFLAGS -Wno-non-virtual-dtor"]) + fi + fi + + if test "$GXX" = "yes" && test "$kde_use_strict_options" = "yes"; then + CXXFLAGS="-Wcast-qual -Wshadow -Wcast-align $CXXFLAGS" + fi + + AC_ARG_ENABLE(pch, + AC_HELP_STRING([--enable-pch], + [enables precompiled header support (currently only KCC or gcc >=3.4+unsermake) [default=no]]), + [ kde_use_pch=$enableval ],[ kde_use_pch=no ]) + + HAVE_GCC_VISIBILITY=0 + AC_SUBST([HAVE_GCC_VISIBILITY]) + + if test "$GXX" = "yes"; then + gcc_no_reorder_blocks=NO + KDE_CHECK_COMPILER_FLAG(fno-reorder-blocks,[gcc_no_reorder_blocks=YES]) + if test $kde_use_debug_code != "no" && \ + test $kde_use_debug_code != "full" && \ + test "YES" = "$gcc_no_reorder_blocks" ; then + CXXFLAGS="$CXXFLAGS -fno-reorder-blocks" + CFLAGS="$CFLAGS -fno-reorder-blocks" + fi + KDE_CHECK_COMPILER_FLAG(fno-exceptions,[CXXFLAGS="$CXXFLAGS -fno-exceptions"]) + KDE_CHECK_COMPILER_FLAG(fno-check-new, [CXXFLAGS="$CXXFLAGS -fno-check-new"]) + KDE_CHECK_COMPILER_FLAG(fno-common, [CXXFLAGS="$CXXFLAGS -fno-common"]) + KDE_CHECK_COMPILER_FLAG(fexceptions, [USE_EXCEPTIONS="-fexceptions"], USE_EXCEPTIONS= ) + ENABLE_PERMISSIVE_FLAG="-fpermissive" + + if test "$kde_use_pch" = "yes"; then + AC_MSG_CHECKING(whether gcc supports precompiling c header files) + echo >conftest.h + if $CC -x c-header conftest.h >/dev/null 2>/dev/null; then + kde_gcc_supports_pch=yes + AC_MSG_RESULT(yes) + else + kde_gcc_supports_pch=no + AC_MSG_RESULT(no) + fi + if test "$kde_gcc_supports_pch" = "yes"; then + AC_MSG_CHECKING(whether gcc supports precompiling c++ header files) + if $CXX -x c++-header conftest.h >/dev/null 2>/dev/null; then + kde_gcc_supports_pch=yes + AC_MSG_RESULT(yes) + else + kde_gcc_supports_pch=no + AC_MSG_RESULT(no) + fi + fi + rm -f conftest.h conftest.h.gch + fi + + KDE_CHECK_FOR_OPT_NOINLINE_MATCH + if test "x$kde_cv_opt_noinline_match" = "xno" ; then + CFLAGS="`echo "$CFLAGS" | sed "s/ -fno-inline//"`" + fi + fi + AM_CONDITIONAL(unsermake_enable_pch, test "$kde_use_pch" = "yes" && test "$kde_gcc_supports_pch" = "yes") + if test "$CXX" = "KCC"; then + dnl unfortunately we currently cannot disable exception support in KCC + dnl because doing so is binary incompatible and Qt by default links with exceptions :-( + dnl KDE_CHECK_COMPILER_FLAG(-no_exceptions,[CXXFLAGS="$CXXFLAGS --no_exceptions"]) + dnl KDE_CHECK_COMPILER_FLAG(-exceptions, [USE_EXCEPTIONS="--exceptions"], USE_EXCEPTIONS= ) + + if test "$kde_use_pch" = "yes"; then + dnl TODO: support --pch-dir! + KDE_CHECK_COMPILER_FLAG(-pch,[CXXFLAGS="$CXXFLAGS --pch"]) + dnl the below works (but the dir must exist), but it's + dnl useless for a whole package. + dnl The are precompiled headers for each source file, so when compiling + dnl from scratch, it doesn't make a difference, and they take up + dnl around ~5Mb _per_ sourcefile. + dnl KDE_CHECK_COMPILER_FLAG(-pch_dir /tmp, + dnl [CXXFLAGS="$CXXFLAGS --pch_dir `pwd`/pcheaders"]) + fi + dnl this flag controls inlining. by default KCC inlines in optimisation mode + dnl all implementations that are defined inside the class {} declaration. + dnl because of templates-compatibility with broken gcc compilers, this + dnl can cause excessive inlining. This flag limits it to a sane level + KDE_CHECK_COMPILER_FLAG(-inline_keyword_space_time=6,[CXXFLAGS="$CXXFLAGS --inline_keyword_space_time=6"]) + KDE_CHECK_COMPILER_FLAG(-inline_auto_space_time=2,[CXXFLAGS="$CXXFLAGS --inline_auto_space_time=2"]) + KDE_CHECK_COMPILER_FLAG(-inline_implicit_space_time=2.0,[CXXFLAGS="$CXXFLAGS --inline_implicit_space_time=2.0"]) + KDE_CHECK_COMPILER_FLAG(-inline_generated_space_time=2.0,[CXXFLAGS="$CXXFLAGS --inline_generated_space_time=2.0"]) + dnl Some source files are shared between multiple executables + dnl (or libraries) and some of those need template instantiations. + dnl In that case KCC needs to compile those sources with + dnl --one_instantiation_per_object. To make it easy for us we compile + dnl _all_ objects with that flag (--one_per is a shorthand). + KDE_CHECK_COMPILER_FLAG(-one_per, [CXXFLAGS="$CXXFLAGS --one_per"]) + fi + AC_SUBST(USE_EXCEPTIONS) + dnl obsolete macro - provided to keep things going + USE_RTTI= + AC_SUBST(USE_RTTI) + + case "$host" in + *-*-irix*) test "$GXX" = yes && CXXFLAGS="-D_LANGUAGE_C_PLUS_PLUS -D__LANGUAGE_C_PLUS_PLUS $CXXFLAGS" ;; + *-*-sysv4.2uw*) CXXFLAGS="-D_UNIXWARE $CXXFLAGS";; + *-*-sysv5uw7*) CXXFLAGS="-D_UNIXWARE7 $CXXFLAGS";; + *-*-solaris*) + if test "$GXX" = yes; then + libstdcpp=`$CXX -print-file-name=libstdc++.so` + if test ! -f $libstdcpp; then + AC_MSG_ERROR([You've compiled gcc without --enable-shared. This doesn't work with KDE. Please recompile gcc with --enable-shared to receive a libstdc++.so]) + fi + fi + ;; + esac + + AC_VALIDIFY_CXXFLAGS + + AC_PROG_CXXCPP + + if test "$GCC" = yes; then + NOOPT_CFLAGS=-O0 + fi + KDE_CHECK_COMPILER_FLAG(O0,[NOOPT_CXXFLAGS=-O0]) + + AC_ARG_ENABLE(coverage, + AC_HELP_STRING([--enable-coverage],[use gcc coverage testing]), [ + if test "$am_cv_CC_dependencies_compiler_type" = "gcc3"; then + ac_coverage_compiler="-fprofile-arcs -ftest-coverage" + ac_coverage_linker="-lgcc" + elif test "$am_cv_CC_dependencies_compiler_type" = "gcc"; then + ac_coverage_compiler="-fprofile-arcs -ftest-coverage" + ac_coverage_linker="" + else + AC_MSG_ERROR([coverage with your compiler is not supported]) + fi + CFLAGS="$CFLAGS $ac_coverage_compiler" + CXXFLAGS="$CXXFLAGS $ac_coverage_compiler" + LDFLAGS="$LDFLAGS $ac_coverage_linker" + ]) + + AC_SUBST(NOOPT_CXXFLAGS) + AC_SUBST(NOOPT_CFLAGS) + AC_SUBST(ENABLE_PERMISSIVE_FLAG) + + KDE_CHECK_NEW_LDFLAGS + KDE_CHECK_FINAL + KDE_CHECK_CLOSURE + KDE_CHECK_NMCHECK + + ifdef([AM_DEPENDENCIES], AC_REQUIRE([KDE_ADD_DEPENDENCIES]), []) +]) + +AC_DEFUN([KDE_CHECK_VISIBILITY_GCC_BUG], + [ + AC_CACHE_CHECK([for gcc -fvisibility-inlines-hidden bug], kde_cv_val_gcc_visibility_bug, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + safe_CXXFLAGS=$CXXFLAGS + safe_LDFLAGS=$LDFLAGS + CXXFLAGS="$CXXFLAGS -fPIC -fvisibility-inlines-hidden -O0" + LDFLAGS="$LDFLAGS -shared -fPIC" + + AC_TRY_LINK( + [ + /* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19664 */ + #include + int some_function( void ) __attribute__ ((visibility("default"))); + int some_function( void ) + { + std::string s("blafasel"); + return 0; + } + ], [/* elvis is alive */], + kde_cv_val_gcc_visibility_bug=no, kde_cv_val_gcc_visibility_bug=yes) + + CXXFLAGS=$safe_CXXFLAGS + LDFLAGS=$safe_LDFLAGS + AC_LANG_RESTORE + ] + ) + + if test x$kde_cv_val_gcc_visibility_bug = xno; then + CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden" + fi + ] +) + +AC_DEFUN([KDE_ENABLE_HIDDEN_VISIBILITY], +[ + AC_BEFORE([AC_PATH_QT_1_3], [KDE_ENABLE_HIDDEN_VISIBILITY]) + + AC_MSG_CHECKING([grepping for visibility push/pop in headers]) + + if test "x$GXX" = "xyes"; then + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_EGREP_CPP( + [GCC visibility push], + [ #include + ], + [ + AC_MSG_RESULT(yes) + kde_stdc_visibility_patched=yes ], + [ + AC_MSG_RESULT(no) + AC_MSG_WARN([Your libstdc++ doesn't appear to be patched for + visibility support. Disabling -fvisibility=hidden]) + + kde_stdc_visibility_patched=no ]) + + AC_LANG_RESTORE + + kde_have_gcc_visibility=no + KDE_CHECK_COMPILER_FLAG(fvisibility=hidden, + [ + kde_have_gcc_visibility=yes + dnl the whole toolchain is just a mess, gcc is just too buggy + dnl to handle STL with visibility enabled. Lets reconsider + dnl when gcc 4.2 is out or when things get fixed in the compiler. + dnl Contact mueller@kde.org for details. + AC_ARG_ENABLE(gcc-hidden-visibility, + AC_HELP_STRING([--enable-gcc-hidden-visibility],[toolchain hidden visibility [default=no]]), + [kde_have_gcc_visibility=$enableval], + [kde_have_gcc_visibility=no]) + + AC_CACHE_CHECK([if Qt is patched for -fvisibility], kde_cv_val_qt_gcc_visibility_patched, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + safe_CXXFLAGS=$CXXFLAGS + CXXFLAGS="$CXXFLAGS $all_includes" + + AC_TRY_COMPILE( + [ +#include +#if Q_EXPORT - 0 != 0 +/* if this compiles, then Q_EXPORT is undefined */ +/* if Q_EXPORT is nonempty, this will break compilation */ +#endif + ], [/* elvis is alive */], + kde_cv_val_qt_gcc_visibility_patched=no, kde_cv_val_qt_gcc_visibility_patched=yes) + + CXXFLAGS=$safe_CXXFLAGS + AC_LANG_RESTORE + ] + ) + + if test x$kde_have_gcc_visibility = "xyes" && test x$kde_stdc_visibility_patched = "xyes" && test x$kde_cv_val_qt_gcc_visibility_patched = "xyes"; then + CXXFLAGS="$CXXFLAGS -fvisibility=hidden" + KDE_CHECK_VISIBILITY_GCC_BUG + HAVE_GCC_VISIBILITY=1 + AC_DEFINE_UNQUOTED(__KDE_HAVE_GCC_VISIBILITY, "$HAVE_GCC_VISIBILITY", [define to 1 if -fvisibility is supported]) + fi + ]) + fi +]) + +AC_DEFUN([KDE_ADD_DEPENDENCIES], +[ + [A]M_DEPENDENCIES(CC) + [A]M_DEPENDENCIES(CXX) +]) + +dnl just a wrapper to clean up configure.in +AC_DEFUN([KDE_PROG_LIBTOOL], +[ +AC_REQUIRE([AC_CHECK_COMPILERS]) +AC_REQUIRE([AC_ENABLE_SHARED]) +AC_REQUIRE([AC_ENABLE_STATIC]) + +AC_REQUIRE([AC_LIBTOOL_DLOPEN]) +AC_REQUIRE([KDE_CHECK_LIB64]) + +AC_OBJEXT +AC_EXEEXT + +AM_PROG_LIBTOOL +AC_LIBTOOL_CXX + +LIBTOOL_SHELL="/bin/sh ./libtool" +# LIBTOOL="$LIBTOOL --silent" +KDE_PLUGIN="-avoid-version -module -no-undefined \$(KDE_NO_UNDEFINED) \$(KDE_RPATH) \$(KDE_MT_LDFLAGS)" +AC_SUBST(KDE_PLUGIN) + +# This hack ensures that libtool creates shared libs for kunittest plugins. By default check_LTLIBRARIES makes static libs. +KDE_CHECK_PLUGIN="\$(KDE_PLUGIN) -rpath \$(libdir)" +AC_SUBST(KDE_CHECK_PLUGIN) + +# we patch configure quite some so we better keep that consistent for incremental runs +AC_SUBST(AUTOCONF,'$(SHELL) $(top_srcdir)/admin/cvs.sh configure || touch configure') +]) + +AC_DEFUN([KDE_CHECK_LIB64], +[ + AC_ARG_ENABLE(libsuffix, + AC_HELP_STRING([--enable-libsuffix], + [/lib directory suffix (64,32,none,auto[=default])]), + kdelibsuff=$enableval, kdelibsuff="auto") + + if test "$kdelibsuff" = "auto"; then + +cat > conftest.c << EOF +#include +int main() { + return 0; +} +EOF + kdelibsuff=`$CC conftest.c -o conftest.out; ldd conftest.out |sed -ne '/libc.so/{ + s,.*/lib\([[^\/]]*\)/.*,\1, + p +}'` + rm -rf conftest.* + fi + + if test "$kdelibsuff" = "no" || test "$kdelibsuff" = "none"; then + kdelibsuff= + fi + if test -z "$kdelibsuff"; then + AC_MSG_RESULT([not using lib directory suffix]) + AC_DEFINE(KDELIBSUFF, [""], Suffix for lib directories) + else + if test "$libdir" = '${exec_prefix}/lib'; then + libdir="$libdir${kdelibsuff}" + AC_SUBST([libdir], ["$libdir"]) dnl ugly hack for lib64 platforms + fi + AC_DEFINE_UNQUOTED(KDELIBSUFF, ["${kdelibsuff}"], Suffix for lib directories) + AC_MSG_RESULT([using lib directory suffix $kdelibsuff]) + fi +]) + +AC_DEFUN([KDE_CHECK_TYPES], +[ AC_CHECK_SIZEOF(int, 4)dnl + AC_CHECK_SIZEOF(short)dnl + AC_CHECK_SIZEOF(long, 4)dnl + AC_CHECK_SIZEOF(char *, 4)dnl +])dnl + +dnl Not used - kept for compat only? +AC_DEFUN([KDE_DO_IT_ALL], +[ +AC_CANONICAL_SYSTEM +AC_ARG_PROGRAM +AM_INIT_AUTOMAKE($1, $2) +AM_DISABLE_LIBRARIES +AC_PREFIX_DEFAULT(${KDEDIR:-/usr/local/kde}) +AC_CHECK_COMPILERS +KDE_PROG_LIBTOOL +AM_KDE_WITH_NLS +AC_PATH_KDE +]) + +AC_DEFUN([AC_CHECK_RPATH], +[ +AC_MSG_CHECKING(for rpath) +AC_ARG_ENABLE(rpath, + AC_HELP_STRING([--disable-rpath],[do not use the rpath feature of ld]), + USE_RPATH=$enableval, USE_RPATH=yes) + +if test -z "$KDE_RPATH" && test "$USE_RPATH" = "yes"; then + + KDE_RPATH="-R \$(libdir)" + + if test "$kde_libraries" != "$libdir"; then + KDE_RPATH="$KDE_RPATH -R \$(kde_libraries)" + fi + + if test -n "$qt_libraries"; then + KDE_RPATH="$KDE_RPATH -R \$(qt_libraries)" + fi + dnl $x_libraries is set to /usr/lib in case + if test -n "$X_LDFLAGS"; then + X_RPATH="-R \$(x_libraries)" + KDE_RPATH="$KDE_RPATH $X_RPATH" + fi + if test -n "$KDE_EXTRA_RPATH"; then + KDE_RPATH="$KDE_RPATH \$(KDE_EXTRA_RPATH)" + fi +fi +AC_SUBST(KDE_EXTRA_RPATH) +AC_SUBST(KDE_RPATH) +AC_SUBST(X_RPATH) +AC_MSG_RESULT($USE_RPATH) +]) + +dnl Check for the type of the third argument of getsockname +AC_DEFUN([AC_CHECK_SOCKLEN_T], +[ + AC_MSG_CHECKING(for socklen_t) + AC_CACHE_VAL(kde_cv_socklen_t, + [ + AC_LANG_PUSH(C++) + kde_cv_socklen_t=no + AC_TRY_COMPILE([ + #include + #include + ], + [ + socklen_t len; + getpeername(0,0,&len); + ], + [ + kde_cv_socklen_t=yes + kde_cv_socklen_t_equiv=socklen_t + ]) + AC_LANG_POP(C++) + ]) + AC_MSG_RESULT($kde_cv_socklen_t) + if test $kde_cv_socklen_t = no; then + AC_MSG_CHECKING([for socklen_t equivalent for socket functions]) + AC_CACHE_VAL(kde_cv_socklen_t_equiv, + [ + kde_cv_socklen_t_equiv=int + AC_LANG_PUSH(C++) + for t in int size_t unsigned long "unsigned long"; do + AC_TRY_COMPILE([ + #include + #include + ], + [ + $t len; + getpeername(0,0,&len); + ], + [ + kde_cv_socklen_t_equiv="$t" + break + ]) + done + AC_LANG_POP(C++) + ]) + AC_MSG_RESULT($kde_cv_socklen_t_equiv) + fi + AC_DEFINE_UNQUOTED(kde_socklen_t, $kde_cv_socklen_t_equiv, + [type to use in place of socklen_t if not defined]) + AC_DEFINE_UNQUOTED(ksize_t, $kde_cv_socklen_t_equiv, + [type to use in place of socklen_t if not defined (deprecated, use kde_socklen_t)]) +]) + +dnl This is a merge of some macros out of the gettext aclocal.m4 +dnl since we don't need anything, I took the things we need +dnl the copyright for them is: +dnl > +dnl Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +dnl This Makefile.in is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. +dnl > +dnl for this file it is relicensed under LGPL + +AC_DEFUN([AM_KDE_WITH_NLS], + [ + dnl If we use NLS figure out what method + + AM_PATH_PROG_WITH_TEST_KDE(MSGFMT, msgfmt, + [test -n "`$ac_dir/$ac_word --version 2>&1 | grep 'GNU gettext'`"], msgfmt) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + + if test -z "`$GMSGFMT --version 2>&1 | grep 'GNU gettext'`"; then + AC_MSG_RESULT([found msgfmt program is not GNU msgfmt; ignore it]) + GMSGFMT=":" + fi + MSGFMT=$GMSGFMT + AC_SUBST(GMSGFMT) + AC_SUBST(MSGFMT) + + AM_PATH_PROG_WITH_TEST_KDE(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is no GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext programs is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + AC_SUBST(XGETTEXT) + + ]) + +# Search path for a program which passes the given test. +# Ulrich Drepper , 1996. + +# serial 1 +# Stephan Kulow: I appended a _KDE against name conflicts + +dnl AM_PATH_PROG_WITH_TEST_KDE(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST_KDE], +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + + +# Check whether LC_MESSAGES is available in . +# Ulrich Drepper , 1995. + +# serial 1 + +AC_DEFUN([AM_LC_MESSAGES], + [if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, [Define if your locale.h file contains LC_MESSAGES]) + fi + fi]) + +dnl From Jim Meyering. +dnl FIXME: migrate into libit. + +AC_DEFUN([AM_FUNC_OBSTACK], +[AC_CACHE_CHECK([for obstacks], am_cv_func_obstack, + [AC_TRY_LINK([#include "obstack.h"], + [struct obstack *mem;obstack_free(mem,(char *) 0)], + am_cv_func_obstack=yes, + am_cv_func_obstack=no)]) + if test $am_cv_func_obstack = yes; then + AC_DEFINE(HAVE_OBSTACK) + else + LIBOBJS="$LIBOBJS obstack.o" + fi +]) + +dnl From Jim Meyering. Use this if you use the GNU error.[ch]. +dnl FIXME: Migrate into libit + +AC_DEFUN([AM_FUNC_ERROR_AT_LINE], +[AC_CACHE_CHECK([for error_at_line], am_cv_lib_error_at_line, + [AC_TRY_LINK([],[error_at_line(0, 0, "", 0, "");], + am_cv_lib_error_at_line=yes, + am_cv_lib_error_at_line=no)]) + if test $am_cv_lib_error_at_line = no; then + LIBOBJS="$LIBOBJS error.o" + fi + AC_SUBST(LIBOBJS)dnl +]) + +# Macro to add for using GNU gettext. +# Ulrich Drepper , 1995. + +# serial 1 +# Stephan Kulow: I put a KDE in it to avoid name conflicts + +AC_DEFUN([AM_KDE_GNU_GETTEXT], + [AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_REQUIRE([AC_TYPE_OFF_T])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + AC_REQUIRE([AM_KDE_WITH_NLS])dnl + AC_CHECK_HEADERS([limits.h locale.h nl_types.h string.h values.h alloca.h]) + AC_CHECK_FUNCS([getcwd munmap putenv setlocale strchr strcasecmp \ +__argz_count __argz_stringify __argz_next]) + + AC_MSG_CHECKING(for stpcpy) + AC_CACHE_VAL(kde_cv_func_stpcpy, + [ + kde_safe_cxxflags=$CXXFLAGS + CXXFLAGS="-Werror" + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([ + #include + ], + [ + char buffer[200]; + stpcpy(buffer, buffer); + ], + kde_cv_func_stpcpy=yes, + kde_cv_func_stpcpy=no) + AC_LANG_RESTORE + CXXFLAGS=$kde_safe_cxxflags + ]) + AC_MSG_RESULT($kde_cv_func_stpcpy) + if eval "test \"`echo $kde_cv_func_stpcpy`\" = yes"; then + AC_DEFINE(HAVE_STPCPY, 1, [Define if you have stpcpy]) + fi + + AM_LC_MESSAGES + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + ]) + +AC_DEFUN([AC_HAVE_XPM], + [AC_REQUIRE_CPP()dnl + AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + + test -z "$XPM_LDFLAGS" && XPM_LDFLAGS= + test -z "$XPM_INCLUDE" && XPM_INCLUDE= + + AC_ARG_WITH(xpm,AC_HELP_STRING([--without-xpm],[disable color pixmap XPM tests]), + xpm_test=$withval, xpm_test="yes") + if test "x$xpm_test" = xno; then + ac_cv_have_xpm=no + else + AC_MSG_CHECKING(for XPM) + AC_CACHE_VAL(ac_cv_have_xpm, + [ + ac_save_ldflags="$LDFLAGS" + ac_save_cflags="$CFLAGS" + if test "x$kde_use_qt_emb" != "xyes" && test "x$kde_use_qt_mac" != "xyes"; then + LDFLAGS="$LDFLAGS $X_LDFLAGS $USER_LDFLAGS $LDFLAGS $XPM_LDFLAGS $all_libraries -lXpm -lX11 -lXext $LIBZ $LIBSOCKET" + else + LDFLAGS="$LDFLAGS $X_LDFLAGS $USER_LDFLAGS $LDFLAGS $XPM_LDFLAGS $all_libraries -lXpm $LIBZ $LIBSOCKET" + fi + CFLAGS="$CFLAGS $X_INCLUDES $USER_INCLUDES" + test -n "$XPM_INCLUDE" && CFLAGS="-I$XPM_INCLUDE $CFLAGS" + AC_TRY_LINK([#include ],[], + ac_cv_have_xpm="yes",ac_cv_have_xpm="no") + LDFLAGS="$ac_save_ldflags" + CFLAGS="$ac_save_cflags" + ])dnl + + if test "$ac_cv_have_xpm" = no; then + AC_MSG_RESULT(no) + XPM_LDFLAGS="" + XPMINC="" + $2 + else + AC_DEFINE(HAVE_XPM, 1, [Define if you have XPM support]) + if test "$XPM_LDFLAGS" = ""; then + XPMLIB='-lXpm $(LIB_X11)' + else + XPMLIB="-L$XPM_LDFLAGS -lXpm "'$(LIB_X11)' + fi + if test "$XPM_INCLUDE" = ""; then + XPMINC="" + else + XPMINC="-I$XPM_INCLUDE" + fi + AC_MSG_RESULT(yes) + $1 + fi + fi + AC_SUBST(XPMINC) + AC_SUBST(XPMLIB) +]) + +AC_DEFUN([AC_HAVE_DPMS], + [AC_REQUIRE_CPP()dnl + AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + + test -z "$DPMS_LDFLAGS" && DPMS_LDFLAGS= + test -z "$DPMS_INCLUDE" && DPMS_INCLUDE= + DPMS_LIB= + + AC_ARG_WITH(dpms,AC_HELP_STRING([--without-dpms],[disable DPMS power saving]), + dpms_test=$withval, dpms_test="yes") + if test "x$dpms_test" = xno; then + ac_cv_have_dpms=no + else + AC_MSG_CHECKING(for DPMS) + dnl Note: ac_cv_have_dpms can be no, yes, or -lXdpms. + dnl 'yes' means DPMS_LIB="", '-lXdpms' means DPMS_LIB="-lXdpms". + AC_CACHE_VAL(ac_cv_have_dpms, + [ + if test "x$kde_use_qt_emb" = "xyes" || test "x$kde_use_qt_mac" = "xyes"; then + AC_MSG_RESULT(no) + ac_cv_have_dpms="no" + else + ac_save_ldflags="$LDFLAGS" + ac_save_cflags="$CFLAGS" + ac_save_libs="$LIBS" + LDFLAGS="$LDFLAGS $DPMS_LDFLAGS $all_libraries" + LIBS="-lX11 -lXext $LIBSOCKET" + CFLAGS="$CFLAGS $X_INCLUDES" + test -n "$DPMS_INCLUDE" && CFLAGS="-I$DPMS_INCLUDE $CFLAGS" + AC_TRY_LINK([ + #include + #include + #include + #include + int foo_test_dpms() + { return DPMSSetTimeouts( 0, 0, 0, 0 ); }],[], + ac_cv_have_dpms="yes", [ + LIBS="-lXdpms $LIBS" + AC_TRY_LINK([ + #include + #include + #include + #include + int foo_test_dpms() + { return DPMSSetTimeouts( 0, 0, 0, 0 ); }],[], + [ + ac_cv_have_dpms="-lXdpms" + ],ac_cv_have_dpms="no") + ]) + LDFLAGS="$ac_save_ldflags" + CFLAGS="$ac_save_cflags" + LIBS="$ac_save_libs" + fi + ])dnl + + if test "$ac_cv_have_dpms" = no; then + AC_MSG_RESULT(no) + DPMS_LDFLAGS="" + DPMSINC="" + $2 + else + AC_DEFINE(HAVE_DPMS, 1, [Define if you have DPMS support]) + if test "$ac_cv_have_dpms" = "-lXdpms"; then + DPMS_LIB="-lXdpms" + fi + if test "$DPMS_LDFLAGS" = ""; then + DPMSLIB="$DPMS_LIB "'$(LIB_X11)' + else + DPMSLIB="$DPMS_LDFLAGS $DPMS_LIB "'$(LIB_X11)' + fi + if test "$DPMS_INCLUDE" = ""; then + DPMSINC="" + else + DPMSINC="-I$DPMS_INCLUDE" + fi + AC_MSG_RESULT(yes) + $1 + fi + fi + ac_save_cflags="$CFLAGS" + CFLAGS="$CFLAGS $X_INCLUDES" + test -n "$DPMS_INCLUDE" && CFLAGS="-I$DPMS_INCLUDE $CFLAGS" + AH_TEMPLATE(HAVE_DPMSCAPABLE_PROTO, + [Define if you have the DPMSCapable prototype in ]) + AC_CHECK_DECL(DPMSCapable, + AC_DEFINE(HAVE_DPMSCAPABLE_PROTO),, + [#include + #include ]) + AH_TEMPLATE(HAVE_DPMSINFO_PROTO, + [Define if you have the DPMSInfo prototype in ]) + AC_CHECK_DECL(DPMSInfo, + AC_DEFINE(HAVE_DPMSINFO_PROTO),, + [#include + #include ]) + CFLAGS="$ac_save_cflags" + AC_SUBST(DPMSINC) + AC_SUBST(DPMSLIB) +]) + +AC_DEFUN([AC_HAVE_GL], + [AC_REQUIRE_CPP()dnl + AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + + test -z "$GL_LDFLAGS" && GL_LDFLAGS= + test -z "$GL_INCLUDE" && GL_INCLUDE= + + AC_ARG_WITH(gl,AC_HELP_STRING([--without-gl],[disable 3D GL modes]), + gl_test=$withval, gl_test="yes") + if test "x$kde_use_qt_emb" = "xyes"; then + # GL and Qt Embedded is a no-go for now. + ac_cv_have_gl=no + elif test "x$gl_test" = xno; then + ac_cv_have_gl=no + else + AC_MSG_CHECKING(for GL) + AC_CACHE_VAL(ac_cv_have_gl, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_ldflags=$LDFLAGS + ac_save_cxxflags=$CXXFLAGS + ac_save_libs=$LIBS + LDFLAGS="$LDFLAGS $GL_LDFLAGS $X_LDFLAGS $all_libraries" + LIBS="$LIBS -lGL -lGLU" + test "x$kde_use_qt_mac" != xyes && test "x$kde_use_qt_emb" != xyes && LIBS="$LIBS -lX11" + LIBS="$LIBS $LIB_XEXT -lm $LIBSOCKET" + CXXFLAGS="$CFLAGS $X_INCLUDES" + test -n "$GL_INCLUDE" && CFLAGS="-I$GL_INCLUDE $CFLAGS" + AC_TRY_LINK([#include +#include +], [], + ac_cv_have_gl="yes", ac_cv_have_gl="no") + AC_LANG_RESTORE + LDFLAGS=$ac_save_ldflags + CXXFLAGS=$ac_save_cxxflags + LIBS=$ac_save_libs + ])dnl + + if test "$ac_cv_have_gl" = "no"; then + AC_MSG_RESULT(no) + GL_LDFLAGS="" + GLINC="" + $2 + else + AC_DEFINE(HAVE_GL, 1, [Defines if you have GL (Mesa, OpenGL, ...)]) + if test "$GL_LDFLAGS" = ""; then + GLLIB='-lGLU -lGL $(LIB_X11)' + else + GLLIB="$GL_LDFLAGS -lGLU -lGL "'$(LIB_X11)' + fi + if test "$GL_INCLUDE" = ""; then + GLINC="" + else + GLINC="-I$GL_INCLUDE" + fi + AC_MSG_RESULT($ac_cv_have_gl) + $1 + fi + fi + AC_SUBST(GLINC) + AC_SUBST(GLLIB) +]) + + + dnl shadow password and PAM magic - maintained by ossi@kde.org + +AC_DEFUN([KDE_PAM], [ + AC_REQUIRE([KDE_CHECK_LIBDL]) + + want_pam= + AC_ARG_WITH(pam, + AC_HELP_STRING([--with-pam[=ARG]],[enable support for PAM: ARG=[yes|no|service name]]), + [ if test "x$withval" = "xyes"; then + want_pam=yes + pam_service=kde + elif test "x$withval" = "xno"; then + want_pam=no + else + want_pam=yes + pam_service=$withval + fi + ], [ pam_service=kde ]) + + use_pam= + PAMLIBS= + if test "x$want_pam" != xno; then + AC_CHECK_LIB(pam, pam_start, [ + AC_CHECK_HEADER(security/pam_appl.h, + [ pam_header=security/pam_appl.h ], + [ AC_CHECK_HEADER(pam/pam_appl.h, + [ pam_header=pam/pam_appl.h ], + [ + AC_MSG_WARN([PAM detected, but no headers found! +Make sure you have the necessary development packages installed.]) + ] + ) + ] + ) + ], , $LIBDL) + if test -z "$pam_header"; then + if test "x$want_pam" = xyes; then + AC_MSG_ERROR([--with-pam was specified, but cannot compile with PAM!]) + fi + else + AC_DEFINE(HAVE_PAM, 1, [Defines if you have PAM (Pluggable Authentication Modules)]) + PAMLIBS="$PAM_MISC_LIB -lpam $LIBDL" + use_pam=yes + + dnl darwin claims to be something special + if test "$pam_header" = "pam/pam_appl.h"; then + AC_DEFINE(HAVE_PAM_PAM_APPL_H, 1, [Define if your PAM headers are in pam/ instead of security/]) + fi + + dnl test whether struct pam_message is const (Linux) or not (Sun) + AC_MSG_CHECKING(for const pam_message) + AC_EGREP_HEADER([struct pam_message], $pam_header, + [ AC_EGREP_HEADER([const struct pam_message], $pam_header, + [AC_MSG_RESULT([const: Linux-type PAM])], + [AC_MSG_RESULT([nonconst: Sun-type PAM]) + AC_DEFINE(PAM_MESSAGE_NONCONST, 1, [Define if your PAM support takes non-const arguments (Solaris)])] + )], + [AC_MSG_RESULT([not found - assume const, Linux-type PAM])]) + fi + fi + + AC_SUBST(PAMLIBS) +]) + +dnl DEF_PAM_SERVICE(arg name, full name, define name) +AC_DEFUN([DEF_PAM_SERVICE], [ + AC_ARG_WITH($1-pam, + AC_HELP_STRING([--with-$1-pam=[val]],[override PAM service from --with-pam for $2]), + [ if test "x$use_pam" = xyes; then + $3_PAM_SERVICE=$withval + else + AC_MSG_ERROR([Cannot use use --with-$1-pam, as no PAM was detected. +You may want to enforce it by using --with-pam.]) + fi + ], + [ if test "x$use_pam" = xyes; then + $3_PAM_SERVICE="$pam_service" + fi + ]) + if test -n "$$3_PAM_SERVICE"; then + AC_MSG_RESULT([The PAM service used by $2 will be $$3_PAM_SERVICE]) + AC_DEFINE_UNQUOTED($3_PAM_SERVICE, "$$3_PAM_SERVICE", [The PAM service to be used by $2]) + fi + AC_SUBST($3_PAM_SERVICE) +]) + +AC_DEFUN([KDE_SHADOWPASSWD], [ + AC_REQUIRE([KDE_PAM]) + + AC_CHECK_LIB(shadow, getspent, + [ LIBSHADOW="-lshadow" + ac_use_shadow=yes + ], + [ dnl for UnixWare + AC_CHECK_LIB(gen, getspent, + [ LIBGEN="-lgen" + ac_use_shadow=yes + ], + [ AC_CHECK_FUNC(getspent, + [ ac_use_shadow=yes ], + [ ac_use_shadow=no ]) + ]) + ]) + AC_SUBST(LIBSHADOW) + AC_SUBST(LIBGEN) + + AC_MSG_CHECKING([for shadow passwords]) + + AC_ARG_WITH(shadow, + AC_HELP_STRING([--with-shadow],[If you want shadow password support]), + [ if test "x$withval" != "xno"; then + use_shadow=yes + else + use_shadow=no + fi + ], [ + use_shadow="$ac_use_shadow" + ]) + + if test "x$use_shadow" = xyes; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SHADOW, 1, [Define if you use shadow passwords]) + else + AC_MSG_RESULT(no) + LIBSHADOW= + LIBGEN= + fi + + dnl finally make the relevant binaries setuid root, if we have shadow passwds. + dnl this still applies, if we could use it indirectly through pam. + if test "x$use_shadow" = xyes || + ( test "x$use_pam" = xyes && test "x$ac_use_shadow" = xyes ); then + case $host in + *-*-freebsd* | *-*-netbsd* | *-*-openbsd*) + SETUIDFLAGS="-m 4755 -o root";; + *) + SETUIDFLAGS="-m 4755";; + esac + fi + AC_SUBST(SETUIDFLAGS) + +]) + +AC_DEFUN([KDE_PASSWDLIBS], [ + AC_REQUIRE([KDE_MISC_TESTS]) dnl for LIBCRYPT + AC_REQUIRE([KDE_PAM]) + AC_REQUIRE([KDE_SHADOWPASSWD]) + + if test "x$use_pam" = "xyes"; then + PASSWDLIBS="$PAMLIBS" + else + PASSWDLIBS="$LIBCRYPT $LIBSHADOW $LIBGEN" + fi + + dnl FreeBSD uses a shadow-like setup, where /etc/passwd holds the users, but + dnl /etc/master.passwd holds the actual passwords. /etc/master.passwd requires + dnl root to read, so kcheckpass needs to be root (even when using pam, since pam + dnl may need to read /etc/master.passwd). + case $host in + *-*-freebsd*) + SETUIDFLAGS="-m 4755 -o root" + ;; + *) + ;; + esac + + AC_SUBST(PASSWDLIBS) +]) + +AC_DEFUN([KDE_CHECK_LIBDL], +[ +AC_CHECK_LIB(dl, dlopen, [ +LIBDL="-ldl" +ac_cv_have_dlfcn=yes +]) + +AC_CHECK_LIB(dld, shl_unload, [ +LIBDL="-ldld" +ac_cv_have_shload=yes +]) + +AC_SUBST(LIBDL) +]) + +AC_DEFUN([KDE_CHECK_DLOPEN], +[ +KDE_CHECK_LIBDL +AC_CHECK_HEADERS(dlfcn.h dl.h) +if test "$ac_cv_header_dlfcn_h" = "no"; then + ac_cv_have_dlfcn=no +fi + +if test "$ac_cv_header_dl_h" = "no"; then + ac_cv_have_shload=no +fi + +dnl XXX why change enable_dlopen? its already set by autoconf's AC_ARG_ENABLE +dnl (MM) +AC_ARG_ENABLE(dlopen, +AC_HELP_STRING([--disable-dlopen],[link statically [default=no]]), +enable_dlopen=$enableval, +enable_dlopen=yes) + +# override the user's opinion, if we know it better ;) +if test "$ac_cv_have_dlfcn" = "no" && test "$ac_cv_have_shload" = "no"; then + enable_dlopen=no +fi + +if test "$ac_cv_have_dlfcn" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_DLFCN, 1, [Define if you have dlfcn]) +fi + +if test "$ac_cv_have_shload" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_SHLOAD, 1, [Define if you have shload]) +fi + +if test "$enable_dlopen" = no ; then + test -n "$1" && eval $1 +else + test -n "$2" && eval $2 +fi + +]) + +AC_DEFUN([KDE_CHECK_DYNAMIC_LOADING], +[ +KDE_CHECK_DLOPEN(libtool_enable_shared=yes, libtool_enable_static=no) +KDE_PROG_LIBTOOL +AC_MSG_CHECKING([dynamic loading]) +eval "`egrep '^build_libtool_libs=' libtool`" +if test "$build_libtool_libs" = "yes" && test "$enable_dlopen" = "yes"; then + dynamic_loading=yes + AC_DEFINE_UNQUOTED(HAVE_DYNAMIC_LOADING) +else + dynamic_loading=no +fi +AC_MSG_RESULT($dynamic_loading) +if test "$dynamic_loading" = "yes"; then + $1 +else + $2 +fi +]) + +AC_DEFUN([KDE_ADD_INCLUDES], +[ +if test -z "$1"; then + test_include="Pix.h" +else + test_include="$1" +fi + +AC_MSG_CHECKING([for libg++ ($test_include)]) + +AC_CACHE_VAL(kde_cv_libgpp_includes, +[ +kde_cv_libgpp_includes=no + + for ac_dir in \ + \ + /usr/include/g++ \ + /usr/include \ + /usr/unsupported/include \ + /opt/include \ + $extra_include \ + ; \ + do + if test -r "$ac_dir/$test_include"; then + kde_cv_libgpp_includes=$ac_dir + break + fi + done +]) + +AC_MSG_RESULT($kde_cv_libgpp_includes) +if test "$kde_cv_libgpp_includes" != "no"; then + all_includes="-I$kde_cv_libgpp_includes $all_includes $USER_INCLUDES" +fi +]) +]) + +AC_DEFUN([KDE_CHECK_LIBPTHREAD], +[ + dnl This code is here specifically to handle the + dnl various flavors of threading library on FreeBSD + dnl 4-, 5-, and 6-, and the (weird) rules around it. + dnl There may be an environment PTHREAD_LIBS that + dnl specifies what to use; otherwise, search for it. + dnl -pthread is special cased and unsets LIBPTHREAD + dnl below if found. + LIBPTHREAD="" + + if test -n "$PTHREAD_LIBS"; then + if test "x$PTHREAD_LIBS" = "x-pthread" ; then + LIBPTHREAD="PTHREAD" + else + PTHREAD_LIBS_save="$PTHREAD_LIBS" + PTHREAD_LIBS=`echo "$PTHREAD_LIBS_save" | sed -e 's,^-l,,g'` + AC_MSG_CHECKING([for pthread_create in $PTHREAD_LIBS]) + KDE_CHECK_LIB($PTHREAD_LIBS, pthread_create, [ + LIBPTHREAD="$PTHREAD_LIBS_save"]) + PTHREAD_LIBS="$PTHREAD_LIBS_save" + fi + fi + + dnl Is this test really needed, in the face of the Tru64 test below? + if test -z "$LIBPTHREAD"; then + AC_CHECK_LIB(pthread, pthread_create, [LIBPTHREAD="-lpthread"]) + fi + + dnl This is a special Tru64 check, see BR 76171 issue #18. + if test -z "$LIBPTHREAD" ; then + AC_MSG_CHECKING([for pthread_create in -lpthread]) + kde_safe_libs=$LIBS + LIBS="$LIBS -lpthread" + AC_TRY_LINK([#include ],[(void)pthread_create(0,0,0,0);],[ + AC_MSG_RESULT(yes) + LIBPTHREAD="-lpthread"],[ + AC_MSG_RESULT(no)]) + LIBS=$kde_safe_libs + fi + + dnl Un-special-case for FreeBSD. + if test "x$LIBPTHREAD" = "xPTHREAD" ; then + LIBPTHREAD="" + fi + + AC_SUBST(LIBPTHREAD) +]) + +AC_DEFUN([KDE_CHECK_PTHREAD_OPTION], +[ + USE_THREADS="" + if test -z "$LIBPTHREAD"; then + KDE_CHECK_COMPILER_FLAG(pthread, [USE_THREADS="-D_THREAD_SAFE -pthread"]) + fi + + AH_VERBATIM(__svr_define, [ +#if defined(__SVR4) && !defined(__svr4__) +#define __svr4__ 1 +#endif +]) + case $host_os in + solaris*) + KDE_CHECK_COMPILER_FLAG(mt, [USE_THREADS="-mt"]) + CPPFLAGS="$CPPFLAGS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -DUSE_SOLARIS -DSVR4" + ;; + freebsd*) + CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE $PTHREAD_CFLAGS" + ;; + aix*) + CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" + LIBPTHREAD="$LIBPTHREAD -lc_r" + ;; + linux*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" + if test "$CXX" = "KCC"; then + CXXFLAGS="$CXXFLAGS --thread_safe" + NOOPT_CXXFLAGS="$NOOPT_CXXFLAGS --thread_safe" + fi + ;; + *) + ;; + esac + AC_SUBST(USE_THREADS) + AC_SUBST(LIBPTHREAD) +]) + +AC_DEFUN([KDE_CHECK_THREADING], +[ + AC_REQUIRE([KDE_CHECK_LIBPTHREAD]) + AC_REQUIRE([KDE_CHECK_PTHREAD_OPTION]) + dnl default is yes if libpthread is found and no if no libpthread is available + if test -z "$LIBPTHREAD"; then + if test -z "$USE_THREADS"; then + kde_check_threading_default=no + else + kde_check_threading_default=yes + fi + else + kde_check_threading_default=yes + fi + AC_ARG_ENABLE(threading,AC_HELP_STRING([--disable-threading],[disables threading even if libpthread found]), + kde_use_threading=$enableval, kde_use_threading=$kde_check_threading_default) + if test "x$kde_use_threading" = "xyes"; then + AC_DEFINE(HAVE_LIBPTHREAD, 1, [Define if you have a working libpthread (will enable threaded code)]) + fi +]) + +AC_DEFUN([KDE_TRY_LINK_PYTHON], +[ +if test "$kde_python_link_found" = no; then + +if test "$1" = normal; then + AC_MSG_CHECKING(if a Python application links) +else + AC_MSG_CHECKING(if Python depends on $2) +fi + +AC_CACHE_VAL(kde_cv_try_link_python_$1, +[ +kde_save_cflags="$CFLAGS" +CFLAGS="$CFLAGS $PYTHONINC" +kde_save_libs="$LIBS" +LIBS="$LIBS $LIBPYTHON $2 $LIBDL $LIBSOCKET" +kde_save_ldflags="$LDFLAGS" +LDFLAGS="$LDFLAGS $PYTHONLIB" + +AC_TRY_LINK( +[ +#include +],[ + PySys_SetArgv(1, 0); +], + [kde_cv_try_link_python_$1=yes], + [kde_cv_try_link_python_$1=no] +) +CFLAGS="$kde_save_cflags" +LIBS="$kde_save_libs" +LDFLAGS="$kde_save_ldflags" +]) + +if test "$kde_cv_try_link_python_$1" = "yes"; then + AC_MSG_RESULT(yes) + kde_python_link_found=yes + if test ! "$1" = normal; then + LIBPYTHON="$LIBPYTHON $2" + fi + $3 +else + AC_MSG_RESULT(no) + $4 +fi + +fi + +]) + +AC_DEFUN([KDE_CHECK_PYTHON_DIR], +[ +AC_MSG_CHECKING([for Python directory]) + +AC_CACHE_VAL(kde_cv_pythondir, +[ + if test -z "$PYTHONDIR"; then + kde_cv_pythondir=/usr/local + else + kde_cv_pythondir="$PYTHONDIR" + fi +]) + +AC_ARG_WITH(pythondir, +AC_HELP_STRING([--with-pythondir=pythondir],[use python installed in pythondir]), +[ + ac_python_dir=$withval +], ac_python_dir=$kde_cv_pythondir +) + +AC_MSG_RESULT($ac_python_dir) +]) + +AC_DEFUN([KDE_CHECK_PYTHON_INTERN], +[ +AC_REQUIRE([KDE_CHECK_LIBDL]) +AC_REQUIRE([KDE_CHECK_LIBPTHREAD]) +AC_REQUIRE([KDE_CHECK_PYTHON_DIR]) + +if test -z "$1"; then + version="1.5" +else + version="$1" +fi + +AC_MSG_CHECKING([for Python$version]) + +python_incdirs="$ac_python_dir/include /usr/include /usr/local/include/ $kde_extra_includes" +AC_FIND_FILE(Python.h, $python_incdirs, python_incdir) +if test ! -r $python_incdir/Python.h; then + AC_FIND_FILE(python$version/Python.h, $python_incdirs, python_incdir) + python_incdir=$python_incdir/python$version + if test ! -r $python_incdir/Python.h; then + python_incdir=no + fi +fi + +PYTHONINC=-I$python_incdir + +python_libdirs="$ac_python_dir/lib$kdelibsuff /usr/lib$kdelibsuff /usr/local /usr/lib$kdelibsuff $kde_extra_libs" +AC_FIND_FILE(libpython$version.so, $python_libdirs, python_libdir) +if test ! -r $python_libdir/libpython$version.so; then + AC_FIND_FILE(libpython$version.a, $python_libdirs, python_libdir) + if test ! -r $python_libdir/libpython$version.a; then + AC_FIND_FILE(python$version/config/libpython$version.a, $python_libdirs, python_libdir) + python_libdir=$python_libdir/python$version/config + if test ! -r $python_libdir/libpython$version.a; then + python_libdir=no + fi + fi +fi + +PYTHONLIB=-L$python_libdir +kde_orig_LIBPYTHON=$LIBPYTHON +if test -z "$LIBPYTHON"; then + LIBPYTHON=-lpython$version +fi + +AC_FIND_FILE(python$version/copy.py, $python_libdirs, python_moddir) +python_moddir=$python_moddir/python$version +if test ! -r $python_moddir/copy.py; then + python_moddir=no +fi + +PYTHONMODDIR=$python_moddir + +AC_MSG_RESULT(header $python_incdir library $python_libdir modules $python_moddir) + +if test x$python_incdir = xno || test x$python_libdir = xno || test x$python_moddir = xno; then + LIBPYTHON=$kde_orig_LIBPYTHON + test "x$PYTHONLIB" = "x-Lno" && PYTHONLIB="" + test "x$PYTHONINC" = "x-Ino" && PYTHONINC="" + $2 +else + dnl Note: this test is very weak + kde_python_link_found=no + KDE_TRY_LINK_PYTHON(normal) + KDE_TRY_LINK_PYTHON(m, -lm) + KDE_TRY_LINK_PYTHON(pthread, $LIBPTHREAD) + KDE_TRY_LINK_PYTHON(tcl, -ltcl) + KDE_TRY_LINK_PYTHON(db2, -ldb2) + KDE_TRY_LINK_PYTHON(m_and_thread, [$LIBPTHREAD -lm]) + KDE_TRY_LINK_PYTHON(m_and_thread_and_util, [$LIBPTHREAD -lm -lutil]) + KDE_TRY_LINK_PYTHON(m_and_thread_and_db3, [$LIBPTHREAD -lm -ldb-3 -lutil]) + KDE_TRY_LINK_PYTHON(pthread_and_db3, [$LIBPTHREAD -ldb-3]) + KDE_TRY_LINK_PYTHON(m_and_thread_and_db, [$LIBPTHREAD -lm -ldb -ltermcap -lutil]) + KDE_TRY_LINK_PYTHON(pthread_and_dl, [$LIBPTHREAD $LIBDL -lutil -lreadline -lncurses -lm]) + KDE_TRY_LINK_PYTHON(pthread_and_panel_curses, [$LIBPTHREAD $LIBDL -lm -lpanel -lcurses]) + KDE_TRY_LINK_PYTHON(m_and_thread_and_db_special, [$LIBPTHREAD -lm -ldb -lutil], [], + [AC_MSG_WARN([it seems, Python depends on another library. + Please set LIBPYTHON to '-lpython$version -lotherlib' before calling configure to fix this + and contact the authors to let them know about this problem]) + ]) + + LIBPYTHON="$LIBPYTHON $LIBDL $LIBSOCKET" + AC_SUBST(PYTHONINC) + AC_SUBST(PYTHONLIB) + AC_SUBST(LIBPYTHON) + AC_SUBST(PYTHONMODDIR) + AC_DEFINE(HAVE_PYTHON, 1, [Define if you have the development files for python]) +fi + +]) + + +AC_DEFUN([KDE_CHECK_PYTHON], +[ + KDE_CHECK_PYTHON_INTERN("2.5", + [KDE_CHECK_PYTHON_INTERN("2.4", + [KDE_CHECK_PYTHON_INTERN("2.3", + [KDE_CHECK_PYTHON_INTERN("2.2", + [KDE_CHECK_PYTHON_INTERN("2.1", + [KDE_CHECK_PYTHON_INTERN("2.0", + [KDE_CHECK_PYTHON_INTERN($1, $2) ]) + ]) + ]) + ]) + ]) + ]) +]) + +AC_DEFUN([KDE_CHECK_STL], +[ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="`echo $CXXFLAGS | sed s/-fno-exceptions//`" + + AC_MSG_CHECKING([if C++ programs can be compiled]) + AC_CACHE_VAL(kde_cv_stl_works, + [ + AC_TRY_COMPILE([ +#include +using namespace std; +],[ + string astring="Hallo Welt."; + astring.erase(0, 6); // now astring is "Welt" + return 0; +], kde_cv_stl_works=yes, + kde_cv_stl_works=no) +]) + + AC_MSG_RESULT($kde_cv_stl_works) + + if test "$kde_cv_stl_works" = "yes"; then + # back compatible + AC_DEFINE_UNQUOTED(HAVE_SGI_STL, 1, [Define if you have a STL implementation by SGI]) + else + AC_MSG_ERROR([Your Installation isn't able to compile simple C++ programs. +Check config.log for details - if you're using a Linux distribution you might miss +a package named similar to libstdc++-dev.]) + fi + + CXXFLAGS="$ac_save_CXXFLAGS" + AC_LANG_RESTORE +]) + +AC_DEFUN([AC_FIND_QIMGIO], + [AC_REQUIRE([AC_FIND_JPEG]) +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_MSG_CHECKING([for qimgio]) +AC_CACHE_VAL(ac_cv_lib_qimgio, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +ac_save_LIBS="$LIBS" +ac_save_CXXFLAGS="$CXXFLAGS" +LIBS="$all_libraries -lqimgio -lpng -lz $LIBJPEG $LIBQT" +CXXFLAGS="$CXXFLAGS -I$qt_incdir $all_includes" +AC_TRY_RUN(dnl +[ +#include +#include +int main() { + QString t = "hallo"; + t.fill('t'); + qInitImageIO(); +} +], + ac_cv_lib_qimgio=yes, + ac_cv_lib_qimgio=no, + ac_cv_lib_qimgio=no) +LIBS="$ac_save_LIBS" +CXXFLAGS="$ac_save_CXXFLAGS" +AC_LANG_RESTORE +])dnl +if eval "test \"`echo $ac_cv_lib_qimgio`\" = yes"; then + LIBQIMGIO="-lqimgio -lpng -lz $LIBJPEG" + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_QIMGIO, 1, [Define if you have the Qt extension qimgio available]) + AC_SUBST(LIBQIMGIO) +else + AC_MSG_RESULT(not found) +fi +]) + +AC_DEFUN([AM_DISABLE_LIBRARIES], +[ + AC_PROVIDE([AM_ENABLE_STATIC]) + AC_PROVIDE([AM_ENABLE_SHARED]) + enable_static=no + enable_shared=yes +]) + + +AC_DEFUN([AC_CHECK_UTMP_FILE], +[ + AC_MSG_CHECKING([for utmp file]) + + AC_CACHE_VAL(kde_cv_utmp_file, + [ + kde_cv_utmp_file=no + + for ac_file in \ + \ + /var/run/utmp \ + /var/adm/utmp \ + /etc/utmp \ + ; \ + do + if test -r "$ac_file"; then + kde_cv_utmp_file=$ac_file + break + fi + done + ]) + + if test "$kde_cv_utmp_file" != "no"; then + AC_DEFINE_UNQUOTED(UTMP, "$kde_cv_utmp_file", [Define the file for utmp entries]) + $1 + AC_MSG_RESULT($kde_cv_utmp_file) + else + $2 + AC_MSG_RESULT([non found]) + fi +]) + + +AC_DEFUN([KDE_CREATE_SUBDIRSLIST], +[ + +DO_NOT_COMPILE="$DO_NOT_COMPILE CVS debian bsd-port admin" +TOPSUBDIRS="" + +if test ! -s $srcdir/subdirs; then + dnl Note: Makefile.common creates subdirs, so this is just a fallback + files=`cd $srcdir && ls -1` + dirs=`for i in $files; do if test -d $i; then echo $i; fi; done` + for i in $dirs; do + echo $i >> $srcdir/subdirs + done +fi + +ac_topsubdirs= +if test -s $srcdir/inst-apps; then + ac_topsubdirs="`cat $srcdir/inst-apps`" +elif test -s $srcdir/subdirs; then + ac_topsubdirs="`cat $srcdir/subdirs`" +fi + +for i in $ac_topsubdirs; do + AC_MSG_CHECKING([if $i should be compiled]) + if test -d $srcdir/$i; then + install_it="yes" + for j in $DO_NOT_COMPILE; do + if test $i = $j; then + install_it="no" + fi + done + else + install_it="no" + fi + AC_MSG_RESULT($install_it) + vari=`echo $i | sed -e 's,[[-+.@]],_,g'` + if test $install_it = "yes"; then + TOPSUBDIRS="$TOPSUBDIRS $i" + eval "$vari""_SUBDIR_included=yes" + else + eval "$vari""_SUBDIR_included=no" + fi +done + +AC_SUBST(TOPSUBDIRS) +]) + +AC_DEFUN([KDE_CHECK_NAMESPACES], +[ +AC_MSG_CHECKING(whether C++ compiler supports namespaces) +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +AC_TRY_COMPILE([ +], +[ +namespace Foo { + extern int i; + namespace Bar { + extern int i; + } +} + +int Foo::i = 0; +int Foo::Bar::i = 1; +],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_NAMESPACES) +], [ +AC_MSG_RESULT(no) +]) +AC_LANG_RESTORE +]) + +dnl ------------------------------------------------------------------------ +dnl Check for S_ISSOCK macro. Doesn't exist on Unix SCO. faure@kde.org +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([AC_CHECK_S_ISSOCK], +[ +AC_MSG_CHECKING(for S_ISSOCK) +AC_CACHE_VAL(ac_cv_have_s_issock, +[ +AC_TRY_LINK( +[ +#include +], +[ +struct stat buff; +int b = S_ISSOCK( buff.st_mode ); +], +ac_cv_have_s_issock=yes, +ac_cv_have_s_issock=no) +]) +AC_MSG_RESULT($ac_cv_have_s_issock) +if test "$ac_cv_have_s_issock" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_S_ISSOCK, 1, [Define if sys/stat.h declares S_ISSOCK.]) +fi + +AH_VERBATIM(_ISSOCK, +[ +#ifndef HAVE_S_ISSOCK +#define HAVE_S_ISSOCK +#define S_ISSOCK(mode) (1==0) +#endif +]) + +]) + +dnl ------------------------------------------------------------------------ +dnl Check for MAXPATHLEN macro, defines KDEMAXPATHLEN. faure@kde.org +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([AC_CHECK_KDEMAXPATHLEN], +[ +AC_MSG_CHECKING(for MAXPATHLEN) +AC_CACHE_VAL(ac_cv_maxpathlen, +[ +cat > conftest.$ac_ext < +#endif +#include +#include +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +KDE_HELLO MAXPATHLEN + +EOF + +ac_try="$ac_cpp conftest.$ac_ext 2>/dev/null | grep '^KDE_HELLO' >conftest.out" + +if AC_TRY_EVAL(ac_try) && test -s conftest.out; then + ac_cv_maxpathlen=`sed 's#KDE_HELLO ##' conftest.out` +else + ac_cv_maxpathlen=1024 +fi + +rm conftest.* + +]) +AC_MSG_RESULT($ac_cv_maxpathlen) +AC_DEFINE_UNQUOTED(KDEMAXPATHLEN,$ac_cv_maxpathlen, [Define a safe value for MAXPATHLEN] ) +]) + +AC_DEFUN([KDE_CHECK_HEADER], +[ + kde_safe_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $all_includes" + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_CHECK_HEADER([$1], [$2], [$3], [$4]) + AC_LANG_RESTORE + CPPFLAGS=$kde_safe_cppflags +]) + +AC_DEFUN([KDE_CHECK_HEADERS], +[ + AH_CHECK_HEADERS([$1]) + AC_LANG_SAVE + kde_safe_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $all_includes" + AC_LANG_CPLUSPLUS + AC_CHECK_HEADERS([$1], [$2], [$3], [$4]) + CPPFLAGS=$kde_safe_cppflags + AC_LANG_RESTORE +]) + +AC_DEFUN([KDE_FAST_CONFIGURE], +[ + dnl makes configure fast (needs perl) + AC_ARG_ENABLE(fast-perl, AC_HELP_STRING([--disable-fast-perl],[disable fast Makefile generation (needs perl)]), + with_fast_perl=$enableval, with_fast_perl=yes) +]) + +AC_DEFUN([KDE_CONF_FILES], +[ + val= + if test -f $srcdir/configure.files ; then + val=`sed -e 's%^%\$(top_srcdir)/%' $srcdir/configure.files` + fi + CONF_FILES= + if test -n "$val" ; then + for i in $val ; do + CONF_FILES="$CONF_FILES $i" + done + fi + AC_SUBST(CONF_FILES) +])dnl + +dnl This sets the prefix, for arts and kdelibs +dnl Do NOT use in any other module. +dnl It only looks at --prefix, KDEDIR and falls back to /usr/local/kde +AC_DEFUN([KDE_SET_PREFIX_CORE], +[ + unset CDPATH + dnl make $KDEDIR the default for the installation + AC_PREFIX_DEFAULT(${KDEDIR:-/usr/local/kde}) + + if test "x$prefix" = "xNONE"; then + prefix=$ac_default_prefix + ac_configure_args="$ac_configure_args --prefix=$prefix" + fi + # And delete superfluous '/' to make compares easier + prefix=`echo "$prefix" | sed 's,//*,/,g' | sed -e 's,/$,,'` + exec_prefix=`echo "$exec_prefix" | sed 's,//*,/,g' | sed -e 's,/$,,'` + + kde_libs_prefix='$(prefix)' + kde_libs_htmldir='$(kde_htmldir)' + AC_SUBST(kde_libs_prefix) + AC_SUBST(kde_libs_htmldir) + KDE_FAST_CONFIGURE + KDE_CONF_FILES +]) + + +AC_DEFUN([KDE_SET_PREFIX], +[ + unset CDPATH + dnl We can't give real code to that macro, only a value. + dnl It only matters for --help, since we set the prefix in this function anyway. + AC_PREFIX_DEFAULT(${KDEDIR:-the kde prefix}) + + KDE_SET_DEFAULT_BINDIRS + if test "x$prefix" = "xNONE"; then + dnl no prefix given: look for kde-config in the PATH and deduce the prefix from it + KDE_FIND_PATH(kde-config, KDECONFIG, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(kde-config)], [], prepend) + else + dnl prefix given: look for kde-config, preferrably in prefix, otherwise in PATH + kde_save_PATH="$PATH" + PATH="$exec_prefix/bin:$prefix/bin:$PATH" + KDE_FIND_PATH(kde-config, KDECONFIG, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(kde-config)], [], prepend) + PATH="$kde_save_PATH" + fi + + kde_libs_prefix=`$KDECONFIG --prefix` + if test -z "$kde_libs_prefix" || test ! -x "$kde_libs_prefix"; then + AC_MSG_ERROR([$KDECONFIG --prefix outputed the non existant prefix '$kde_libs_prefix' for kdelibs. + This means it has been moved since you installed it. + This won't work. Please recompile kdelibs for the new prefix. + ]) + fi + kde_libs_htmldir=`$KDECONFIG --install html --expandvars` + + AC_MSG_CHECKING([where to install]) + if test "x$prefix" = "xNONE"; then + prefix=$kde_libs_prefix + AC_MSG_RESULT([$prefix (as returned by kde-config)]) + else + dnl --prefix was given. Compare prefixes and warn (in configure.in.bot.end) if different + given_prefix=$prefix + AC_MSG_RESULT([$prefix (as requested)]) + fi + + # And delete superfluous '/' to make compares easier + prefix=`echo "$prefix" | sed 's,//*,/,g' | sed -e 's,/$,,'` + exec_prefix=`echo "$exec_prefix" | sed 's,//*,/,g' | sed -e 's,/$,,'` + given_prefix=`echo "$given_prefix" | sed 's,//*,/,g' | sed -e 's,/$,,'` + + AC_SUBST(KDECONFIG) + AC_SUBST(kde_libs_prefix) + AC_SUBST(kde_libs_htmldir) + + KDE_FAST_CONFIGURE + KDE_CONF_FILES +]) + +pushdef([AC_PROG_INSTALL], +[ + dnl our own version, testing for a -p flag + popdef([AC_PROG_INSTALL]) + dnl as AC_PROG_INSTALL works as it works we first have + dnl to save if the user didn't specify INSTALL, as the + dnl autoconf one overwrites INSTALL and we have no chance to find + dnl out afterwards + test -n "$INSTALL" && kde_save_INSTALL_given=$INSTALL + test -n "$INSTALL_PROGRAM" && kde_save_INSTALL_PROGRAM_given=$INSTALL_PROGRAM + test -n "$INSTALL_SCRIPT" && kde_save_INSTALL_SCRIPT_given=$INSTALL_SCRIPT + AC_PROG_INSTALL + + if test -z "$kde_save_INSTALL_given" ; then + # OK, user hasn't given any INSTALL, autoconf found one for us + # now we test, if it supports the -p flag + AC_MSG_CHECKING(for -p flag to install) + rm -f confinst.$$.* > /dev/null 2>&1 + echo "Testtest" > confinst.$$.orig + ac_res=no + if ${INSTALL} -p confinst.$$.orig confinst.$$.new > /dev/null 2>&1 ; then + if test -f confinst.$$.new ; then + # OK, -p seems to do no harm to install + INSTALL="${INSTALL} -p" + ac_res=yes + fi + fi + rm -f confinst.$$.* + AC_MSG_RESULT($ac_res) + fi + dnl the following tries to resolve some signs and wonders coming up + dnl with different autoconf/automake versions + dnl e.g.: + dnl *automake 1.4 install-strip sets A_M_INSTALL_PROGRAM_FLAGS to -s + dnl and has INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(A_M_INSTALL_PROGRAM_FLAGS) + dnl it header-vars.am, so there the actual INSTALL_PROGRAM gets the -s + dnl *automake 1.4a (and above) use INSTALL_STRIP_FLAG and only has + dnl INSTALL_PROGRAM = @INSTALL_PROGRAM@ there, but changes the + dnl install-@DIR@PROGRAMS targets to explicitly use that flag + dnl *autoconf 2.13 is dumb, and thinks it can use INSTALL_PROGRAM as + dnl INSTALL_SCRIPT, which breaks with automake <= 1.4 + dnl *autoconf >2.13 (since 10.Apr 1999) has not that failure + dnl *sometimes KDE does not use the install-@DIR@PROGRAM targets from + dnl automake (due to broken Makefile.am or whatever) to install programs, + dnl and so does not see the -s flag in automake > 1.4 + dnl to clean up that mess we: + dnl +set INSTALL_PROGRAM to use INSTALL_STRIP_FLAG + dnl which cleans KDE's program with automake > 1.4; + dnl +set INSTALL_SCRIPT to only use INSTALL, to clean up autoconf's problems + dnl with automake<=1.4 + dnl note that dues to this sometimes two '-s' flags are used (if KDE + dnl properly uses install-@DIR@PROGRAMS, but I don't care + dnl + dnl And to all this comes, that I even can't write in comments variable + dnl names used by automake, because it is so stupid to think I wanted to + dnl _use_ them, therefor I have written A_M_... instead of AM_ + dnl hmm, I wanted to say something ... ahh yes: Arghhh. + + if test -z "$kde_save_INSTALL_PROGRAM_given" ; then + INSTALL_PROGRAM='${INSTALL} $(INSTALL_STRIP_FLAG)' + fi + if test -z "$kde_save_INSTALL_SCRIPT_given" ; then + INSTALL_SCRIPT='${INSTALL}' + fi +])dnl + +AC_DEFUN([KDE_LANG_CPLUSPLUS], +[AC_LANG_CPLUSPLUS +ac_link='rm -rf SunWS_cache; ${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC' +pushdef([AC_LANG_CPLUSPLUS], [popdef([AC_LANG_CPLUSPLUS]) KDE_LANG_CPLUSPLUS]) +]) + +pushdef([AC_LANG_CPLUSPLUS], +[popdef([AC_LANG_CPLUSPLUS]) +KDE_LANG_CPLUSPLUS +]) + +AC_DEFUN([KDE_CHECK_LONG_LONG], +[ +AC_MSG_CHECKING(for long long) +AC_CACHE_VAL(kde_cv_c_long_long, +[ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_LINK([], [ + long long foo = 0; + foo = foo+1; + ], + kde_cv_c_long_long=yes, kde_cv_c_long_long=no) + AC_LANG_RESTORE +]) +AC_MSG_RESULT($kde_cv_c_long_long) +if test "$kde_cv_c_long_long" = yes; then + AC_DEFINE(HAVE_LONG_LONG, 1, [Define if you have long long as datatype]) +fi +]) + +AC_DEFUN([KDE_CHECK_LIB], +[ + kde_save_LDFLAGS="$LDFLAGS" + dnl AC_CHECK_LIB modifies LIBS, so save it here + kde_save_LIBS="$LIBS" + LDFLAGS="$LDFLAGS $all_libraries" + case $host_os in + aix*) LDFLAGS="-brtl $LDFLAGS" + test "$GCC" = yes && LDFLAGS="-Wl,$LDFLAGS" + ;; + esac + AC_CHECK_LIB($1, $2, $3, $4, $5) + LDFLAGS="$kde_save_LDFLAGS" + LIBS="$kde_save_LIBS" +]) + +AC_DEFUN([KDE_JAVA_PREFIX], +[ + dir=`dirname "$1"` + base=`basename "$1"` + list=`ls -1 $dir 2> /dev/null` + for entry in $list; do + if test -d $dir/$entry/bin; then + case $entry in + $base) + javadirs="$javadirs $dir/$entry/bin" + ;; + esac + elif test -d $dir/$entry/jre/bin; then + case $entry in + $base) + javadirs="$javadirs $dir/$entry/jre/bin" + ;; + esac + fi + done +]) + +dnl KDE_CHEC_JAVA_DIR(onlyjre) +AC_DEFUN([KDE_CHECK_JAVA_DIR], +[ + +AC_ARG_WITH(java, +AC_HELP_STRING([--with-java=javadir],[use java installed in javadir, --without-java disables]), +[ ac_java_dir=$withval +], ac_java_dir="" +) + +AC_MSG_CHECKING([for Java]) + +dnl at this point ac_java_dir is either a dir, 'no' to disable, or '' to say look in $PATH +if test "x$ac_java_dir" = "xno"; then + kde_java_bindir=no + kde_java_includedir=no + kde_java_libjvmdir=no + kde_java_libgcjdir=no + kde_java_libhpidir=no +else + if test "x$ac_java_dir" = "x"; then + + + dnl No option set -> collect list of candidate paths + if test -n "$JAVA_HOME"; then + KDE_JAVA_PREFIX($JAVA_HOME) + fi + KDE_JAVA_PREFIX(/usr/j2se) + KDE_JAVA_PREFIX(/usr/lib/j2se) + KDE_JAVA_PREFIX(/usr/j*dk*) + KDE_JAVA_PREFIX(/usr/lib/j*dk*) + KDE_JAVA_PREFIX(/opt/j*sdk*) + KDE_JAVA_PREFIX(/usr/lib/java*) + KDE_JAVA_PREFIX(/usr/java*) + KDE_JAVA_PREFIX(/usr/java/j*dk*) + KDE_JAVA_PREFIX(/usr/java/j*re*) + KDE_JAVA_PREFIX(/usr/lib/SunJava2*) + KDE_JAVA_PREFIX(/usr/lib/SunJava*) + KDE_JAVA_PREFIX(/usr/lib/IBMJava2*) + KDE_JAVA_PREFIX(/usr/lib/IBMJava*) + KDE_JAVA_PREFIX(/opt/java*) + + kde_cv_path="NONE" + kde_save_IFS=$IFS + IFS=':' + for dir in $PATH; do + if test -d "$dir"; then + javadirs="$javadirs $dir" + fi + done + IFS=$kde_save_IFS + jredirs= + + dnl Now javadirs contains a list of paths that exist, all ending with bin/ + for dir in $javadirs; do + dnl Check for the java executable + if test -x "$dir/java"; then + sane_path=$(cd $dir; /bin/pwd) + dnl And also check for a libjvm.so somewhere under there + dnl Since we have to go to the parent dir, /usr/bin is excluded, /usr is too big. + if test "$sane_path" != "/usr/bin"; then + libjvmdir=`find $dir/.. -name libjvm.so | sed 's,libjvm.so,,'|head -n 1` + if test ! -f $libjvmdir/libjvm.so; then continue; fi + jredirs="$jredirs $dir" + fi + fi + done + + dnl Now jredirs contains a reduced list, of paths where both java and ../**/libjvm.so was found + JAVAC= + JAVA= + kde_java_bindir=no + for dir in $jredirs; do + JAVA="$dir/java" + kde_java_bindir=$dir + if test -x "$dir/javac"; then + JAVAC="$dir/javac" + break + fi + done + + if test -n "$JAVAC"; then + dnl this substitution might not work - well, we test for jni.h below + kde_java_includedir=`echo $JAVAC | sed -e 's,bin/javac$,include/,'` + else + kde_java_includedir=no + fi + else + dnl config option set + kde_java_bindir=$ac_java_dir/bin + if test -x $ac_java_dir/bin/java && test ! -x $ac_java_dir/bin/javac; then + kde_java_includedir=no + else + kde_java_includedir=$ac_java_dir/include + fi + fi +fi + +dnl At this point kde_java_bindir and kde_java_includedir are either set or "no" +if test "x$kde_java_bindir" != "xno"; then + + dnl Look for libjvm.so + kde_java_libjvmdir=`find $kde_java_bindir/.. -name libjvm.so | sed 's,libjvm.so,,'|head -n 1` + dnl Look for libgcj.so + kde_java_libgcjdir=`find $kde_java_bindir/.. -name libgcj.so | sed 's,libgcj.so,,'|head -n 1` + dnl Look for libhpi.so and avoid green threads + kde_java_libhpidir=`find $kde_java_bindir/.. -name libhpi.so | grep -v green | sed 's,libhpi.so,,' | head -n 1` + + dnl Now check everything's fine under there + dnl the include dir is our flag for having the JDK + if test -d "$kde_java_includedir"; then + if test ! -x "$kde_java_bindir/javac"; then + AC_MSG_ERROR([javac not found under $kde_java_bindir - it seems you passed a wrong --with-java.]) + fi + if test ! -x "$kde_java_bindir/javah"; then + AC_MSG_ERROR([javah not found under $kde_java_bindir. javac was found though! Use --with-java or --without-java.]) + fi + if test ! -x "$kde_java_bindir/jar"; then + AC_MSG_ERROR([jar not found under $kde_java_bindir. javac was found though! Use --with-java or --without-java.]) + fi + if test ! -r "$kde_java_includedir/jni.h"; then + AC_MSG_ERROR([jni.h not found under $kde_java_includedir. Use --with-java or --without-java.]) + fi + + jni_includes="-I$kde_java_includedir" + dnl Strange thing, jni.h requires jni_md.h which is under genunix here.. + dnl and under linux here.. + + dnl not needed for gcj + + if test "x$kde_java_libgcjdir" = "x"; then + test -d "$kde_java_includedir/linux" && jni_includes="$jni_includes -I$kde_java_includedir/linux" + test -d "$kde_java_includedir/solaris" && jni_includes="$jni_includes -I$kde_java_includedir/solaris" + test -d "$kde_java_includedir/genunix" && jni_includes="$jni_includes -I$kde_java_includedir/genunix" + fi + + else + JAVAC= + jni_includes= + fi + + if test "x$kde_java_libgcjdir" = "x"; then + if test ! -r "$kde_java_libjvmdir/libjvm.so"; then + AC_MSG_ERROR([libjvm.so not found under $kde_java_libjvmdir. Use --without-java.]) + fi + else + if test ! -r "$kde_java_libgcjdir/libgcj.so"; then + AC_MSG_ERROR([libgcj.so not found under $kde_java_libgcjdir. Use --without-java.]) + fi + fi + + if test ! -x "$kde_java_bindir/java"; then + AC_MSG_ERROR([java not found under $kde_java_bindir. javac was found though! Use --with-java or --without-java.]) + fi + + dnl not needed for gcj compile + + if test "x$kde_java_libgcjdir" = "x"; then + if test ! -r "$kde_java_libhpidir/libhpi.so"; then + AC_MSG_ERROR([libhpi.so not found under $kde_java_libhpidir. Use --without-java.]) + fi + fi + + if test -n "$jni_includes"; then + dnl Check for JNI version + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_cxxflags_safe="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $all_includes $jni_includes" + + AC_TRY_COMPILE([ + #include + ], + [ + #ifndef JNI_VERSION_1_2 + Syntax Error + #endif + ],[ kde_jni_works=yes ], + [ kde_jni_works=no ]) + + if test $kde_jni_works = no; then + AC_MSG_ERROR([Incorrect version of $kde_java_includedir/jni.h. + You need to have Java Development Kit (JDK) version 1.2. + + Use --with-java to specify another location. + Use --without-java to configure without java support. + Or download a newer JDK and try again. + See e.g. http://java.sun.com/products/jdk/1.2 ]) + fi + + CXXFLAGS="$ac_cxxflags_safe" + AC_LANG_RESTORE + + dnl All tests ok, inform and subst the variables + + JAVAC=$kde_java_bindir/javac + JAVAH=$kde_java_bindir/javah + JAR=$kde_java_bindir/jar + AC_DEFINE_UNQUOTED(PATH_JAVA, "$kde_java_bindir/java", [Define where your java executable is]) + if test "x$kde_java_libgcjdir" = "x"; then + JVMLIBS="-L$kde_java_libjvmdir -ljvm -L$kde_java_libhpidir -lhpi" + else + JVMLIBS="-L$kde_java_libgcjdir -lgcj" + fi + AC_MSG_RESULT([java JDK in $kde_java_bindir]) + + else + AC_DEFINE_UNQUOTED(PATH_JAVA, "$kde_java_bindir/java", [Define where your java executable is]) + AC_MSG_RESULT([java JRE in $kde_java_bindir]) + fi +elif test -d "/Library/Java/Home"; then + kde_java_bindir="/Library/Java/Home/bin" + jni_includes="-I/Library/Java/Home/include" + + JAVAC=$kde_java_bindir/javac + JAVAH=$kde_java_bindir/javah + JAR=$kde_java_bindir/jar + JVMLIBS="-Wl,-framework,JavaVM" + + AC_DEFINE_UNQUOTED(PATH_JAVA, "$kde_java_bindir/java", [Define where your java executable is]) + AC_MSG_RESULT([Apple Java Framework]) +else + AC_MSG_RESULT([none found]) +fi + +AC_SUBST(JAVAC) +AC_SUBST(JAVAH) +AC_SUBST(JAR) +AC_SUBST(JVMLIBS) +AC_SUBST(jni_includes) + +# for backward compat +kde_cv_java_includedir=$kde_java_includedir +kde_cv_java_bindir=$kde_java_bindir +]) + +dnl this is a redefinition of autoconf 2.5x's AC_FOREACH. +dnl When the argument list becomes big, as in KDE for AC_OUTPUT in +dnl big packages, m4_foreach is dog-slow. So use our own version of +dnl it. (matz@kde.org) +m4_define([mm_foreach], +[m4_pushdef([$1])_mm_foreach($@)m4_popdef([$1])]) +m4_define([mm_car], [[$1]]) +m4_define([mm_car2], [[$@]]) +m4_define([_mm_foreach], +[m4_if(m4_quote($2), [], [], + [m4_define([$1], mm_car($2))$3[]_mm_foreach([$1], + mm_car2(m4_shift($2)), + [$3])])]) +m4_define([AC_FOREACH], +[mm_foreach([$1], m4_split(m4_normalize([$2])), [$3])]) + +AC_DEFUN([KDE_NEED_FLEX], +[ +kde_libs_safe=$LIBS +LIBS="$LIBS $USER_LDFLAGS" +AM_PROG_LEX +LIBS=$kde_libs_safe +if test -z "$LEXLIB"; then + AC_MSG_ERROR([You need to have flex installed.]) +fi +AC_SUBST(LEXLIB) +]) + +AC_DEFUN([AC_PATH_QTOPIA], +[ + dnl TODO: use AC_CACHE_VAL + + if test -z "$1"; then + qtopia_minver_maj=1 + qtopia_minver_min=5 + qtopia_minver_pat=0 + else + qtopia_minver_maj=`echo "$1" | sed -e "s/^\(.*\)\..*\..*$/\1/"` + qtopia_minver_min=`echo "$1" | sed -e "s/^.*\.\(.*\)\..*$/\1/"` + qtopia_minver_pat=`echo "$1" | sed -e "s/^.*\..*\.\(.*\)$/\1/"` + fi + + qtopia_minver="$qtopia_minver_maj$qtopia_minver_min$qtopia_minver_pat" + qtopia_minverstr="$qtopia_minver_maj.$qtopia_minver_min.$qtopia_minver_pat" + + AC_REQUIRE([AC_PATH_QT]) + + AC_MSG_CHECKING([for Qtopia]) + + LIB_QTOPIA="-lqpe" + AC_SUBST(LIB_QTOPIA) + + kde_qtopia_dirs="$QPEDIR /opt/Qtopia" + + ac_qtopia_incdir=NO + + AC_ARG_WITH(qtopia-dir, + AC_HELP_STRING([--with-qtopia-dir=DIR],[where the root of Qtopia is installed]), + [ ac_qtopia_incdir="$withval"/include] ) + + qtopia_incdirs="" + for dir in $kde_qtopia_dirs; do + qtopia_incdirs="$qtopia_incdirs $dir/include" + done + + if test ! "$ac_qtopia_incdir" = "NO"; then + qtopia_incdirs="$ac_qtopia_incdir $qtopia_incdirs" + fi + + qtopia_incdir="" + AC_FIND_FILE(qpe/qpeapplication.h, $qtopia_incdirs, qtopia_incdir) + ac_qtopia_incdir="$qtopia_incdir" + + if test -z "$qtopia_incdir"; then + AC_MSG_ERROR([Cannot find Qtopia headers. Please check your installation.]) + fi + + qtopia_ver_maj=`cat $qtopia_incdir/qpe/version.h | sed -n -e 's,.*QPE_VERSION "\(.*\)\..*\..*".*,\1,p'`; + qtopia_ver_min=`cat $qtopia_incdir/qpe/version.h | sed -n -e 's,.*QPE_VERSION ".*\.\(.*\)\..*".*,\1,p'`; + qtopia_ver_pat=`cat $qtopia_incdir/qpe/version.h | sed -n -e 's,.*QPE_VERSION ".*\..*\.\(.*\)".*,\1,p'`; + + qtopia_ver="$qtopia_ver_maj$qtopia_ver_min$qtopia_ver_pat" + qtopia_verstr="$qtopia_ver_maj.$qtopia_ver_min.$qtopia_ver_pat" + if test "$qtopia_ver" -lt "$qtopia_minver"; then + AC_MSG_ERROR([found Qtopia version $qtopia_verstr but version $qtopia_minverstr +is required.]) + fi + + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + ac_cxxflags_safe="$CXXFLAGS" + ac_ldflags_safe="$LDFLAGS" + ac_libs_safe="$LIBS" + + CXXFLAGS="$CXXFLAGS -I$qtopia_incdir $all_includes" + LDFLAGS="$LDFLAGS $QT_LDFLAGS $all_libraries $USER_LDFLAGS $KDE_MT_LDFLAGS" + LIBS="$LIBS $LIB_QTOPIA $LIBQT" + + cat > conftest.$ac_ext < +#include + +int main( int argc, char **argv ) +{ + QPEApplication app( argc, argv ); + return 0; +} +EOF + + if AC_TRY_EVAL(ac_link) && test -s conftest; then + rm -f conftest* + else + rm -f conftest* + AC_MSG_ERROR([Cannot link small Qtopia Application. For more details look at +the end of config.log]) + fi + + CXXFLAGS="$ac_cxxflags_safe" + LDFLAGS="$ac_ldflags_safe" + LIBS="$ac_libs_safe" + + AC_LANG_RESTORE + + QTOPIA_INCLUDES="-I$qtopia_incdir" + AC_SUBST(QTOPIA_INCLUDES) + + AC_MSG_RESULT([found version $qtopia_verstr with headers at $qtopia_incdir]) +]) + + +AC_DEFUN([KDE_INIT_DOXYGEN], +[ +AC_MSG_CHECKING([for Qt docs]) +kde_qtdir= +if test "${with_qt_dir+set}" = set; then + kde_qtdir="$with_qt_dir" +fi + +AC_FIND_FILE(qsql.html, [ $kde_qtdir/doc/html $QTDIR/doc/html /usr/share/doc/packages/qt3/html /usr/lib/qt/doc /usr/lib/qt3/doc /usr/lib/qt3/doc/html /usr/doc/qt3/html /usr/doc/qt3 /usr/share/doc/qt3-doc /usr/share/qt3/doc/html /usr/X11R6/share/doc/qt/html ], QTDOCDIR) +AC_MSG_RESULT($QTDOCDIR) + +AC_SUBST(QTDOCDIR) + +KDE_FIND_PATH(dot, DOT, [], []) +if test -n "$DOT"; then + KDE_HAVE_DOT="YES" +else + KDE_HAVE_DOT="NO" +fi +AC_SUBST(KDE_HAVE_DOT) +KDE_FIND_PATH(doxygen, DOXYGEN, [], []) +AC_SUBST(DOXYGEN) + +DOXYGEN_PROJECT_NAME="$1" +DOXYGEN_PROJECT_NUMBER="$2" +AC_SUBST(DOXYGEN_PROJECT_NAME) +AC_SUBST(DOXYGEN_PROJECT_NUMBER) + +KDE_HAS_DOXYGEN=no +if test -n "$DOXYGEN" && test -x "$DOXYGEN" && test -f $QTDOCDIR/qsql.html; then + KDE_HAS_DOXYGEN=yes +fi +AC_SUBST(KDE_HAS_DOXYGEN) + +]) + + +AC_DEFUN([AC_FIND_BZIP2], +[ +AC_MSG_CHECKING([for bzDecompress in libbz2]) +AC_CACHE_VAL(ac_cv_lib_bzip2, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +kde_save_LIBS="$LIBS" +LIBS="$all_libraries $USER_LDFLAGS -lbz2 $LIBSOCKET" +kde_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $all_includes $USER_INCLUDES" +AC_TRY_LINK(dnl +[ +#define BZ_NO_STDIO +#include +], + [ bz_stream s; (void) bzDecompress(&s); ], + eval "ac_cv_lib_bzip2='-lbz2'", + eval "ac_cv_lib_bzip2=no") +LIBS="$kde_save_LIBS" +CXXFLAGS="$kde_save_CXXFLAGS" +AC_LANG_RESTORE +])dnl +AC_MSG_RESULT($ac_cv_lib_bzip2) + +if test ! "$ac_cv_lib_bzip2" = no; then + BZIP2DIR=bzip2 + + LIBBZ2="$ac_cv_lib_bzip2" + AC_SUBST(LIBBZ2) + +else + + cxx_shared_flag= + ld_shared_flag= + KDE_CHECK_COMPILER_FLAG(shared, [ + ld_shared_flag="-shared" + ]) + KDE_CHECK_COMPILER_FLAG(fPIC, [ + cxx_shared_flag="-fPIC" + ]) + + AC_MSG_CHECKING([for BZ2_bzDecompress in (shared) libbz2]) + AC_CACHE_VAL(ac_cv_lib_bzip2_prefix, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + kde_save_LIBS="$LIBS" + LIBS="$all_libraries $USER_LDFLAGS $ld_shared_flag -lbz2 $LIBSOCKET" + kde_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CFLAGS $cxx_shared_flag $all_includes $USER_INCLUDES" + + AC_TRY_LINK(dnl + [ + #define BZ_NO_STDIO + #include + ], + [ bz_stream s; (void) BZ2_bzDecompress(&s); ], + eval "ac_cv_lib_bzip2_prefix='-lbz2'", + eval "ac_cv_lib_bzip2_prefix=no") + LIBS="$kde_save_LIBS" + CXXFLAGS="$kde_save_CXXFLAGS" + AC_LANG_RESTORE + ])dnl + + AC_MSG_RESULT($ac_cv_lib_bzip2_prefix) + + if test ! "$ac_cv_lib_bzip2_prefix" = no; then + BZIP2DIR=bzip2 + + LIBBZ2="$ac_cv_lib_bzip2_prefix" + AC_SUBST(LIBBZ2) + + AC_DEFINE(NEED_BZ2_PREFIX, 1, [Define if the libbz2 functions need the BZ2_ prefix]) + dnl else, we just ignore this + fi + +fi +AM_CONDITIONAL(include_BZIP2, test -n "$BZIP2DIR") +]) + +dnl ------------------------------------------------------------------------ +dnl Try to find the SSL headers and libraries. +dnl $(SSL_LDFLAGS) will be -Lsslliblocation (if needed) +dnl and $(SSL_INCLUDES) will be -Isslhdrlocation (if needed) +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([KDE_CHECK_SSL], +[ +LIBSSL="-lssl -lcrypto" +AC_REQUIRE([KDE_CHECK_LIB64]) + +ac_ssl_includes=NO ac_ssl_libraries=NO +ssl_libraries="" +ssl_includes="" +AC_ARG_WITH(ssl-dir, + AC_HELP_STRING([--with-ssl-dir=DIR],[where the root of OpenSSL is installed]), + [ ac_ssl_includes="$withval"/include + ac_ssl_libraries="$withval"/lib$kdelibsuff + ]) + +want_ssl=yes +AC_ARG_WITH(ssl, + AC_HELP_STRING([--without-ssl],[disable SSL checks]), + [want_ssl=$withval]) + +if test $want_ssl = yes; then + +AC_MSG_CHECKING(for OpenSSL) + +AC_CACHE_VAL(ac_cv_have_ssl, +[#try to guess OpenSSL locations + + ssl_incdirs="/usr/include /usr/local/include /usr/ssl/include /usr/local/ssl/include $prefix/include $kde_extra_includes" + ssl_incdirs="$ac_ssl_includes $ssl_incdirs" + AC_FIND_FILE(openssl/ssl.h, $ssl_incdirs, ssl_incdir) + ac_ssl_includes="$ssl_incdir" + + ssl_libdirs="/usr/lib$kdelibsuff /usr/local/lib$kdelibsuff /usr/ssl/lib$kdelibsuff /usr/local/ssl/lib$kdelibsuff $libdir $prefix/lib$kdelibsuff $exec_prefix/lib$kdelibsuff $kde_extra_libs" + if test ! "$ac_ssl_libraries" = "NO"; then + ssl_libdirs="$ac_ssl_libraries $ssl_libdirs" + fi + + test=NONE + ssl_libdir=NONE + for dir in $ssl_libdirs; do + try="ls -1 $dir/libssl*" + if test=`eval $try 2> /dev/null`; then ssl_libdir=$dir; break; else echo "tried $dir" >&AC_FD_CC ; fi + done + + ac_ssl_libraries="$ssl_libdir" + + ac_ldflags_safe="$LDFLAGS" + ac_libs_safe="$LIBS" + + LDFLAGS="$LDFLAGS -L$ssl_libdir $all_libraries" + LIBS="$LIBS $LIBSSL -lRSAglue -lrsaref" + + AC_TRY_LINK(,void RSAPrivateEncrypt(void);RSAPrivateEncrypt();, + ac_ssl_rsaref="yes" + , + ac_ssl_rsaref="no" + ) + + LDFLAGS="$ac_ldflags_safe" + LIBS="$ac_libs_safe" + + if test "$ac_ssl_includes" = NO || test "$ac_ssl_libraries" = NO; then + have_ssl=no + else + have_ssl=yes; + fi + + ]) + + eval "$ac_cv_have_ssl" + + AC_MSG_RESULT([libraries $ac_ssl_libraries, headers $ac_ssl_includes]) + + AC_MSG_CHECKING([whether OpenSSL uses rsaref]) + AC_MSG_RESULT($ac_ssl_rsaref) + + AC_MSG_CHECKING([for easter eggs]) + AC_MSG_RESULT([none found]) + +else + have_ssl=no +fi + +if test "$have_ssl" = yes; then + AC_MSG_CHECKING(for OpenSSL version) + dnl Check for SSL version + AC_CACHE_VAL(ac_cv_ssl_version, + [ + + cat >conftest.$ac_ext < +#include + int main() { + +#ifndef OPENSSL_VERSION_NUMBER + printf("ssl_version=\\"error\\"\n"); +#else + if (OPENSSL_VERSION_NUMBER < 0x00906000) + printf("ssl_version=\\"old\\"\n"); + else + printf("ssl_version=\\"ok\\"\n"); +#endif + return (0); + } +EOF + + ac_save_CPPFLAGS=$CPPFLAGS + if test "$ac_ssl_includes" != "/usr/include"; then + CPPFLAGS="$CPPFLAGS -I$ac_ssl_includes" + fi + + if AC_TRY_EVAL(ac_link); then + + if eval `./conftest 2>&5`; then + if test $ssl_version = error; then + AC_MSG_ERROR([$ssl_incdir/openssl/opensslv.h doesn't define OPENSSL_VERSION_NUMBER !]) + else + if test $ssl_version = old; then + AC_MSG_WARN([OpenSSL version too old. Upgrade to 0.9.6 at least, see http://www.openssl.org. SSL support disabled.]) + have_ssl=no + fi + fi + ac_cv_ssl_version="ssl_version=$ssl_version" + else + AC_MSG_ERROR([Your system couldn't run a small SSL test program. + Check config.log, and if you can't figure it out, send a mail to + David Faure , attaching your config.log]) + fi + + else + AC_MSG_ERROR([Your system couldn't link a small SSL test program. + Check config.log, and if you can't figure it out, send a mail to + David Faure , attaching your config.log]) + fi + CPPFLAGS=$ac_save_CPPFLAGS + + ]) + + eval "$ac_cv_ssl_version" + AC_MSG_RESULT($ssl_version) +fi + +if test "$have_ssl" != yes; then + LIBSSL=""; +else + AC_DEFINE(HAVE_SSL, 1, [If we are going to use OpenSSL]) + ac_cv_have_ssl="have_ssl=yes \ + ac_ssl_includes=$ac_ssl_includes ac_ssl_libraries=$ac_ssl_libraries ac_ssl_rsaref=$ac_ssl_rsaref" + + + ssl_libraries="$ac_ssl_libraries" + ssl_includes="$ac_ssl_includes" + + if test "$ac_ssl_rsaref" = yes; then + LIBSSL="-lssl -lcrypto -lRSAglue -lrsaref" + fi + + if test $ssl_version = "old"; then + AC_DEFINE(HAVE_OLD_SSL_API, 1, [Define if you have OpenSSL < 0.9.6]) + fi +fi + +SSL_INCLUDES= + +if test "$ssl_includes" = "/usr/include"; then + if test -f /usr/kerberos/include/krb5.h; then + SSL_INCLUDES="-I/usr/kerberos/include" + fi +elif test "$ssl_includes" != "/usr/local/include" && test -n "$ssl_includes"; then + SSL_INCLUDES="-I$ssl_includes" +fi + +if test "$ssl_libraries" = "/usr/lib" || test "$ssl_libraries" = "/usr/local/lib" || test -z "$ssl_libraries" || test "$ssl_libraries" = "NONE"; then + SSL_LDFLAGS="" +else + SSL_LDFLAGS="-L$ssl_libraries -R$ssl_libraries" +fi + +AC_SUBST(SSL_INCLUDES) +AC_SUBST(SSL_LDFLAGS) +AC_SUBST(LIBSSL) +]) + +AC_DEFUN([KDE_CHECK_STRLCPY], +[ + AC_REQUIRE([AC_CHECK_STRLCAT]) + AC_REQUIRE([AC_CHECK_STRLCPY]) + AC_CHECK_SIZEOF(size_t) + AC_CHECK_SIZEOF(unsigned long) + + AC_MSG_CHECKING([sizeof size_t == sizeof unsigned long]) + AC_TRY_COMPILE(,[ + #if SIZEOF_SIZE_T != SIZEOF_UNSIGNED_LONG + choke me + #endif + ],AC_MSG_RESULT([yes]),[ + AC_MSG_RESULT(no) + AC_MSG_ERROR([ + Apparently on your system our assumption sizeof size_t == sizeof unsigned long + does not apply. Please mail kde-devel@kde.org with a description of your system! + ]) + ]) +]) + +AC_DEFUN([KDE_CHECK_BINUTILS], +[ + AC_MSG_CHECKING([if ld supports unversioned version maps]) + + kde_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map" + echo "{ local: extern \"C++\" { foo }; };" > conftest.map + AC_TRY_LINK([int foo;], +[ +#ifdef __INTEL_COMPILER +icc apparently does not support libtools version-info and version-script +at the same time. Dunno where the bug is, but until somebody figured out, +better disable the optional version scripts. +#endif + + foo = 42; +], kde_supports_versionmaps=yes, kde_supports_versionmaps=no) + LDFLAGS="$kde_save_LDFLAGS" + rm -f conftest.map + AM_CONDITIONAL(include_VERSION_SCRIPT, + [test "$kde_supports_versionmaps" = "yes" && test "$kde_use_debug_code" = "no"]) + + AC_MSG_RESULT($kde_supports_versionmaps) +]) + +AC_DEFUN([AM_PROG_OBJC],[ +AC_CHECK_PROGS(OBJC, gcc, gcc) +test -z "$OBJC" && AC_MSG_ERROR([no acceptable objective-c gcc found in \$PATH]) +if test "x${OBJCFLAGS-unset}" = xunset; then + OBJCFLAGS="-g -O2" +fi +AC_SUBST(OBJCFLAGS) +_AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES(OBJC)]) +]) + +AC_DEFUN([KDE_CHECK_PERL], +[ + KDE_FIND_PATH(perl, PERL, [$bindir $exec_prefix/bin $prefix/bin], [ + AC_MSG_ERROR([No Perl found in your $PATH. +We need perl to generate some code.]) + ]) + AC_SUBST(PERL) +]) + +AC_DEFUN([KDE_CHECK_LARGEFILE], +[ +AC_SYS_LARGEFILE +if test "$ac_cv_sys_file_offset_bits" != no; then + CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits" +fi + +if test "x$ac_cv_sys_large_files" != "xno"; then + CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=1" +fi + +]) + +dnl A small extension to PKG_CHECK_MODULES (defined in pkg.m4.in) +dnl which allows to search for libs that get installed into the KDE prefix. +dnl +dnl Syntax: KDE_PKG_CHECK_MODULES(KSTUFF, libkexif >= 0.2 glib = 1.3.4, action-if, action-not) +dnl defines KSTUFF_LIBS, KSTUFF_CFLAGS, see pkg-config man page +dnl also defines KSTUFF_PKG_ERRORS on error +AC_DEFUN([KDE_PKG_CHECK_MODULES], [ + + PKG_CONFIG_PATH="$prefix/lib${kdelibsuff}/pkgconfig:$PKG_CONFIG_PATH" + if test "$prefix" != "$kde_libs_prefix"; then + PKG_CONFIG_PATH="$kde_libs_prefix/lib${kdelibsuff}/pkgconfig:$PKG_CONFIG_PATH" + fi + export PKG_CONFIG_PATH + PKG_CHECK_MODULES([$1],[$2],[$3],[$4]) +]) + + +dnl Check for PIE support in the compiler and linker +AC_DEFUN([KDE_CHECK_PIE_SUPPORT], +[ + AC_CACHE_CHECK([for PIE support], kde_cv_val_pie_support, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + safe_CXXFLAGS=$CXXFLAGS + safe_LDFLAGS=$LDFLAGS + CXXFLAGS="$CXXFLAGS -fPIE" + LDFLAGS="$LDFLAGS -pie" + + AC_TRY_LINK([int foo;], [], [kde_cv_val_pie_support=yes], [kde_cv_val_pie_support=no]) + + CXXFLAGS=$safe_CXXFLAGS + LDFLAGS=$safe_LDFLAGS + AC_LANG_RESTORE + ]) + + AC_MSG_CHECKING(if enabling -pie/fPIE support) + + AC_ARG_ENABLE(pie, + AC_HELP_STRING([--enable-pie],[platform supports PIE linking [default=detect]]), + [kde_has_pie_support=$enableval], + [kde_has_pie_support=detect]) + + if test "$kde_has_pie_support" = "detect"; then + kde_has_pie_support=$kde_cv_val_pie_support + fi + + AC_MSG_RESULT([$kde_has_pie_support]) + + KDE_USE_FPIE="" + KDE_USE_PIE="" + + AC_SUBST([KDE_USE_FPIE]) + AC_SUBST([KDE_USE_PIE]) + + if test "$kde_has_pie_support" = "yes"; then + KDE_USE_FPIE="-fPIE" + KDE_USE_PIE="-pie" + fi +]) +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 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. + +# serial 51 Debian 1.5.24-1 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +AC_DEFUN([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +AC_DEFUN([_LT_COMPILER_BOILERPLATE], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +AC_DEFUN([_LT_LINKER_BOILERPLATE], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_LINKER_BOILERPLATE + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# ------------------ +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# --------------------------------------------------------------------- +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ---------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +m4_if($1,[],[ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'` + else + lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + sys_lib_search_path_spec=`echo $lt_search_path_spec` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix[[3-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 DLLs +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +# set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognize shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognize a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# it is assumed to be `libltdl'. LIBLTDL will be prefixed with +# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' +# (note the single quotes!). If your package is not flat and you're not +# using automake, define top_builddir and top_srcdir appropriately in +# the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# and an installed libltdl is not found, it is assumed to be `libltdl'. +# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and top_srcdir +# appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + +# _LT_AC_PROG_CXXCPP +# ------------------ +AC_DEFUN([_LT_AC_PROG_CXXCPP], +[ +AC_REQUIRE([AC_PROG_CXX]) +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +fi +])# _LT_AC_PROG_CXXCPP + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# ------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF + +# Report which library types will actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + 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 + exp_sym_flag='-Bexport' + no_entry_flag="" + 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 + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) ;; + *) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + interix[[3-9]]*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + # + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + if test "$solaris_use_stlport4" != yes; then + _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_AC_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac +])# AC_LIBTOOL_POSTDEP_PREDEP + +# AC_LIBTOOL_LANG_F77_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)]) +AC_DEFUN([_LT_AC_LANG_F77_CONFIG], +[AC_REQUIRE([AC_PROG_F77]) +AC_LANG_PUSH(Fortran 77) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="\ + subroutine t + return + end +" + +# Code to be used in simple link tests +lt_simple_link_test_code="\ + program t + end +" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${F77-"f77"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +_LT_AC_TAGVAR(GCC, $1)="$G77" +_LT_AC_TAGVAR(LD, $1)="$LD" + +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_F77_CONFIG + + +# AC_LIBTOOL_LANG_GCJ_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)]) +AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG], +[AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_RESTORE +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_GCJ_CONFIG + + +# AC_LIBTOOL_LANG_RC_CONFIG +# ------------------------- +# Ensure that the configuration vars for the Windows resource compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)]) +AC_DEFUN([_LT_AC_LANG_RC_CONFIG], +[AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_RESTORE +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_RC_CONFIG + + +# AC_LIBTOOL_CONFIG([TAGNAME]) +# ---------------------------- +# If TAGNAME is not passed, then create an initial libtool script +# with a default configuration from the untagged config vars. Otherwise +# add code to config.status for appending the configuration named by +# TAGNAME from the matching tagged config vars. +AC_DEFUN([AC_LIBTOOL_CONFIG], +[# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + _LT_AC_TAGVAR(compiler, $1) \ + _LT_AC_TAGVAR(CC, $1) \ + _LT_AC_TAGVAR(LD, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \ + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \ + _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \ + _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \ + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \ + _LT_AC_TAGVAR(old_archive_cmds, $1) \ + _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \ + _LT_AC_TAGVAR(predep_objects, $1) \ + _LT_AC_TAGVAR(postdep_objects, $1) \ + _LT_AC_TAGVAR(predeps, $1) \ + _LT_AC_TAGVAR(postdeps, $1) \ + _LT_AC_TAGVAR(compiler_lib_search_path, $1) \ + _LT_AC_TAGVAR(archive_cmds, $1) \ + _LT_AC_TAGVAR(archive_expsym_cmds, $1) \ + _LT_AC_TAGVAR(postinstall_cmds, $1) \ + _LT_AC_TAGVAR(postuninstall_cmds, $1) \ + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \ + _LT_AC_TAGVAR(allow_undefined_flag, $1) \ + _LT_AC_TAGVAR(no_undefined_flag, $1) \ + _LT_AC_TAGVAR(export_symbols_cmds, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \ + _LT_AC_TAGVAR(hardcode_automatic, $1) \ + _LT_AC_TAGVAR(module_cmds, $1) \ + _LT_AC_TAGVAR(module_expsym_cmds, $1) \ + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \ + _LT_AC_TAGVAR(fix_srcfile_path, $1) \ + _LT_AC_TAGVAR(exclude_expsyms, $1) \ + _LT_AC_TAGVAR(include_expsyms, $1); do + + case $var in + _LT_AC_TAGVAR(old_archive_cmds, $1) | \ + _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \ + _LT_AC_TAGVAR(archive_cmds, $1) | \ + _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \ + _LT_AC_TAGVAR(module_cmds, $1) | \ + _LT_AC_TAGVAR(module_expsym_cmds, $1) | \ + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \ + _LT_AC_TAGVAR(export_symbols_cmds, $1) | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\[$]0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'` + ;; + esac + +ifelse([$1], [], + [cfgfile="${ofile}T" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + $rm -f "$cfgfile" + AC_MSG_NOTICE([creating $ofile])], + [cfgfile="$ofile"]) + + cat <<__EOF__ >> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([LT_AC_PROG_SED]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux* | k*bsd*-gnu) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + esac + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + ;; + linux* | k*bsd*-gnu) + _LT_AC_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) + 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 + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II 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 can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix[[3-9]]*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + *) + tmp_sharedflag='-shared' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=no + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=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 + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + 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 + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi[[45]]*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + 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. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + + +# Cheap backport of AS_EXECUTABLE_P and required macros +# from Autoconf 2.59; we should not use $as_executable_p directly. + +# _AS_TEST_PREPARE +# ---------------- +m4_ifndef([_AS_TEST_PREPARE], +[m4_defun([_AS_TEST_PREPARE], +[if test -x / >/dev/null 2>&1; then + as_executable_p='test -x' +else + as_executable_p='test -f' +fi +])])# _AS_TEST_PREPARE + +# AS_EXECUTABLE_P +# --------------- +# Check whether a file is executable. +m4_ifndef([AS_EXECUTABLE_P], +[m4_defun([AS_EXECUTABLE_P], +[AS_REQUIRE([_AS_TEST_PREPARE])dnl +$as_executable_p $1[]dnl +])])# AS_EXECUTABLE_P + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if AS_EXECUTABLE_P(["$as_dir/$lt_ac_prog$ac_exec_ext"]); then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +]) + +dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) +dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page +dnl also defines GSTUFF_PKG_ERRORS on error +AC_DEFUN([PKG_CHECK_MODULES], [ + succeeded=no + + if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + fi + + if test "$PKG_CONFIG" = "no" ; then + echo "*** The pkg-config script could not be found. Make sure it is" + echo "*** in your path, or set the PKG_CONFIG environment variable" + echo "*** to the full path to pkg-config." + echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." + else + PKG_CONFIG_MIN_VERSION=0.9.0 + if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then + AC_MSG_CHECKING(for $2) + + if $PKG_CONFIG --exists "$2" ; then + AC_MSG_RESULT(yes) + succeeded=yes + + AC_MSG_CHECKING($1_CFLAGS) + $1_CFLAGS=`$PKG_CONFIG --cflags "$2"` + AC_MSG_RESULT($$1_CFLAGS) + + AC_MSG_CHECKING($1_LIBS) + $1_LIBS=`$PKG_CONFIG --libs "$2"` + AC_MSG_RESULT($$1_LIBS) + else + $1_CFLAGS="" + $1_LIBS="" + ## If we have a custom action on failure, don't print errors, but + ## do set a variable so people can do so. + $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + ifelse([$4], ,echo $$1_PKG_ERRORS,) + fi + + AC_SUBST($1_CFLAGS) + AC_SUBST($1_LIBS) + else + echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." + echo "*** See http://www.freedesktop.org/software/pkgconfig" + fi + fi + + if test $succeeded = yes; then + ifelse([$3], , :, [$3]) + else + ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4]) + fi +]) + + diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..2f1ca33 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,910 @@ +# generated automatically by aclocal 1.10.1 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(AC_AUTOCONF_VERSION, [2.61],, +[m4_warning([this file was generated for autoconf 2.61. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. +# +# 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. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.10' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.10.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.10.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(AC_AUTOCONF_VERSION)]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006 +# Free Software Foundation, Inc. +# +# 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. + +# serial 8 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 +# Free Software Foundation, Inc. +# +# 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. + +# serial 9 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# 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. + +#serial 3 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# 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. + +# serial 8 + +# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. +AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008 Free Software Foundation, Inc. +# +# 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. + +# serial 13 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.60])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# 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. + +# serial 4 + +AC_DEFUN([AM_MAINTAINER_MODE], +[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode is disabled by default + AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + USE_MAINTAINER_MODE=$enableval, + USE_MAINTAINER_MODE=no) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST(MAINT)dnl +] +) + +AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# serial 3 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# 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. + +# serial 5 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# +# 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. + +# AM_PROG_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# serial 3 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# 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. + +# serial 4 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# 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. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006 Free Software Foundation, Inc. +# +# 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. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# +# 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. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([acinclude.m4]) diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..a3806e3 --- /dev/null +++ b/config.h.in @@ -0,0 +1,252 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_CARBON_CARBON_H + +/* Define if you have the CoreAudio API */ +#undef HAVE_COREAUDIO + +/* Define to 1 if you have the header file. */ +#undef HAVE_CRT_EXTERNS_H + +/* Defines if your system has the crypt function */ +#undef HAVE_CRYPT + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define if you have Kimiface headers */ +#undef HAVE_KIMIFACE + +/* Define if you have libjpeg */ +#undef HAVE_LIBJPEG + +/* Define if you have libpng */ +#undef HAVE_LIBPNG + +/* Define if you have a working libpthread (will enable threaded code) */ +#undef HAVE_LIBPTHREAD + +/* Define if you have libz */ +#undef HAVE_LIBZ + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if your system needs _NSGetEnviron to set up the environment */ +#undef HAVE_NSGETENVIRON + +/* Define if you have res_init */ +#undef HAVE_RES_INIT + +/* Define if you have the res_init prototype */ +#undef HAVE_RES_INIT_PROTO + +/* Define if you have a STL implementation by SGI */ +#undef HAVE_SGI_STL + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have strlcat */ +#undef HAVE_STRLCAT + +/* Define if you have the strlcat prototype */ +#undef HAVE_STRLCAT_PROTO + +/* Define if you have strlcpy */ +#undef HAVE_STRLCPY + +/* Define if you have the strlcpy prototype */ +#undef HAVE_STRLCPY_PROTO + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_BITYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TGMATH_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define if you have the XScreenSaver extension */ +#undef HAVE_XSCREENSAVER + +/* Suffix for lib directories */ +#undef KDELIBSUFF + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of `char *', as computed by sizeof. */ +#undef SIZEOF_CHAR_P + +/* The size of `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of `short', as computed by sizeof. */ +#undef SIZEOF_SHORT + +/* The size of `size_t', as computed by sizeof. */ +#undef SIZEOF_SIZE_T + +/* The size of `unsigned long', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_LONG + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* If we use arts volume */ +#undef USE_ARTS + +/* Define if you have KNotify */ +#undef USE_KNOTIFY + +/* Version number of package */ +#undef VERSION + +/* Defined if compiling without arts */ +#undef WITHOUT_ARTS + +/* + * jpeg.h needs HAVE_BOOLEAN, when the system uses boolean in system + * headers and I'm too lazy to write a configure test as long as only + * unixware is related + */ +#ifdef _UNIXWARE +#define HAVE_BOOLEAN +#endif + + + +/* + * AIX defines FD_SET in terms of bzero, but fails to include + * that defines bzero. + */ + +#if defined(_AIX) +#include +#endif + + + +#if defined(HAVE_NSGETENVIRON) && defined(HAVE_CRT_EXTERNS_H) +# include +# include +# define environ (*_NSGetEnviron()) +#endif + + + +#if !defined(HAVE_RES_INIT_PROTO) +#ifdef __cplusplus +extern "C" { +#endif +int res_init(void); +#ifdef __cplusplus +} +#endif +#endif + + + +#if !defined(HAVE_STRLCAT_PROTO) +#ifdef __cplusplus +extern "C" { +#endif +unsigned long strlcat(char*, const char*, unsigned long); +#ifdef __cplusplus +} +#endif +#endif + + + +#if !defined(HAVE_STRLCPY_PROTO) +#ifdef __cplusplus +extern "C" { +#endif +unsigned long strlcpy(char*, const char*, unsigned long); +#ifdef __cplusplus +} +#endif +#endif + + + +/* + * On HP-UX, the declaration of vsnprintf() is needed every time ! + */ + +#if !defined(HAVE_VSNPRINTF) || defined(hpux) +#if __STDC__ +#include +#include +#else +#include +#endif +#ifdef __cplusplus +extern "C" +#endif +int vsnprintf(char *str, size_t n, char const *fmt, va_list ap); +#ifdef __cplusplus +extern "C" +#endif +int snprintf(char *str, size_t n, char const *fmt, ...); +#endif + + + +#if defined(__SVR4) && !defined(__svr4__) +#define __svr4__ 1 +#endif + + +/* type to use in place of socklen_t if not defined */ +#undef kde_socklen_t + +/* type to use in place of socklen_t if not defined (deprecated, use + kde_socklen_t) */ +#undef ksize_t diff --git a/configure.files b/configure.files new file mode 100644 index 0000000..e21fe66 --- /dev/null +++ b/configure.files @@ -0,0 +1,3 @@ +./admin/configure.in.min +configure.in.in +./konversation/configure.in.in diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..0c5f566 --- /dev/null +++ b/configure.in @@ -0,0 +1,234 @@ +dnl ======================================================= +dnl FILE: ./admin/configure.in.min +dnl ======================================================= + +dnl This file is part of the KDE libraries/packages +dnl Copyright (C) 2001 Stephan Kulow (coolo@kde.org) + +dnl This file is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Library General Public +dnl License as published by the Free Software Foundation; either +dnl version 2 of the License, or (at your option) any later version. + +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Library General Public License for more details. + +dnl You should have received a copy of the GNU Library General Public License +dnl along with this library; see the file COPYING.LIB. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +dnl Boston, MA 02110-1301, USA. + +# Original Author was Kalle@kde.org +# I lifted it in some mater. (Stephan Kulow) +# I used much code from Janos Farkas + +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(acinclude.m4) dnl a source file from your sub dir + +dnl This is so we can use kde-common +AC_CONFIG_AUX_DIR(admin) + +dnl This ksh/zsh feature conflicts with `cd blah ; pwd` +unset CDPATH + +dnl Checking host/target/build systems, for make, install etc. +AC_CANONICAL_SYSTEM +dnl Perform program name transformation +AC_ARG_PROGRAM + +dnl Automake doc recommends to do this only here. (Janos) +AM_INIT_AUTOMAKE(konversation-1.1, "3.5.9") dnl searches for some needed programs + +AM_MAINTAINER_MODE + +KDE_SET_PREFIX + +dnl generate the config header +AM_CONFIG_HEADER(config.h) dnl at the distribution this done + +dnl Checks for programs. +AC_CHECK_COMPILERS +AC_ENABLE_SHARED(yes) +AC_ENABLE_STATIC(no) +KDE_PROG_LIBTOOL + +dnl for NLS support. Call them in this order! +dnl WITH_NLS is for the po files +AM_KDE_WITH_NLS + +KDE_USE_QT(3.2) +AC_PATH_KDE +dnl ======================================================= +dnl FILE: configure.in.in +dnl ======================================================= + +#MIN_CONFIG(3.2) +CXXFLAGS="$CXXFLAGS $KDE_DEFAULT_CXXFLAGS" + +if test "$build_arts" = "yes"; then + AC_DEFINE(USE_ARTS, 1, [If we use arts volume]) + LIB_ARTS="-lartskde" + AC_SUBST(LIB_ARTS) +fi + +KDE_INIT_DOXYGEN([KEG Network API Reference], [Version $VERSION]) + +dnl ======================================================= +dnl FILE: ./konversation/configure.in.in +dnl ======================================================= + +#MIN_CONFIG(3.2) +CXXFLAGS="$CXXFLAGS $KDE_DEFAULT_CXXFLAGS" + +KDE_CHECK_HEADER(knotifyclient.h, + [ + AC_DEFINE(USE_KNOTIFY, 1, [Define if you have KNotify] ) + ]) + + +KDE_CHECK_HEADER(kimiface.h, + [ + AC_DEFINE(HAVE_KIMIFACE, 1, [Define if you have Kimiface headers] ) + LIB_KIMIFACE="-lkimproxy" + AC_SUBST(LIB_KIMIFACE) + ]) + +# Check for XScreenSaver +AC_CHECK_HEADERS(tgmath.h)xss_save_ldflags="$LDFLAGS" +LDFLAGS="$X_LDFLAGS" + +LIB_XSS= + +KDE_CHECK_HEADER(X11/extensions/scrnsaver.h, + [ + AC_CHECK_LIB(Xext,XScreenSaverQueryInfo, + [ + AC_DEFINE(HAVE_XSCREENSAVER, 1, [Define if you have the XScreenSaver extension]) + LIB_XSS="-lXext" + ], + [ + ld_shared_flag= + KDE_CHECK_COMPILER_FLAG(shared, [ld_shared_flag="-shared"]) + AC_CHECK_LIB(Xss,XScreenSaverQueryInfo, + [ + AC_DEFINE(HAVE_XSCREENSAVER, 1, [Define if you have the XScreenSaver extension]) + LIB_XSS="-lXss" + ], + [], + [ $ld_shared_flag $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS ]) + ], + [ $X_PRE_LIBS -lX11 $X_EXTRA_LIBS ]) + ], [], + [ + #include + ] ) + +AC_SUBST(LIB_XSS) +LDFLAGS="$xss_save_ldflags" +KDE_CREATE_SUBDIRSLIST +AM_CONDITIONAL(doc_SUBDIR_included, test "x$doc_SUBDIR_included" = xyes) +AM_CONDITIONAL(konversation_SUBDIR_included, test "x$konversation_SUBDIR_included" = xyes) +AM_CONDITIONAL(po_SUBDIR_included, test "x$po_SUBDIR_included" = xyes) +AC_CONFIG_FILES([ Makefile ]) +AC_CONFIG_FILES([ doc/Makefile ]) +AC_CONFIG_FILES([ doc/da/Makefile ]) +AC_CONFIG_FILES([ doc/es/Makefile ]) +AC_CONFIG_FILES([ doc/et/Makefile ]) +AC_CONFIG_FILES([ doc/it/Makefile ]) +AC_CONFIG_FILES([ doc/konversation/Makefile ]) +AC_CONFIG_FILES([ doc/pt/Makefile ]) +AC_CONFIG_FILES([ doc/ru/Makefile ]) +AC_CONFIG_FILES([ doc/sv/Makefile ]) +AC_CONFIG_FILES([ konversation/Makefile ]) +AC_CONFIG_FILES([ konversation/images/Makefile ]) +AC_CONFIG_FILES([ konversation/images/icons/Makefile ]) +AC_CONFIG_FILES([ konversation/images/nickicons/Makefile ]) +AC_CONFIG_FILES([ konversation/images/nickicons/alternative/Makefile ]) +AC_CONFIG_FILES([ konversation/images/nickicons/christmas/Makefile ]) +AC_CONFIG_FILES([ konversation/images/nickicons/classic/Makefile ]) +AC_CONFIG_FILES([ konversation/images/nickicons/default/Makefile ]) +AC_CONFIG_FILES([ konversation/images/nickicons/oxygen/Makefile ]) +AC_CONFIG_FILES([ konversation/images/nickicons/smiling/Makefile ]) +AC_CONFIG_FILES([ konversation/images/nickicons/square/Makefile ]) +AC_CONFIG_FILES([ konversation/scripts/Makefile ]) +AC_CONFIG_FILES([ konversation/src/Makefile ]) +AC_CONFIG_FILES([ konversation/src/blowfish/Makefile ]) +AC_CONFIG_FILES([ konversation/src/config/Makefile ]) +AC_CONFIG_FILES([ konversation/src/linkaddressbook/Makefile ]) +AC_CONFIG_FILES([ po/Makefile ]) +AC_CONFIG_FILES([ po/ar/Makefile ]) +AC_CONFIG_FILES([ po/bg/Makefile ]) +AC_CONFIG_FILES([ po/ca/Makefile ]) +AC_CONFIG_FILES([ po/da/Makefile ]) +AC_CONFIG_FILES([ po/de/Makefile ]) +AC_CONFIG_FILES([ po/el/Makefile ]) +AC_CONFIG_FILES([ po/en_GB/Makefile ]) +AC_CONFIG_FILES([ po/es/Makefile ]) +AC_CONFIG_FILES([ po/et/Makefile ]) +AC_CONFIG_FILES([ po/fi/Makefile ]) +AC_CONFIG_FILES([ po/fr/Makefile ]) +AC_CONFIG_FILES([ po/gl/Makefile ]) +AC_CONFIG_FILES([ po/he/Makefile ]) +AC_CONFIG_FILES([ po/hu/Makefile ]) +AC_CONFIG_FILES([ po/it/Makefile ]) +AC_CONFIG_FILES([ po/ja/Makefile ]) +AC_CONFIG_FILES([ po/ka/Makefile ]) +AC_CONFIG_FILES([ po/ko/Makefile ]) +AC_CONFIG_FILES([ po/pa/Makefile ]) +AC_CONFIG_FILES([ po/pt/Makefile ]) +AC_CONFIG_FILES([ po/ru/Makefile ]) +AC_CONFIG_FILES([ po/sr/Makefile ]) +AC_CONFIG_FILES([ po/sr@Latn/Makefile ]) +AC_CONFIG_FILES([ po/sv/Makefile ]) +AC_CONFIG_FILES([ po/tr/Makefile ]) +AC_CONFIG_FILES([ po/zh_CN/Makefile ]) +AC_CONFIG_FILES([ po/zh_TW/Makefile ]) +AC_OUTPUT +# Check if KDE_SET_PREFIX was called, and --prefix was passed to configure +if test -n "$kde_libs_prefix" -a -n "$given_prefix"; then + # And if so, warn when they don't match + if test "$kde_libs_prefix" != "$given_prefix"; then + # And if kde doesn't know about the prefix yet + echo ":"`kde-config --path exe`":" | grep ":$given_prefix/bin/:" 2>&1 >/dev/null + if test $? -ne 0; then + echo "" + echo "Warning: you chose to install this package in $given_prefix," + echo "but KDE was found in $kde_libs_prefix." + echo "For this to work, you will need to tell KDE about the new prefix, by ensuring" + echo "that KDEDIRS contains it, e.g. export KDEDIRS=$given_prefix:$kde_libs_prefix" + echo "Then restart KDE." + echo "" + fi + fi +fi + +if test x$GXX = "xyes" -a x$kde_have_gcc_visibility = "xyes" -a x$kde_cv_val_qt_gcc_visibility_patched = "xno"; then + echo "" + echo "Your GCC supports symbol visibility, but the patch for Qt supporting visibility" + echo "was not included. Therefore, GCC symbol visibility support remains disabled." + echo "" + echo "For better performance, consider including the Qt visibility supporting patch" + echo "located at:" + echo "" + echo "http://bugs.kde.org/show_bug.cgi?id=109386" + echo "" + echo "and recompile all of Qt and KDE. Note, this is entirely optional and" + echo "everything will continue to work just fine without it." + echo "" +fi + +if test "$all_tests" = "bad"; then + if test ! "$cache_file" = "/dev/null"; then + echo "" + echo "Please remove the file $cache_file after changing your setup" + echo "so that configure will find the changes next time." + echo "" + fi +else + echo "" + echo "Good - your configure finished. Start make now" + echo "" +fi diff --git a/configure.in.in b/configure.in.in new file mode 100644 index 0000000..a781b76 --- /dev/null +++ b/configure.in.in @@ -0,0 +1,11 @@ +#MIN_CONFIG(3.2) +CXXFLAGS="$CXXFLAGS $KDE_DEFAULT_CXXFLAGS" + +if test "$build_arts" = "yes"; then + AC_DEFINE(USE_ARTS, 1, [If we use arts volume]) + LIB_ARTS="-lartskde" + AC_SUBST(LIB_ARTS) +fi + +KDE_INIT_DOXYGEN([KEG Network API Reference], [Version $VERSION]) + diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..6812bd2 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,5 @@ + +KDE_LANG = en +KDE_DOCS = AUTO +SUBDIRS = $(AUTODIRS) + diff --git a/doc/da/Makefile.am b/doc/da/Makefile.am new file mode 100644 index 0000000..fc88e70 --- /dev/null +++ b/doc/da/Makefile.am @@ -0,0 +1,2 @@ +KDE_LANG = da +KDE_DOCS = konversation diff --git a/doc/da/index.docbook b/doc/da/index.docbook new file mode 100644 index 0000000..0b29be3 --- /dev/null +++ b/doc/da/index.docbook @@ -0,0 +1,5935 @@ + + + + + IRC"> + CTCP"> + nickname"> + Nickname"> + LED"> + OSD"> + URL"> + MIME"> + + + + + + +]> + + + + + + + + + + + + +&konversation;-håndbogen + + + Gary R. Cramblitt garycramblitt@comcast.net +&erik.kjaer.pedersen.role; + + + + + +2003-2005 +Gary R. Cramblitt + + + + +&FDLNotice; + + + +2005-05-23 +0.18 + + + + +&konversation; er en brugervenlig &irc;-klient for K-desktopmiljøet. + + + + + +KDE +kdeextragear-2 +Konversation +irc +internet relay chat +chat +kommunikationer + + + + + + + + + +Indledning + + + +&konversation; er en &irc;-klient for &kde; 3.2 eller senere. Den tilbyder følgende funktioner. + + + +Støtte for SSL. +Brugervenlig fanebladsgrænseflade. +Brugerindstillelige hurtigknapper til ofte brugte kommandoer +Automatisk genforbindelse og gendeltagelse i kanal. +DCC sende og modtage. +&Nickname;-overvågningsliste. +Visuelle og lydmæssige påmindelser for et vidt område af begivenheder, såsom beskeder der indeholder dit alias, eller aliasser på din overvågningsliste der kommer på eller går af nettet. +Brugerindstillelig fremhævning a beskeder efter alias eller regulært udtryk. +&Nickname;-komplettering. +Indfangning og gemning af &URL;'er fra meddelelser. +Visning af meddelelser på skærmen, selv minimeret. +&Nickname;-ignoreringsliste. +Automatisk logning og log-håndtering. +Markering af linjer i logger. +Scripting. +Integration med &kaddressbook;. + + + +Hjemmesiden for &konversation; er &konviwebsite;. Spørgsmål og svar om &konversation; kan diskuteres via e-mail-listen &konversation;-Users. Abonnér venligst for at lære om nye funktioner, fejlrapporter og lignende. For at blive informeret om nye udgaver, kan du gå med i e-mail-listen &konversation;-Announce. Dette er en e-mail-liste med et lille antal breve, som kun bruges til at annoncere nye udgaver eller programrettelser. + +Udviklere af &konversation; kan ofte kontaktes via &irc; på irc.kde.org kanalen #konversation. + + + + +Brug af &konversation; + + + + +Hvis du ikke har brugt &irc; tidligere... + +Enkelt udtrykt er &irc; en chat-protokol, defineret af officielle Internetstandarder, med mulighed for at stjæle mange timer af dit liv. For at bruge &irc; skal du være forbundet til en server, og derefter gå med i en kanal (som svarer til et chatrum) eller blot deltage i en privat konversation. + +For at blive forbundet til en server og kanal, startes &konversation;. Skærmen Serverliste vises. + + + +Serverliste + + + + + + + + + + + + + Serverliste + + + + + + + +Listen med indstellede &irc;-netværk angives her. Et &irc;-netværk er en samling samarbejdende servere. Du behøver kun at forbinde dig til en af serverne i netværket for at være forbundet til hele &irc;-netværket. Når du er forbundet, vil &konversation; automatisk gå med i de viste Kanaler. Når &konversation; startes for første gang, er netværket Freenode og kanalen #kde allerede skrevet indfor dig. Klik på et netværk for at vælge det. +Klik her for at definere et nyt Netværk, inklusive serveren at forbinde til, og Kanalerne som automatisk skal gås med i efter forbindelse. Se Definér nye netværk, servere og kanaler at gå med i automatisk for mere information. +Klik her for at forbinde til den valgte &irc; netværk og kanal. + + + + +Når du klikker på knappen Forbind første gang du åbner &konversation;, ser du måske følgende meddelelse, som fortæller dig at din standardidentitet ikke er rigtigt indstillet. + + + + Kontrollér identiteter + + + + + + Kontrollér identiteter + + + + + +Første gang du åbner &konversation; hentes information om nuværende bruger fra operativsystemet, og standardværdier for identiteten udfyldes. Hvis brugerinformationen i operativsystemet ikke er fuldstændig, for eksempel hvis intet Fuldstændigt navn er defineret, vil du se meddelelsen ovenfor. For at rette problemet, klikkes på O.k. og så kigges i Opsætning af din identitet for mere information. + + +Hovedskærmen åbnes og viser meddelelser som sendes af serveren til klienten. (Hvis &konversation; ikke vil forbindes til serveren, se Ofte stillede spørgsmål.) Når servermeddelelser er færdige med at rulle forbi, går &konversation; med i den kanal eller de kanaler som blev valgt. + + + +Kanal. + + + + + + + + + + + + + Kanal + + + + + + + + +Dette kaldes indtastningslinjen. For at sende en meddelelse til alle på kanalen, indskrives meddelelsen her og der trykkes på &Enter;. Meddelelsen samt alle andres meddelelser ses i kanalvinduet ovenfor. Hver meddelelse indledes med tiden og brugerens alias. + +Du kan gå med i yderligere servere og kanaler. Hver server, kanal, kanalliste og anden skærm får et separat faneblad her. For at vise en liste med tilgængelige kanaler, se Liste over tilgængelige kanaler. For at gå med i en kanal, skriv: /join #kanalnavn på inddatalinjen. (Tegnet # kræves.) Du kan også skrive /j som forkortelse af /join. For at forlade en kanal, skrives blot /part. For at skifte visning til en anden server eller kanal, klikkes på det tilsvarende faneblad. + +Dette kaldes Aliaspanelet. Det er en liste over aliasser for alle brugere som er gået med på kanalen, inklusive dig selv. + + + + +Dette er det grundlæggende, for mere detaljeret information, læs videre... + + + + + + +Indstil din identitet + +Inden du begynder at bruge &konversation; regelmæssigt bør du indstille hvordan du vil være identificeret på netværket. + +Klik på Opsætning Identiteter i hovedmenuen. Skærmen Identiteter vises. Du kan også vise skærmen Identiteter ved at klikke på knappen Redigér på skærmen Tilføj netværk. + + + +Identiteter (fanebladet Generelt) + + + + + + + + + + + + + + + + + Identiteter (fanebladet Generelt) + + + + + + + +Klik her for at vælge en Identitet at redigere. +Brug disse knapper for at tilføje, duplikere, omdøbe eller fjerne en Identitet. +Indtast dit rigtige navn her. &irc; er ikke beregnet til skjule sig for dine venner eller fjender. Husk det hvis du bliver fristet til at opføre dig ondartet. Et forkert "rigtigt navn" kan være en god måde at skjule om du er mand eller kvinde for alle tumperne derude, men maskinen som du bruger kan altid spores, så du kan aldrig være virkeligt anonym. +Brug disse knapperne for handlingerne Tilføj, Redigér eller Slet et alias. +Dette er din liste af alsiasser. Et alias er navnet som de øvrige brugere kender dig som. Du kan indtaste hvilket som helst navn du ønsker. Det første tegn skal være et bogstav, mens øvrige tegn kan være bogstaver, tal eller specialtegn -[]\`_^{}|. + +Eftersom aliasser skal være entydige på hele &irc;-netværket, kan dit ønskede navn måske ikke tillades af servere eftersom en anden allerede bruger det. Indtast alternative aliasser for dig selv. Hvis dit første valg ikke tillades af serveren, forsøger &konversation; med de alternative aliasser. + +Ifølge RFC 2812 er den maksimale aliasnavnelængde 9, men det afgøres i virkeligheden af serveren. For at afgøre maksimum for en server, forbindes til serveren. Led efter meddelelsen [Support] i fanebladet Servermeddelelsen. For eksempel: + + +[18:51] *Eisfuchs* [21:45] [Support] Eisfuchs MODES=4 MAXCHANNELS=20 NICKLEN=16 USERLEN=10 HOSTLEN=63 TOPICLEN=450 KICKLEN=450 CHANNELLEN=30 KEYLEN=23 CHANTYPES=# PREFIX=@+ CASEMAPPING=ascii CAPAB &irc;D=dancer + + +Parameteren NICKLEN angiver den maksimale længde på alias. + + +Brug disse knapper for at ændre rækkefølge på aliasser. Det øverste alias prøves først, derefter det næste, og så videre. +Hvis du har registreret dit alias med &irc;-netværket, indtastes tjenesten og kodeordet for godkende dit alias. Når &konversation; forbinder, sendes automatisk /msg tjeneste IDENTIFY kodeord til serveren. Hvis du ikke ved hvad dette er, så lad felterne være tomme. + + + + + +Klik på fanebladet Borte. + + + + Identiteter (fanebladet Borte) + + + + + + + + + + + + + Identiteter (fanebladet Borte) + + + + + + + +Indtast et alias som angiver at du er borte. Så snart du udfører kommandoen /away meddelelse i en kanal som du gået med i med denne Identitet, ændrer &konversation; automatisk dit alias til Borte alias. Andre brugere mærker at du er væk fra maskinen. Så snart du udfører kommandoen /away i den kanal hvor du er borte, ændrer &konversation; automatisk dit alias tilbage til det normale. Hvis du ikke automatisk vil ændre dit alias når du er borte, så lad det være tomt. +Hvis du markerer dette felt, så tegnes en vandret linje i kanalen så snart du udfører kommandoen /away, som markerer stedet du gik væk fra. Andre &irc;-brugere ser ikke denne vandrette linje. +Hvis du markerer dette felt sender &konversation; automatisk Bortemeddelelse til alle kanaler som du gået med i med denne Identitet. %s erstattes med meddelelse. Så snart du udfører kommandoen /away, vises Genkomstmeddelelsei alle kanaler du gået med i med denne Identitet. + +Borte-meddelelser anses ofte for at være irriterende af andre brugere. Brug dette med forsigtighed, og tag hensyn til andre &irc;-brugere. + + + + + + +Klik på fanebladet Avanceret. + + + + Identiteter (fanebladet Avanceret) + + + + + + + + + + + + + + + + Identiteter (fanebladet Avanceret) + + + + + + + +Du kan indtaste et kommando her som køres inden forbindelse til serveren. Hvis identiteten bruges for mere end en server, køres kommandoen for hver server. +Denne indstilling påvirker hvordan tegn du skriver kodes når de skal sendes til serveren. Den påvirker også hvordan meddelelser vises. Når du først åbner &konversation;, hentes denne indstilling automatisk fra operativsystemet. Hvis du synes at have problemer med at se andre brugeres meddelelser rigtigt, så forsøg at ændre denne indstilling. +Når du forbinder, spørger mange servere din maskine efter et IDENT-svar. Hvis din maskine ikke kører en IDENT-server, sendes svaret af &konversation;. Ingen mellemrum er tilladt. Et forslag er at bruge dit fornavn. +Så snart du forlader en kanal, sendes denne meddelelse til kanalen. +Så snart du sparkes ud fra en kanal (oftest af en &irc;-operatør), sendes denne meddelelse til kanalen. +Klik for at anvende dine ændringer. For at alle ændringer skal få virkning, skal du afbryde fra serveren og forbinde igen. Den enkleste måde at gøre det er at afslutte &konversation; og starte forfra. + + + + + + + + + + +Definér nye netværk, servere og autodeltage-kanaler + +Skærmen Serverliste vises når du starter programmet &konversation;. Den vises også når du vælger Fil Serverliste i hovedmenuen. Skærmen Serverliste angiver de eksisterende definerede &irc;-netværk, efter gruppe. Et &irc;-netværk er en samling samarbejdende servere. Når du forbinder til en server i et netværk, kan du få adgang til alle kanaler i netværket. Eksempel på &irc;-netværk er Freenode og Undernet. + + + + Serverliste + + + + + + + + + + + + + + Serverliste + + + + + + + +Dine eksisterende definerede netværk er på listen her sammen med den identitet som bruges til at forbinde til netværket, og de kanaler som du automatisk går med i når du er forbundet. Hvis du har angivet en gruppe for dine netværk, er netværkene indrykket på listen under gruppen. Klik på et netværk for at markere det. +Brug disse knapperne for at tilføje et nyt netværk, redigere et markeret netværk eller slette et markeret netværk. +Klik på denne knap for at forbinde til et markeret netværk og lukke skærmen Serverliste. Du kan markere mere end et netværk hvis du ønsker det, hvilket forbinder til alle de markerede netværk. +At klikke på denne knap kasserer ikke de ændringer du har gjort. Det betyder kun at du ikke vil forbinde til noget netværk for øjeblikket. + + + + + +Når du klikker på knappen Tilføj vises skærmen Tilføj netværk. + + + + Tilføj netværk + + + + + + + + + + + + + + + + + + + Tilføj netværk + + + + + + + +Indtast navnet på et netværk her. Du kan oprette så mange indgange på skærmen Serverliste med samme netværk som du vil. +Valgfrit. Hvis du skriver noget her, kommer alle netværk med samme gruppe sammen på en liste på skærmen Serverliste. +Vælg en eksisterende identitet eller klik på knappen Redigér for at tilføje en ny identitet eller redigere en eksisterende. En identitet vil identificere dig og afgøre dit alias når du forbinder til netværket. +Valgfrit. Kommandoen sendes til serveren efter forbindelse. Eksempel: /msg NickServ IDENTIFY konvirocks. Eksemplet gælder for netværket freenode, som kræver at brugere registrerer deres aliasser med et kodeord og brugernavn ved forbindelse. konvirocks er kodeordet for aliasset som angives under Identitet. Du kan indtaste mere end en kommando ved at skille dem ad med semikolon. +Markér dette hvis du ønsker at &konversation; automatisk skal forbinde til netværket så snart du åbner &konversation;. +Dette er en liste med &irc;-servere i netværket. Ved forbindelse til netværket, forsøger &konversation; at forbinde til den øverste server først. Hvis det mislykkes, forsøger den med den anden server. Hvis det mislykkes, forsøger den med den tredje, og så videre. I det mindste en server skal angives. Klik på en server for at markere den. +Brug disse knapper til at tilføje en server, redigere en markeret server eller slette en markeret server. Du kan også justere servernes rækkefølge, og på den måde rækkefølgen af forbindelsesforsøg. +Valgfrit. Dette er en liste over kanalerne du automatisk går med i så snart &konversation; er forbundet til en server. Du kan lade den være tom hvis du ikke vil gå med i nogen kanaler automatisk. +Brug disse knapper til at tilføje en kanal, redigere en markeret kanal eller slette en markeret kanal. Du kan også ændre rækkefølgen som du går med i kanalerne. + + + +Undgå at blande servere på forskellige &irc;-netværk under samme netværk. Undgå at indtaste samme server under to forskellige netværk. Ellers virker &konversation;s integration med adressbogen og overvågning af online aliasser ikke rigtigt. + + + + +Når du klikker på knappen Tilføj i feltet Servere, vises skærmen Tilføj server. + + + + Tilføj server + + + + + + + + + + + + + + Tilføj server + + + + + + + +Navnet eller IP-adressen på serveren. En liste med servere findes på irchelp.org. +Indtast portnummeret som kræves for at forbinde til serveren. For de fleste servere skal det være 6667. +Hvis serveren kræver et kodeord for at forbinde, så indtast dette. Lad det ellers være tomt. +Markér hvis du vil bruge SSL-protokollen (Secure Socket Layer) til at kommunikere med serveren. Det beskytter kommunikationen mellem din maskine og &irc;-servern, og gør den privat. Serveren skal understøtte SSL-protokollen for at det skal virke. I de fleste tilfælde, hvis serveren ikke understøtter SSL, mislykkes forbindelsen. + + + + + +Når du klikker på knappen Tilføj i feltet Gå automatisk med i kanaler, vises skærmen Tilføj kanal. + + + + Tilføj kanal + + + + + + Tilføj kanal + + + + + +Indtast et kanalnavn. Glem ikke det indledende tegn #. Hvis kanalen kræver et kodeord for at gå med, så indtast det, lad det ellers være tomt. + + + + + + +Liste over tilgængelige kanaler + +For at vise en liste med tilgængelige kanaler, vælges Vindue Kanalliste i hovedmenuen. Efter en advarselsskærm laves et nyt faneblad som hedder Kanalliste. + + + +Fanebladet med kanallisten. + + + + + + + + + + + + + + + + Fanebladet med kanallisten. + + + + + + + + +Indtast en filterstreng her. + +Her kan du begrænse kanallisten til de kanaler som har et minimalt eller maksimalt antal brugere. At vælge 0 deaktiverer det respektive kriterium. + +Klik her for at hente listen over kanaler fra serveren og tilpasse filtret. + +Den filtrerede liste med kanaler vises her. Bemærk at hvis du ikke bruger regulære udtryk, giver &konversation; en liste over alle kanaler hvis navn indeholder filterstrengen som du indskrev. Kanalnavnet behøver ikke begynde med strengen du skrev. + +Vælg en kanal som du vil gå med i ved at klikke på den. Højreklik på kanalen for at få en liste med alle netadresser som nævnes i kanalens emne. + +Klik her for at gå med i en kanal. Et nyt faneblad laves for kanalen. + + + + +Du skal undgå at klikke på knappen Genopfrisk liste. De fleste servere har tusindvis af kanaler, og udførsel af dette giver høj belastning på serveren. Desuden kan det kræve flere minutter at udføre, afhængig af din netværksbåndbredde. Hvis din klient er for langsom, kan serveren til og med afbryde forbindelsen til dig. + +Sommetider er der "hemmelige" kanaler på en server. Sådanne kanaler kommer ikke på Kanallisten. Du kan stadigvæk gå med i kanalerne hvis du kender til deres navn. Skriv i en hvilken som helst indtastningslinje, /join #kanalnavn. (Tegnet # kræves.) Så laves et nyt faneblad for kanalen. Hvis du går med i en kanal og aliaspanelet kun har dit alias, betyder det at kanalen ikke fandtes tidligere. Serveren oprettede kanalen, og du er operator. I dette tilfælde vil du formodentlig lukke kanalen ved at skrive: /part. + + + + + + +En oversigt over hovedskærmen + +Lad os lære mere om hovedskærmen. Skærmen vises nedenfor med en kanals faneblad valgt. + + + +Hovedskærmen. + + + + + + + + + + + + + + + + + + + Hovedskærmen + + + + + + + + +Dette kaldes indtastningslinjen. Den vises kun hvis det nuværende faneblad er en kanal. For at sende en meddelelse til alle i kanalen, skrives meddelelsen og der trykkes på &Enter;. Meddelelsen samt alle andres meddelelser ses i kanalvinduet ovenfor. Hver meddelelse indledes med tiden og brugerens alias. + + Du kan også indsætte tekst fra klippebordet. Hvis indsat tekst har mere end én line (newlines), kommer en dialog frem. Redigér teksten som ønsket og klik på O.k. + + Hvis den indsatte tekst er længere end 256 tegn, eller den indeholder mere end en linje, kommer en advarselsbesked frem, der fortæller dig at store indsendelser kan forårsage nulstilling af forbindelsen og oversvømmelse. Du kan stadig fortsætte med din meddelelse, men det er en dårlig idé at gøre det, da oversvømmelse vil irritere andre brugere på kanalen, eller din forbindelse til serveren kan blive afbrudt. Det er bedre at sende beskederne i mindre stumper. + + + + En konvention som bruges i mange kanaler er at indlede meddelelser rettede til en bruger med deres alias. &konversation; sørger for en bekvem funktion til at komplettere aliasser. Begynd med at skrive brugerens alias, tryk derefter på Tab. &konversation; kompletterer så resten af brugerens alias, fulgt af et kolon. For at brugerindstille kompletteringsegenskaben, vælges Opsætning Indstil Konversation fra hovedmenuen, udvid Opførsel, klik på Generelt, og klik på feltet Kompletteringstilstand. + + Du kan også indtaste &irc;-kommandoen her ved først at skrive / fulgt af en gyldig &irc;-kommando. Se Ofte brugte &irc;-kommandoer. På visse servere kan du skrive /help for at få en liste over tilgængelige kommandoer, eller skrive /help kommando for at få hjælp med en angiven kommando. + + + +Du kan gå med i yderligere servere og kanaler. Hver server og kanal får et separat faneblad her. For at vise en liste over tilgængelige kanaler, se Liste over tilgængelige kanaler. For at gå med i en kanal, skriv: /join #kanalnavn på inddatalinjen. (Tegnet # kræves.) For at forlade en kanal, skrives blot /part. Faneblade vises også her hvis du åbner en Kanalliste, deltager i en privat konversation (query), åbner &URL;-indfangeren, eller åbner en eller flere Terminaler. For at skifte til en anden skærm, klikkes på det tilsvarende faneblad, eller musehjulet bruges til at gå gennem fanebladene cyklisk. + +For at indstille andre tilvalg for faneblade, vælg Opsætning Indstil Konversation i hovedmenuen, udvid Opførsel og klik på Generelt. + + + +Disse lys vil blinke når der er noget du ikke har set i dette faneblad. Lyset vil blinke langsommere når de eneste ikke sete beskeder er join, part, quit, eller alias ændringer. De blinker hurtigere hvis der er ikke sete regulære beskeder. Farverne er følgende: + + Kanal + + + Servermeddelelse, Kanalliste eller &URL;-indfangning + + + Terminal eller DCC Status. + + + Privat meddelelse (forespørgsel). + + + + +Klik her for at lukke nuværende faneblad. Hvis et kanalfaneblad lukkes forlades kanalen. Lukkes et faneblad med servermeddelelser forlades alle kanaler som du var gået med i, alle åbne spørgsmålskanaler på serveren lukkes og serveren afbrydes. + +Klik på knappen for at ændre dit eget alias. Det vises kun når nuværende faneblad er en kanal. Vælg Opsætning Indstil Konversation i hovedmenuen, udvid Opførsel, klik på Chat-vindue og afmarkér feltet Vis felt til at ændre eget alias for at skjule knappen. + +Kanalemnet vises her. Hold musen stille over emnet for at se det lange emne. Du kan ændre emnet ved at klikke på knappen til venstre for emnet. Vælg Opsætning Indstil Konversation i hovedmenuen, udvid Opførsel, klik på Chat-vindue og afmarkér feltet Vis kanalemne for at skjule kanalemnerne. + +Disse knapper viser nuværende status af kanaltilstande. En knap er trykket ned hvis tilstanden er aktiveret. Hvis du har de rette privilegier kan du også ændre kanaltilstande ved at klikke på knapperne, eller ved at klikke på knappen til venstre for emnet. Vælg Opsætning Indstil Konversation i hovedmenuen, udvid Opførsel, klik på Chat-vindue og afmarkér feltet Vis kanaltilstandsknapper for at skjule kanaltilstandsknapperne. + + +Dette kaldes alias panelet. Det vises så snart det nuværende faneblad er en kanal. Det lister aliasserne for alle brugere som er gået med i kanalen, inklusive dig selv. Hold musen stille over et alias for at vise yderligere information om brugeren. Du kan ændre hvordan ikoner vises ved siden af hvert alias ved at ændre ikontemaet for alias. Se Indstil aliasstemaer for mere information. Temaet Big Bullets, som vises på skærmen ovenfor, bruger følgende ikoner: + + + normale brugere + + + + brugere med stemme. Brugeren kan tale i en modereret kanal. + + + + deloperator for kanalen + + + + operator for kanalen + + + + ejer af kanalen + + + + kanaladministrator + + + + + +Derudover, hvis en bruger er borte, vil et lille rødt kryds blive tegnet i hjørnet af ikonen. + +Klik med højreknappen på et hvilket som helst alias for at vise en sammenhængsafhængig menu med handlinger som du kan udføre med aliasset. Du kan for eksempel sende en fil til aliasset. Dette er også stedet hvor du kan knytte et alias til en kontakt i din adressebog. + +For at skjule alias panelet, vælg Vindue Skjul aliasliste i hovedmenuen. + + + +Disse kaldes Hurtigknapper. Normalt vises de ikke. For at vise dem, se Indstil hurtigknapper. Du kan indstille deres definitioner til hvilken som helst kommando du vil. + + + + +Bemærk: Du kan kontrollere hvordan meddelelser vises for meddelelser som vises i kanal- og forespørgselsfaneblade. Du kan for eksempel ændre meddelelsens farve, afspille en lyd når en meddelelse som indeholder en streng modtages, eller svare på meddelelser automatisk. Se Fremhævning af meddelelser for mere information. + +Bemærk: Kanalnavne begynder sommetider med &, +, eller !. Det første tegn i et kanalnavn afgør typen af kanal (RFC 2811) ifølge følgende: # - Sædvanlige kanaler. ! - Sædvanlige kanaler. & - Lokal. Kanaler som man kun kan gå med i fra serveren som er vært for kanalen. Alle andre kanaler kan man gå med i fra en hvilken somhelst server på netværket. + - Kanaler som ikke understøtter kanaltilstande. Det betyder at ingen tilstande er aktiverede, med undtagelse af kanalflaget 't' som er aktiveret. Kanalnavne kan være op til 50 tegn lange og indeholde alle tegn undtagen mellemrum, kommategn og Ctrl+G. + + + + + + +Hurtigforbind + +Sommetider ønsker du at forbinde til en server uden at gå gennem besværet med at oprette en ny server i Serverlisten. + +Vælg Fil Hurtigforbindelse i hovedmenuen. Skærmen Hurtigforbindelse vises. + + + +Hurtigforbins-skærmen. + + + + + + Hurtigforbind-skærmen + + + + + +Indtast serveradressen i feltet Server-vært box, dit ønskede &nickname; i Nick-feltet, og klik på Forbind-kanppen. Når &konversation; er forbundet til serveren, indtastes kommandoen /join #channelname for at gå med i en kanal. + + + + + + +Ofte brugte &irc;-kommandoer + +Det følgende er en kort liste over ofte brugte &irc;-kommandoer. Se RFC 2812 for en fuldstændig liste over alle kommandoer, eller besøg irchelp.org. For en liste af kommandoer der behandles specielt af &konversation;, se Konversations kommandoer + + + + + +/help +Giver en liste over kommander tilgængelige på denne server. Understøttes ikke af alle servere. + + + +/help kommando +Sørger for hjælp for kommando. Understøttes ikke af alle servere. + + + +/join #kanal +Går med i #kanal. Hvis kanalen ikke allerede findes, oprettes den og du bliver kanaloperator. + + + +/part +Forlader nuværende kanal og lukker kanal-fanebladet . + + + +/part #kanal +Forlader #kanal og lukker det tilsvarende kanal-faneblad. Synonym for /leave. + + + +/me meddelelse +Sender meddelelse til kanalen ud for dit alias. Hvis dit alias for eksempel er Tux, ville meddelelsen Tux brygger en kop te vises ved at skrive /me brygger en kop te. Hvis der ikke er filtre for denne slags meddelelser, ser alle brugere dem. Denne slags meddelelser bruges oftest til at udtrykke ikke-verbal information, såsom din følelsesmæssige tilstand lige nu, eller hvad du fysisk sysler med. Hvis du forlader maskinen en kort stund, så brug kommandoen /away i stedet for. + + + +/away meddelelse +Hvis nogen forsøger at sende dig en privat meddelelse eller indbyde dig til en kanal, vil de blive fortalt at du er borte fra din maskine med msg. + + + +/away +Annullerer en /away meddelelse kommando. + + + +/query alias +Opretter et nyt faneblad med brugerens alias for en privat konversation, almindeligvis kendt på &irc; som en forespørgsel. Alt som skrives her ses kun hos dig og din partner. + + + +/msg alias meddelelse +Sender meddelelse til brugeren med alias alias. Kun alias ser meddelelsen. Brug /query til længere konversationer. + + + +/invite alias +Indbyder brugeren med alias alias til at gå med i en kanal. Kommandoen er især nyttig hvis kanalen kun er åben for indbudte. + + + + + + + + + + +Private konversationer (forespørgsler) + +En privat konversation er en som kun du og en anden person kan se. Private konversationer kalde "forespørgsler" i &konversation;. For at starte en privat konversation, skrives /query alias på en hvilken som helst indtastningslinje, hvor alias er alias på personen som du vil tale med. Du kan også klikke med højre museknap i aliaspanelet og vælge Åbn forespørgsel. Et nyt faneblad oprettes.. Tilkendegiv dig ved at sende en meddelelse. + +Forespørgsler er nøjagtig ligesom andre kanaler, bortset fra at kun du og den anden person kan deltage i kanalen. + +For at forlade forespørgslen, lukkes blot fanebladet. Bemærk dog at hvis den anden person sender en meddelelse til i forespørgslen, åbnes fanebladet igen. + +For at forlade alle forespørgsler, vælges Vindue Luk alle åbne forespørgsler i hovedmenuen, eller tryk på F11. + +Når en anden åbner en forespørgsel til dig, laver &konversation; et nyt faneblad med deres alias. Hvis du ikke vil tale med personen, så luk fanebladet. + + + + + + +Indstil påmindelser + +Påmindelser er handlinger som &konversation; udfører så snart en begivenhed indtræffer. Antag at du lader &konversation; køre, men minimeret eller skjult bagved andre programvinduer på desktoppen. Hvis nogen vil kommunikere med dig, eller hvis en ven går med i en kanal, vil du gerne have det at vide. Bekendtgørelser dørger for dette. + +For at indstille påmindelser, vælges Indstillinger Indstil bekendtgørelser i hovedmenuen. Skærmen til opsætning af bekendtgørelser vises. + +Klik med det samme på knappen Flere valgmuligheder. + + + +Skærmen til opsætning af bekendtgørelser. + + + + + + + + + + + + + Skærmen til opsætning af bekendtgørelser. + + + + + + + + +Klik her for at vælge en begivenhed. + +Markér de typer af påmindelser som du vil skal vises når begivenheden indtræffer. (Brug opgavelinjen til underretning om ny begivenhed får ikonen i opgavelinjen til at blinke når begivenheden indtræffer.) + + + + +Gentag ved at vælge en anden begivenhed og afkrydse ønsket påmindelse. Når du har indstiller alle ønskede påmindelser, klik så på knappen Anvend. + + + + +Når du har indstillet dine påmindelser, kan du aktivere eller deaktivere alle meddelelseshandlinger her. Du kan for eksempel vælge at afspille en lyd så snart dit alias nævnes i en meddelelse. Når du er ved computeren kan du deaktivere lyd, men mens du er væk fra maskinen men i nærheden, kan du aktivere lyden så den kan få din opmærksomhed. + + + + +Du kan også selv blive underrette når nogle nævner dit alias i en meddelelse med &konversation;s fremhævningsfunktion. + + + + + + +Overvåg hvem der er på nettet + +&konversation; holder dig informeret om dine venner er forbundet til &irc;-netværket eller ej. + +Du kan tilknytte online aliasser til kontaktindgange i adressebogen. Når du gør det, skrives aliasset og &irc;-netværket hvor aliasset er forbundet til ind i adressebogens kontakt. &irc;-netværket opbevares fordi aliasser er entydige i et enkelt &irc;-netværk. Aliasser i to forskellige &irc;-netværk svarer ikke nødvendigtvis til samme person, men samme alias på to forskellige servere i samme &irc;-netværk svarer til samme person. + +Dette er grunden til at det er vigtigt at bruge samme netværk for alle servere i samme &irc;-netværk, når netværk, servere og kanaler til automatisk at gå med i defineres. + +Du kan også definere aliasser som du vil overvåge som ikke findes i din adressebog. I dette tilfalde har hvert alias også et tilknyttet &irc;-netværk. Se nedenfor. + +For at aktivere aliasovervågningsfunktionen, vælges Vindue Overvågede aliasser i hovedmenuen. Skærmen Overvågede aliasser vises. + + + + Overvågede online aliasser. + + + + + + + + + + + + + + + + Overvågede online alias + + + + + + + +Aliasserne i overvågningslisten og også aliasset som hører sammen med indgange i adressebogen angives her. De angives under tilhørende &irc;-netværk. Hvis ingen alias angives, har du enten ikke specificeret noget alias at overvåge, eller du har brug for at aktivere funktionen for aliasovervågning (se nedenfor). Ekspandér hvert online alias for at se en liste med kanaler som aliasset er gået med i. Ikonerne før hver kanal er de samme som ikonerne som vises i aliaspanelet på skærmene med kanaler. +Informationen som er kendt om aliasset vises her. Når skærmen Overvågede online aliasser først vises, er informationen tynd. Hvert ottende sekund, sendes automatisk kommandoen WHOIS til serveren for at bede om information om aliasser som ikke har nogen information. Dette fortsætter indtil alle aliasser har information. +Aliasser som ikke er online på et af &irc;-netværkerne du er forbundet til er under Offline i listen. +Aliasser som hører sammen med en kontaktindgang i din adressebog har denne ikon () ved siden af informationen. +Brug disse knapper til at tilknytte et alias til en kontakt i din adressebog, fjerne en tilknytning, eller åbne adressebogen for at redigere kontaktinformationen. Se &kaddressbook;-håndbogen for yderligere instruktioner om hvordan man bruger &kde;'s adressebog. + + + +For at tilføje yderligere aliasser at overvåge, klik på knappen Redigér overvågningsliste. Så vises skærmen Overvågede aliasser. + + + +Overvågede aliasser + + + + + + + + + + + + + + + Overvågede aliasser + + + + + + + + +Afkryds dette felt for at aktivere funktionen aliasovervågning. + +Hvis du ønsker at skærmen Overvågede online aliasser automatisk skal vises når du starter &konversation;, så markér dette felt. + +Aliasserne for på brugerne som du vil overvåge er på denne liste. Hvert alias har et tilknyttet &irc;-netværk. + +Klik på disse knapper for at tilføje eller fjerne at alias fra listen. + +Funktionen Overvågede aliasser virker ved at periodisk at spørge serveren. Dette felt angiver hvor ofte dette sker. Undgå tal mindre end 20 sekunder, eftersom det forårsager unødig stor belastning på serveren. + +På skærmen Overvågede online aliasser ovenfor, kan du dobbeltklikke på et hvilket som helst alias, så sendes denne kommando til serveren. %u erstattes med aliasset. %n er krævet i slutningen af kommandoen. + + + + +Klik på knappen O.k. når du er færdig med at tilføje eller fjerne aliasser. + +Bemærk: Når du viser skærmen Overvågede aliasser, kan det tage et stykke tid inden nogen aliasser vises, indtil &konversation; har spurgt serveren. Normalt lader du skærmen Overvågede aliasser være i gang. + +&konversation; viser også meddelelser i alle kanaler så snart en bruger fra din Overvågede aliasser forbindes til eller afbryder fra serveren. Meddelelsen ser sådan her ud: + +[17:52] [Underretning] psn er online (irc.kde.org). + + + + + + +Fremhævning af meddelelser + +Du kan kontrollere hvordan meddelelser vises på kanal- og forespørgselsskærme. + +For at aktivere fremhævelsesfunktionen, vælges Indstillinger Indstil &konversation; i hovedmenuen. Skærmen Redigér indstillinger vises. + + + +Fremhævningsskærmen. + + + + + + + + + + + + + + + + + + + Fremhævelsesskærmen + + + + + + + + +Klik her for at vælge skærmen Fremhævelse. +Klik her for at tilføje et nyt punkt til Fremhævningslisten. Når et punkt i listen markeres, kan du redigere det i feltet nedenfor. +Indtast et strengmønster her. Alle modtagne meddelelser som matcher mønstret, noget sted i meddelelsen, aktiverer fremhævning af meddelelsen. Hvis du har værktøjet &kde;editor for regulære udtryk installeret på systemet, er knappen til højre aktiveret. Klik for at vise editoren, som hjælper dig med at oprette mere komplicerede mønstre. (&kde;editor for regulære udtryk er en del af pakken kdeutils.) +Hvis mønstret findes i en meddelelse, vises hele meddelelsen med farven du vælger her. +Hvis du vil kan &konversation; afspille en lyd når mønstret matches. Klik på knappen for at vælge en lydfil at afspille. Klik på testknappen for at høre lyden. +Hvis du ønsker at &konversation; automatisk skal sende en svarmeddelelse når mønstret matches, skriv meddelelsen her. Brug denne funktion med forsigtighed eftersom du kan irritere &irc;-brugere med for meget snak hvis du ikke er forsigtig. Du kan også indtaste &irc;- eller &konversation;-kommandoer her. +Hvis du har indstillet lyd for nogle af dine fremhævninger, kan du deaktivere alle ved at afmarkere dette felt. +Hvis du markerer dette flet, og en eller anden nævner dit alias i en meddelelse, vises meddelelsen med farven som du vælger til højre. +Normalt gælder fremhævning ikke for meddelelser du skriver ind. Hvis du vil fremhæve meddelelser du skriver ind, markeres dette felt og en farve vælges til højre. + + + + + + + + + +Indstil meddelelser på skærmen (&osd;) + +Meddelelser på skærmen (OSD) er en unik funktion i &konversation;. Når &osd; er aktiveret, vises kanalmeddelelser på desktoppens skærm, også selvom &konversation; er minimeret. Her er et eksempel på &osd; i funktion. Meddelelsen længst oppe til venstre på skærmen er fra &konversation;, som kører minimeret i statusfeltet. + + + +Eksempel på meddelelser på skærmen + + + + + + Eksempel på meddelelser på skærmen + + + + + +For at aktivere meddelelser på skærmen, vælges Indstillinger Indstil &konversation; i hovedmenuen. Skærmen Redigér indstillinger vises. + + + +Meddelelser på skærmen. + + + + + + + + + + + + + + + Meddelelser på skærmen + + + + + + + + +Klik her for at ekspandere punktet Påmindelse. + +Klik her for at vælge skærmen Meddelelser på skærmen. + +Markér dette felt for at aktivere meddelelser på skærmen. + +Klik på denne knap for at vælge en skrifttype for meddelelser på skærmen. (Bemærk: Ikke alle skrifttyper virker. Det er kendt at Luxi Sans 22 og Impact 22 virker.) + +Markér feltet her for at vælge typerne af meddelelser som du vil skal vises på skærmen, og klik derefter på knappen Anvend. + + + + + + + + + +Send farvelagte meddelelser + +Du kan tilføje farve til meddelelser du sender i hvilken som helst kanal. Begynd med at skrive meddelelsen i indtastningslinjen for hvilken som helst kanal. Klik så på knappen Indsæt &irc;-farve knappen Indsæt &irc;-farve eller vælg Indsæt &irc;-farve i hovedmenuen. Skærmen &irc;-farvevælger vises. + + + +Skærmen &irc;-farvevælger. + + + + + + Skærmen &irc;-farvevælger + + + + + +Vælg en farve og klik på O.k. Fortsæt med at indtaste meddelelsen på indtastningslinjen. For at ændre farve igen, klikkes på knappen Indsæt &irc;-farve. Vælg en anden farve og klik på O.k. + + + + + + +Indstilling af &nickname;-temaer + +Du kan ændre ikonerne som vises ved siden af alias i aliaspanelet i kanalfanablade. For at ændre aliastema, vælg Opsætning Indstil Konversation i hovedmenuen. Skærmen Redigér indstillinger vises. Klik på Udseende for at udvide den, klik derefter på Temaer for at vis skærmen Temaer. + + + +Temaer-kærmen. + + + + + + + + + + + + + + Temaer-skærmen + + + + + + + + +Klik her for at vælge skærmen Temaer. +Vælg et tema. +Eksempelikoner vises her med det valgte tema. +Hvis du har hentet et aliastema far et andet sted, så klik for at installere det. + + + + + + + + + +Indstil hurtigknapper + +Du kan aktivere funktionen at vis hurtigknapperhovedskærmen. Så vises otte hurtigknapper. For at vise hurtigknapperne, vælg Opsætning Indstil Konversation i hovedmenuen. Skærmen Redigér indstillinger vises. Klik på Udseende for at udvid den, og klik så på Chat-vindue. Markér feltet Vis hurtigknapper og klik på O.k. + +Knapperne kan indstilles som du synes til at udføre &irc;-kommandoer som ofte bruges. For at indstille hurtigknapperne, vælg Opsætning Indstil Konversation i hovedmenuen. Skærmen Redigér indstillinger vises. Klik på Udseende for at udvide den, og klik så på Hurtigknapper for at vise skærmen Hurtigknapper. + + + +Skærmen hurtigknapper + + + + + + Skærmen hurtigknapper + + + + + +Der er otte hurtigknapper. Klik på en indgang for at ændre den. Søjlen Knapnavn er navnet som vises på knappen på hovedskærmen. Hold navnene korte. Søjlen Knapbegivenhed er handlingen som udføres når du klikker på hurtigknappen. Vink til at oprette handlinger gives på skærmen. + +Klik på O.k. for at gøre ændringerne færdige. + +Eksempel: + + + + + Knapnavn: Meddelelse + + Knapbegivenhed: Msg %u (der er et mellemrum efter %u) + + + + + +For at bruge denne knap på hovedskærmen, klikkes på et alias i aliaspanelet, og derefter klikkes på knappen. /MSG vises på indtastningslinjen fulgt af det valgte alias. Indtast en meddelelse som du vil sende til personen og tryk så på &Enter;. Meddelelsen sendes til brugeren. Kun denne bruger vil se meddelelsen. + +Bemærk: Du kan ikke tilføje eller fjerne hurtigkanpper. + + + + + + +Sende og modtage filer + +Du kan sende filer via &irc; til andre brugere der er forbundet, eller også kan de sende filer til dig. + + +Advarsel: Åbn aldrig en fil nogen sender til dig hvis det ikke er en pålidelig kilde. Det kan være en virus. + + +For at sende en fil til en i en kanal, klikkes med højre museknap på personens alias i aliaspanelethovedskærmen. Vælg Send fil. En dialog kommer frem hvor du kan vælge filen som skal sendes. Derefter vises et nyt faneblad med DCC Status. + + + +Fanebladet DCC Status + + + + + + + + + + + + + Fanebladet DCC Status + + + + + + + + +Modtagerens alias og filnavnet vises her. + + +Søjlen Status angiver status for sendingen eller modtagelsen af filen som følger: + + + + + + Tilbyder + + + Du forsøger at sende en fil til modtageren. &konversation; venter på at modtageren skal acceptere filen. + + + + + Forbinder + + + &konversation; forsøger at oprette en forbindelse med den anden ende. + + + + + Sender + + + &konversation; sender filen til den anden ende. + + + + + Modtager + + + &konversation; modtager filen fra den anden ende. + + + + + Færdig + + + Filen er overført uden problemer. + + + + + Hænger + + + Overførslen er startet men går for øjeblikket ikke videre. + + + + + Afbrudt + + + Enten klikkede du på knappen Afbryd, eller også afbrød den anden person overførslen. + + + + + Mislykket + + + En fejl opstod og overførslen lykkedes ikke. + + + + + I kø + + + Overførslen er blevet accepteret og vil begynde når programmellet på den modtagende ende anerkender det. + + + + + Slå op + + + &konversation; forsøger at hente afsenderens IP-adresse. + + + + + Genoptager + + + Når en overførsel begynder men filen allerede findes på brugerens system, vil brugeren blive spurgt Filen eksisterer allerede. Genoptag overførsel? Denne status indikerer at brugeren genoptog overførslen. + + + + + + + + +Når nogen vil sende en fil til dig, oprettes fanebladet DCC Status (hvis det ikke allerede er der). Klik på fanebladet DCC Status for at vise det. Klik på filen for at markere den, og klik derefter på denne knap for at acceptere filen, så begynder overførslen. Bemærk: Du kan indstille &konversation; til automatisk at acceptere overførsler fra andre personer ved at vælge Indstillinger Indstil Konversation DCC-indstillinger i hovedmenuen. + + + + + +Hvis du har problemer med at sende eller modtage filer, så er det måske din brandmur der blokerer DCC-portene. Se Spørgsmål og svar. + + + + + + +Integration med &kaddressbook;. + +Du kan tilknytte ethvert &nickname;til en kontakt i KAddressBook. Når du har gjort dette vil &konversation; vise kontaktens rigtige navn i parentes efter &nickname; i Alias-Panelet. + +For at tilknytte et alias til en kontakt i adressebogen, klikkes med højreknappen på personens alias i aliaspanelethovedskærmen. Vælg Hvem-er-det for at vise information som hjælper dig til at afgøre brugerens rigtige navn. Klik derefter med højreknappen på personens alias og vælg Adressebogstilknytninger. En undermenu vises. Hvis aliasset ikke allerede er tilknyttet en kontakt, vælges Opret ny kontakt. Skærmen Redigér kontakt vises. + + + +Skærmen Redigér kontakter + + + + + + + + + + + + + Skærmen Redigér kontakter + + + + + + + + +Aliasset udfyldes automatisk her. Hvis du kender personens rigtige navn, erstattes aliasset med det rigtige navn. + + +Bemærk at aliasset ikke vises her. I stedet, ... + + + +Klik her. Fanebladet IM-adresser-vinduet kommer frem. + + + + + + + Vinduet IM-adresser. + + + + + + Vinduet IM-adresser. + + + + + +Bemærk at &konversation; udfylder aliasset for dig med protokollen &irc;. + +Se &kaddressbook;'s håndbog for yderligere instruktioner om hvordan man bruger &kde;s adressebog. + +Udfyld mulig yderligere information om aliasset du kender til og klik på O.k. Personens rigtige navn vises i parenteser foran aliasset i Aliaspanelet i &konversation;. Det rigtige navn vises også når musen holdes stille over aliasset. + +Så snart et alias er knyttet sammen med en kontakt i adressebogen, kan du højreklikke på personens alias i Aliaspanelet og redigere den tilknyttede kontakt, knytte aliasset sammen med en anden kontakt, eller fjerne tilknytningen. + +Hvis du har tilknyttet et alias til en kontakt, og brugeren ændrer sit alias mens du kører &konversation;, tilknyttes det nye alias automatisk til kontakten, og desuden beholdes den oprindelige tilknytning. + +Hvis du knytter et alias i &irc; til en kontakt i Kopete, vises også tilknytningen i &konversation; og modsat. + +Bemærk: Det er muligt at markere mere end et alias i Aliaspanelet, klik med musens højre knap, og udfør flere tilknytninger. + + + + + + +Indfangning af &URL;'er fra meddelelser + +Brugere sender ind imellem &URL;'er for interessante steder eller andre ressourcer på nettet, i hvilken som helst kanal. Du kan dobbeltklikke på alle sådanne &URL;'er så starter &konversation; programmet som hører sammen med &URL;'en. Programmet som startes afhænger af &MIME;-typen som &URL;'en har. For eksempel aktiveres din almindelige browser for en &URL; som begynder med http:, og viser den. Hvis &URL;'en ruller forbi på skærmen, kan det være svært at finde den igen. &konversation; kan gemme en bekvem liste med alle &URL;'er for dig. For at aktivere denne funktion, vælges Vindue &URL;-indfangning i hovedmenuen. Et nyt faneblad som hedder &URL;-indfangning laves. + + + +Fanebladet &URL;-indfangning. + + + + + + + + + + + + + + + + Fanebladet &URL;-indfangning. + + + + + + + + +Dette er listen med &URL;'er som er set siden du startede &konversation;. Søjlen Alias er alias på personen som sendte &URL;'en. Hvis alias er blankt, blev &URL;'en vist i fanebladet Servermeddelelser. (&URL;'er som vises i meddelelser for at gå med i eller forlade kanaler er ikke på listen.) Klik på en &URL; for at markere den. + +Klik her for at aktivere programmet som hører sammen med den markerede &URL;. Programmet som startes afhænger af &MIME;-typen som &URL;'en har. For eksempel aktiveres din almindelige browser for en &URL; som begynder med http:, og viser netsiden. For netsider kan du også specificere den browser der skal bruges. + +Klik her for at kopiere markeret &URL; til &kde;'s klippebord. + +Klik her for at slette markeret &URL; fra listen. + +Klik her for at gemme listen med &URL;'er i en fil. + +Klik her for at rydde listen. + + + + + + + + + +Opsætning af din foretrukne browser + +Når du klikker på en fremhævet &URL; hvorsomhelst i &konversation;, vil den starte standardprogrammet i &kde; tilknyttet &MIME;-typen for denne &URL;. For eksempel, når der klikkes på en &URL; der begynder med http, startes &konqueror; for at vise netsiden. Du kan angive et andet program end &kde;'s standard. For eksempel, kan du bruge Mozilla i stedet for. + +For at vælge en anden browser, vælges Opsætning Indstil &konversation; i hovedmenuen. Skærmen Redigér indstillinger vil så komme frem. + + + +Browser-skærmen + + + + + + + + + + + + + Browser-skærmen + + + + + + + + +Klik her for at vise skærmen Browser. + +Klik her for at angive at du ønsker at bruge en selvvalgt browser. + +Indtast kommandoen til at starte din ønskede browser. Når du klikker på en &URL; vil %u blive erstattet med &URL;'en. + + + + +Vink: (kun for &UNIX;-systemer) Standardkommandoen er mozilla '%u', hvilket vil starte en ny udgave af Mozilla hver gang du klikker på en &URL;. Hvis du foretrækker at Mozilla viser netsiden i et nyt faneblad af en allerede-kørende udgave, så lav en fil der indeholder følgende: + + +#!/bin/sh +mozilla -remote "openURL($@, new-tab)" || exec mozilla "$@"; + + + +Navngiv filen moz, placér den i din PATH, og gør den kørbar (chmod a+x moz). Skriv så moz '%u' for browser-kommandoen i skærmen ovenfor. + +Bemærk: Browser-opsætningen kommer ikke til at gælde mailto: &URL;'er. mailto: &URL;'er starter altid &kde;s standardprogram. + +Klik på Anvend for at gemme dine ændringer. Du skal forbinde til hver server igen for at alle ændringer skal få virkning. Den nemmeste måde at gøre det er at afslutte &konversation; og starte forfra. + + + + + + +Markering af kanaler og forespørgselslogger + +Du kan indsætte en markering i channel og query skærmene for at hjælpe dig til hurtigt at finde information. For at gøre dette vælg Indsæt Huskelinje i hovedmenuen, eller tryk på &Ctrl;R. En linje vil så komme frem for neden af teksten på skærmen. Linjen vil rulle med resten af teksten på skærmen. + +For at få en Huske-linje til at blive indsat i alle kanaler og spørgsmål samtidigt, vælges Indstillinger Indstil Konversation i hovedmenuen, ekspandér Opførsel, klik på Chat-vindue og markér feltet Vis en huske-linje for alle kanaler og spørgsmål. + +For at få &konversation; til automatisk at indsætte en huske-linje så snart du sender kommandoen /away meddelelse, se Opsætning af din identitet. + + + + + + +Logning + +Hvis logning er aktiveret, logger &konversation; hver server, kanal og privat konversation (spørgsmål). Hver session opbevares i en logfil på disken. Når du åbner samme session igen, tilføjer &konversation; til loggen. Loggen vokser til en grænse som du kan indstille (se nedenfor). Når grænsen nås, kasseres de ældste meddelelser. + +Så snart du åbner en session igen, læses cirka de sidste 1024 tegn af foregående session fra slutningen af loggen og vises på skærmen. + +Mens sessionen er i gang, ruller meddelelser væk højst oppe på skærmen. Du kan rulle baglæns for at se disse meddelelser. Før eller siden, for at spare hukommelse, tages de ældste meddelelser væk fra skærmen. Dette kaldes for historikgrænsen. Meddelelser som forsvinder fra skærmen på grund af denne historikgrænse er stadigvæk tilgængelige i logfilen, hvis logning er aktiveret. + +For at vise logfilen for en session, klikkes på sessionens faneblad for at gøre den til aktuel session og så vælges Vindue Åbn logfil i hovedmenuen. Et nyt faneblad åbnes som viser logfilen. + + + +Logfil + + + + + + + + + + + + + + + Logfil + + + + + + + +Meddelelser fra logfilen vises her. De ældste meddelelser er højst oppe og de seneste forneden. +Klik på denne knap for at gemme logfilen til en anden fil. +Klik for at opdatere visningen af logfilen. Mens du kigger på en logfil, tilføjes nye meddelelser i tilsvarende session ikke automatisk til visningen af logfilen. Brug denne knap for at kigge på de seneste meddelelser. +Klik for at rydde skærmen med logfilen og fjerne logfilen på disken. +Brug dette felt til at indstille maksimal størrelse på logfilen. Indstillingen får ingen effekt førend du genstarter &konversation;. Hver logfil kan have en separat indstilling. + + + +Historikgrænsen kan ændres ved at vælge Indstillinger Indstil &konversation; i hovedmenuen, og derefter ekspandere Opførsel og klikke på Chat-vindue. Feltet Historikgrænse vises så på skærmen. Hvis du indstiller den til Ubegrænset, tages meddelelser ikke bort fra skærmen. + +Du kan aktivere eller deaktivere logning og indstille andre logningstilvalg ved at vælge Indstillinger Indstil &konversation; i hovedmenuen, og derefter ekspandere Opførsel og klikke på Logning. + + + + + + +&konversation;'s kommandoer + +Følgende kommandoer tolkes af &konversation; og kan være forskellige fra almindelige &irc;-kommandoer. Flag indenfor forkantede parenteser er valgfrie. Flag adskilte med en lodret streg (|) er forskellige former af kommandoen. Kommandoer som ikke er på denne liste, sendes til serveren som de skrives ind. + + + + + +/me meddelelse +Sender meddelelse til kanalen ud for dit alias. Hvis dit alias for eksempel er Tux, ville meddelelsen Tux brygger en kop te vises ved at skrive /me brygger en kop te. Hvis der ikke er filtre for denne slags meddelelser, ser alle brugere dem. Denne slags meddelelser bruges oftest til at udtrykke ikke-verbal information, såsom din følelsesmæssige tilstand lige nu, eller hvad du fysisk sysler med. Hvis du forlader maskinen en kort stund, så brug kommandoen /away i stedet for. + + + +/ame meddelelse +Ligesom kommandoen /me ovenfor, undtagen at meddelelsen sendes til alle kanaler og forespørgsler som er åbne på alle servere du er tilsluttet i &konversation;. + + + +/join kanal [pwd] +Går med i kanal. Hvis serveren tillader det, og hvis kanalen ikke allerede findes, laves den og du bliver kanaloperator. Hvis kanalen kræver et kodeord for at gå med, angives det som kodeord. De fleste kanalnavne begynder med #. + + + +/j kanal [pwd] +Samme som /join ovenfor. + + + +/part [kanal] [grund] +Forlader kanal med grund og lukker tilsvarende kanalfaneblad. Inde i en &konversation; kanal eller et forespørgselsfaneblad, kan du kun indtaste /part hvilket lukker kanalen eller forespørgslen med din standardbegrundelse som angivet i Indstillinger. + + +/leave [kanal] [grund] +Samme som /part ovenfor. + + +/quit +Når dette indtastes i et kanalfaneblad, forespørgselsfaneblad eller DCC-faneblad, afbrydes forbindelsen til den tilsvarende server og alle kanalfaneblade, forespørgselsfaneblade eller DCC-faneblade som er åbne for denne server lukkes. + + +/notice alias|kanal msg +Sender meddelelse til brugeren med aliasset alias eller til alle i en kanal. Det følgende er et eksempel på hvad du ser i kanalfanebladet + +[17:14] [Notits] Sender meddelelse "Jeg tror jeg forstår" til #konversation + +Og dette er hvad modtagerne ser + +[17:15] [Notits] -Eisfuchs- Jeg tror jeg forstår + + + + +/query alias +Opretter et nyt faneblad med brugerens alias for en privat konversation, almindeligvis kendt på &irc; som en forespørgsel. Alt som skrives her ses kun hos dig og din partner. Du kan indtaste mere end et &nickname; adskilt af mellemrum og et forspørgselsfanebald for hvert &nickname;. Hver sådan forespørgselsfaneblad vil være privat mellem dig og den forespurgte partner. + + + +/msg alias|kanal meddelelse +Sender en privat meddelelse til brugeren med aliasset alias eller til alle brugere i kanalen. I modsætning til /query åbner det ikke et nyt faneblad. Hvis meddelelse begynder med /me, formateres meddelelsen på samme måde som en /me-kommando. + +Eksempler + +/msg Eisfuchs Jeg har brug for en del hjælp med kommandoen msg + +/msg #konversation Ny version af Konvi er online! + +/msg Eisfuchs /me kompilerer håndbogen lige nu. + + + + + +/smsg alias|kanal meddelelse +Samme som /msg undtagen at meddelelsen ikke vises på din skærm. Dette er nyttigt for at forhindre at kodeord og anden følsom information forbliver synlig på din skærm eller logges. + + + +/amsg alias|kanal meddelelse +Samme som /msg kommandoen ovenfor, undtagen at meddelelsen sendes til alle kanaler og forespørgsler som du har åbnet på alle servere du er tilknyttet i &konversation;. + + + +/op alias +Når dette indtastes i et kanalfaneblad, forsøges det at give alias operatorrettigheder for kanalen. Måske virker dette ikke hvis du mangler tilstrækkelige rettigheder til kanalen (du skal selv være kanaloperator). Du kan indtaste mere end et alias adskilt med mellemrum. + + + +/deop alias +Når dette indtastes i et kanalfaneblad, fjernes operatorrettigheder fra alias. Du kan indtaste mere end et alias adskilt med mellemrum. + + + +/oper [alias] +Giver brugeren med aliasset alias &irc;-op rettigheder (administrator). Dette virker kun hvis aliasset er på listen på servernes O:-linje. En &irc;-op har ret til at udføre /kill for et alias, forbinde servere til &irc;-netværket med /connect med mere. Hvis alias ikke indtastes, forsøges det at give dig selv &irc;-op rettigheder. Du bliver spurgt om dit &irc;-op brugernavn og kodeord i begge tilfælde. + + + +/voice alias +I visse kanaler (med +m flag) kan brugere ikke sende meddelelser hvis de ikke har stemmeret. Denne kommandoen forsøger at give alias stemmeret. Du skal have kanaloperatorrettigheder for at udføre kommandoen. Kommandoen bruges oftest når du er operator på en modereret kanal. + + + +/unvoice alias +Fjerner stemmeret fra alias i kanalen. + + + +/topic [kanal] [meddelelse] +Forsøger at ændre emnet i kanal til meddelelse. Når det indtastes i et kanalfaneblad, kan kanal udelades, og bliver som standard til kanalen som er aktiv i fanebladet. Hvis meddelelse udelades, vises kanalens nuværende emne. Ændring af kanalens emne kan mislykkes hvis du mangler tilstrækkelige rettigheder. + + + +/away grund +Hvis nogen forsøger at sende dig en privat meddelelse eller indbyde dig til en kanal, vil de blive fortalt at du er borte fra din maskine med grund. For at ændre din tilstand tilbage til det normale indtastes /away uden en grund. + + + +/aaway grund +Ligesom kommandoen /away ovenfor, bortset fra at kommandoen sendes til alle servere du er forbundet til i &konversation;. + + + +/invite alias [kanal] +Indbyder brugeren med aliasset alias til at gå med i kanal. Kommandoen er særlig nyttig hvis kanalen kun er åben for indbudte. Når indtastes i et kanalfaneblad kan kanal udelades. + + + +/exec script [parametre] +Kører et skalscript som virker sammen med &konversation; som hedder script, og sender det parametre. Se Scripter for mere information om at bruge og skrive scripter. +Eksempler: + +/exec kdeversion + +Sender dit systems &kde;- og &Qt;-versionsnummer til kanalen. + +/exec cmd uname -a + +Sender din Linux-versionsstreng til kanalen. + + + + + +/notify [alias] +Tilføjer eller fjerner alias fra listen Overvågede tilsluttede aliasser. Hvis aliasset allerede er på listen, fjernes det. Hvis det ikke er på listen, tilføjes det. Hvis alias udelades, vises den nuværende liste over overvågede aliasser. + + + + +/prefs [list|gruppe] [liste|flag] [værdi] +Viser eller indstiller opsætning af &konversation; uden at bruge opsætningsskærmen. Hvis en parameter indeholder mellemrum, omgive den med citationstegn. + +Eksempler: + +/prefs list + +giver en liste af tilgængelige alternative grupper. + +/prefs "General Options" list + +giver en liste af valgmulighederne tilgængelige i gruppenGeneral Options sammen med deres aktuelle værdier + +/prefs "General Options" ShowTrayIcon + +Viser nuværende værdi af indstillingen som viser &konversation;s ikon i statusfeltet. + +/prefs "General Options" ShowTrayIcon false + +Lukker for &konversation;s ikon i statusfeltet. + + + + +/kick alias grund +Når dette indtastes i et kanalfaneblad, forsøges det at sparke brugeren med aliasset alias væk fra kanalen med grund som begrundelse. Hvis grund ikke indskrives, bruges standardgrunden fra Indstillinger. Kommandoen må kun bruges i et kanalfaneblad. + + + +/ban [-host|-domain| -userhost|-userdomain] [kanal] brugere|mask +Forsøger at bandlyse bruger eller mask fra kanal. Når dette indtastes i et kanalfaneblad, kan kanal udelades. For mere information om værter, domæner og masker, se dokumenterne på irchelp.org. For at hente den nuværende bandlysningsliste for en kanal, indtastes /mode kanal b. + + + +/unban [kanal] mønster +Tager en en tidligere bandlysning tilbage fra en kanal. Når dette indtastes i et kanalfaneblad kan kanal udelades. + + + +/ignore [-all] alias +Tilføjer alias til din ignorér-liste. Du kan angive mere end et alias adskilt af mellemrum. Kanalmeddelelser fra brugere på din ignorér-liste vises ikke. Hvis du desuden indtaster -all, ignoreres alle typer af meddelelser fra brugeren (spørgsmål, notitser, CRCP, DCC og undtagelser) så vel som kanalmeddelelser. + + + +/quote kommando +Sender kommando til serveren. + + + +/say meddelelse +Når dette indtastes i et kanalfaneblad, sendes meddelelse til kanalen. Dette er det samme som at indtaste meddelelse i kanalens indtastningsfelt. Nyttigt for at sende &irc;-kommandoer når du ikke vil udføre kommandoen. To kommandotegn efter hinanden (//) gør samme som /say. Bruges også af script til at sende meddelelser. + + + +/raw [open|close] +Indstiller serverloggen til ubehandlet tilstand (open) eller afslutter ubehandlet tilstand (close). Hvis hverken open eller close indtastes, er standardværdien open. I ubehandlet tilstand viser loggen alle meddelelser som modtages fra serveren i rigtigt &irc;-format. + + + +/konsole +Åbner et nyt faneblad som kører en &kde;-terminal. + + + +/server [url] [kodeord] +Forbinder til serveren på adressen url. Hvis url udelades, forbindes til serveren som hører sammen med fanebladet hvor du indtastede kommandoen. Dette er nyttigt for at forbinde til en server igen hvis du blev afbrudt. Hvis serveren kræver et kodeord for at forbinde til den, indtastes det som kodeord. Hvis serveren kræver et andet portnummer end standardnummeret (6667), indtastes url sådan her: irc.kde.org:6665. + + + +/dcc SEND alias [filnavn] +Sender filnavn til brugeren med aliasset alias. Hvis filnavn udelades, vises en dialog så du kan vælge en fil. + + + +/dcc +Åbner et DCC-statusfaneblad + + + +/ctcp alias|kanal ping +Sender en PING-meddelelse til alias eller kanal. Dette er nyttigt for at afgøre om nogen som du taler med har en lang netværksforsinkelse eller (når det sendes til en kanal) om dit system har en lang forsinkelse. + + + +/ctcp alias|kanal meddelelse +Sender en meddelelse til alias eller alle brugere i kanal. Det ligner kommandoen /msg ovenfor, bortset fra at meddelelsen sendes med CTCP-protokollen. Svaret fra den anden side afhænger af &irc;-klientprogrammet brugeren kører. Hvis du for eksempel taler med en anden brugere af &konversation;, returneres /ctcp Eisfuchs TIME systemtiden på Eisfuchs maskine. /ctcp Eisfuchs VERSION returnerer versionsnumret for &konversation; fra Eisfuchs maskine. + + + + + + + + + + +Scripter + +&konversation; levereres med nogle praktiske scripter som du kan køre fra programmet. For at køre et script i et kanalfaneblad, DCC-faneblad eller serverfaneblad, indtastes en kommando på formen + +/exec script [parametre] + +som kører et script som hedder script og sender det (valgfrie) parametre. + +Skriv for eksempel følgende kommandoer i et kanalfaneblad + +/exec kdeversion + +for at sende dine &kde;- og &Qt;-versionsnumre til kanalen. + +/exec cmd uname -a + +kører scriptet cmd, og sender uname -a til det. Det sender din Linux-versionsstreng til kanalen. + +For at få en liste over alle tilgængelige scripter, indtastes følgende kommando i en terminal: + +ls $KDEDIR/share/apps/konversation/scripts + +Du kan skrive dine egne scripter. Scripter er skalscripter og kan skrives med hvilket som helst skalsprog, såsom bash, perl eller python. Når &konversation; kører et script, er de første tre parametre som sendes til scriptet: + + + +Portnumret for &irc;-serveren i fanebladet hvor kommandoen /exec blev skrevet. + + +Serverens adresse. + +Kanalens navn. + + + +Her er et eksempel på et skalscript (cmd). + + +#!/bin/sh + +# Kører en kommando og skriver resultatet ud i Konversation. + +PORT=$1; +SERVER=$2; +TARGET=$3; +shift;shift;shift; + +$@ | while read line; do dcop $PORT Konversation say $SERVER "$TARGET" "$@: $line"; done + + + +Bemærk at scriptet bruger DCOP til at kommunikere med &konversation;. Kommandoen /say gør at udskriften sendes til kanalen som en normal meddelelse. For at vise noget i fanebladet uden at sende det til andre brugere, bruges info i stedet. Kig i eksisterende scriptfiler for flere eksempler på at skrive scripter. + +For at kunne køre et script som du har skrevet, skal du installere det ved at kopiere det til $KDEDIR/share/apps/konversation/scripts eller til $HOME/.kde/share/apps/konversation/scripts. Du skal også give filen kørerettigheder, for eksempel med chmod a+x mit_script. + + + + + + + + +Kommandoreference + + + + + + +Hovedvinduet for &konversation; + + +Fil-menuen + + + + F2 Fil Serverliste + Viser listen med servere og kanaler. + + + F7 Fil Hurtigforbindelse + Viser Hurtigforbind-skærmen til at forbinde til en server. + + + Fil Forbind igen + Forbinder igen til alle servere som blev afbrudt på grund af en netværksfejl eller andet problem. + + + &Ctrl;J Fil Gå med i kanal + Viser en dialog hvor du kan indtaste navnet på en kanal at gå med i. Gør det samme som at indtaste /join #kanalnavn i en kanal eller er serverfaneblad. + + + &Alt; &Ctrl;Q Fil Angiv som borte globalt + Ændrer status for dit alias til borte i alle kanaler. + + + &Ctrl;Q Fil Afslut + Afslutter &konversation; + + + + + + +Menuen <guimenu +>Redigér</guimenu +> + + + + &Ctrl;F Redigér Søg + + Søger efter tekststrenge på nuværende skærm. + + + + F3 Redigér Søg igen + + Søger igen efter tekststrenge på nuværende skærm ved brug af den tidligere søgestreng. + + + + &Ctrl;L Redigér Ryd vindue + + Rydder nuværende skærm. + + + + &Ctrl; &Shift;L Redigér Tøm alle vinduer + + Tømmer alle skærme. + + + + + + + +Menuen <guimenu +>Indsæt</guimenu +> + + + + &Ctrl;K Indsæt &irc;-farve + + Se Send farvelagte meddelelser. + + + + &Ctrl;R Indsæt Huske-linje + + Se Markering af kanal- og forspørgselslogger. + + + + &Alt; &Shift;C Indsæt Specialtegn + + Bruges til at indtaste specialtegn, såsom tegn på fremmede sprog. + + + + + + + +Menuen <guimenu +>Bogmærker</guimenu +> + + + + &Ctrl;B Bogmærker Tilføj bogmærke + + Lægger et bogmærke til for nuværende netværk og kanal + + + + Bogmærker Redigér bogmærker + + Åbner bogmærkeeditoren + + + + Bogmærker Ny bogmærkemappe + + Opretter en ny bogmærkemappe + + + + + + + +<guimenu +>Opsætnings</guimenu +>menuen + + + + &Ctrl;M Indstillinger Skjul menulinje + + Skjuler hovedmenuen. Tryk på &Ctrl;M for at vise den igen. + + + + Opsætning Skjul værktøjslinje + + Skjuler værktøjslinjen. + + + + Opsætning Skjul statuslinjen + + Skjuler statuslinjen for neden på hovedskærmen. + + + + Opsætning Identiteter + Viser skærmen Identiteter til indstilling af din identifikationsinformation. + + + Opsætnings Indstil genveje + + Tillader dig at ændre tastaturgenveje for &konversation;. + + + + Opsætnings Indstil værktøjslinjer + + Tillader dig at tilføje eller fjerne knapper fra &konversation;'s værktøjslinje. + + + + Opsætnings Indstil påmindelser + + Viser skærmen Opsætning af påmindelser. + + + + Opsætnings Indstil &konversation; + + Viser skærmen Redigér indstillinger. + + + + + + + +<guimenu +>Vinduer</guimenu +>-menuen + + + + &Ctrl;. Vindue Foregående faneblad + + Viser skærmen som svarer til foregående faneblad. + + + + &Ctrl;, Vindue Næste faneblad + + Viser skærmen som svarer til næste faneblad. + + + + &Ctrl;W Vindue Luk faneblad + + Lukker den nuværende skærm. Hvis en kanal lukkes, forlades kanalen. Hvis et faneblad med Servermeddelelser lukkes, lukkes alle åbne kanaler på serveren og afbryder fra serveren. + + + + F11 Vindue Luk alle åbne forespørgsler + + Lukker for alle Private konversationer (spørgsmål). + + + + &Ctrl;H Vindue Skjul aliasliste + + Skjuler (eller viser) panelet med aliasser i kanalfaneblade. + + + + F4 Vindue Overvågede tilkoblede aliasser + + Viser skærmen Overvågede aliasser. Se Overvåg hvem der er på. + + + + F5 Vindue Kanaler + + Viser en liste over kanaler tilgængelige på serveren. + + + + F6 Vindue URL-indfangning + + Viser skærmen &URL;-indfangning. + + + + Vindue Ny terminal + + Viser en terminalskærm. Du kan åbne så mange konsoller som du vil. + + + + &Ctrl;O Vindue Åbn logfil + + Viser en skærm med meddelelsesloggen fra nuværende faneblad. Virker kun for fanebladene kanal, servermeddelelser og spørgsmålskanal. Logning skal være aktiveret med Indstillinger Indstil Konversation Logning i hovedmenuen. + + + + + + + +<guimenu +>Hjælpe</guimenu +>menuen +&help.menu.documentation; + + + + + + + +Spørgsmål of svar +&reporting.bugs; &updating.documentation; + + + +Når jeg starter &konversation; vil jeg forbindes til en server uden at gå med i nogen kanaler. Hvordan gør jeg det? + + +Efterlad feltet Kanaler tomt på skærmen Redigér server. + + + + + +&konversation; forbinder ikke til nogen server. Hvad er der galt? + + +Der er flere ting som kan være galt. + + +Sørg for dig at du har indtastet det rigtige Servernavn og den rigtige Port på skærmen Tilføj server. + + +Kontrollér udskriften på skærmen Servermeddelelser for om der er nogen fejlmeddelelser. Afslog serveren forbindelsen på grund af et forkert kodeord? Afslog serveren forbindelsen fordi den kræver IDENTD og din maskine ikke svarede på forespørgsler om IDENT? Markerede du feltet SSL-protokol, men serveren understøtter ikke SSL? + + +Hvis du er bag en brandmur, så sørg for at de rigtige porte er aktiverede. &konversation; kræver at følgende porte er aktiverede: + + + +Udgående TCP 6667 (eller porten på serveren som du forbinder til) +Indkommende TCP 113 (hvis serveren kræver IDENTD) + + + + +For mere information om &irc;-forbindelsesproblemer, se irchelp.org. + + + + + + + + + +Når jeg går til Vindue Kanalliste, kan jeg ikke vælge den. Hvad skyldes det? + + +Menupunktet Vinduer Kanalliste er gråt hvis et faneblad som ikke er en kanal, f.eks. Overvågede forbundne aliasser vises for øjeblikket. For at gøre det muligt at vælge igen, gå tilbage til et kanalfaneblad eller serverfanebladet. + + + + + + + + + + +Medvirkende og licens + +Konversation +Program ophavsret 2002-2005 ved Konversation-gruppen. +&konviwebsite; + +Bidragydere: +Dario Abatianni eisfuchs@tigress.com +Peter Simonsson psn@linux.se +Christian Muehlhaeuser chris@chris.de +John Tapsel john@geola.geo.uk +Ismail Donmez ismail.donmez@boun.edu.tr +Shintaro Matsuoka shin@shoegazed.org +Gary Cramblitt garycramblitt@comcast.net +Matthias Gierlings gismore@users.sourceforge.net +Alex Zepeda garbanzo@hooked.net +Stanislav Karchebny berkus@users.sourceforge.net +Mickael Marchand marchand@kde.org + + + +Tak til: +Michael Goettsche michael.goettsche@kdemail.net +Benjamin Meyer ben+konversation@kdemail.net +Jacub Stachowski qbast@go2.pl +Sabastian Sariego segfault@kde.cl +Olivier Bedard www.konversation.org hosting +Frauke Oster frauke@frsv.de +Lucijan Busch lucijan@kde.org +Sascha Cunz mail@sacu.de +Steve Wollkind steve@njord.org +Thomas Nagy thomas.nagy@eleve.emn.fr +Tobias Olry tobias.olry@web.de +Ruud Nabben r.nabben@gawab.com + + + +Dokumentation ophavsret © 2003-2005 Gary R. Cramblitt garycramblitt@comcast.net + +&erik.kjaer.pedersen.credit; +&underFDL; &underGPL; + + +Installation + + + + +Hvordan får man fat på &konversation; +&install.intro.documentation; Den seneste version af &konversation;, inklusive kildekode og byggeinstruktioner kan også hentes fra &konviwebsite; hjemmeside. + + + + + + +Krav + + + +For at det skal lykkes at bruge &konversation; har du brug for &kde; 3.2 eller senere, og en netværksforbindelse. For tidligere &kde;-versioner kan visse funktioner mangles. Hvis du vil køre &konversation; bag en brandmur, så se Spørgsmål og svar. Hvis du ønsker at bruge SSL-protokollen, vil du måske have brug for OpenSSL. + + + + +&documentation.index; + + + diff --git a/doc/es/Makefile.am b/doc/es/Makefile.am new file mode 100644 index 0000000..212bba7 --- /dev/null +++ b/doc/es/Makefile.am @@ -0,0 +1,2 @@ +KDE_LANG = es +KDE_DOCS = konversation diff --git a/doc/es/addchannel.png b/doc/es/addchannel.png new file mode 100644 index 0000000..08fde93 Binary files /dev/null and b/doc/es/addchannel.png differ diff --git a/doc/es/addnetwork_co.png b/doc/es/addnetwork_co.png new file mode 100644 index 0000000..fe1c959 Binary files /dev/null and b/doc/es/addnetwork_co.png differ diff --git a/doc/es/addserver_co.png b/doc/es/addserver_co.png new file mode 100644 index 0000000..1b0bfc3 Binary files /dev/null and b/doc/es/addserver_co.png differ diff --git a/doc/es/channel_screen_tour_co.png b/doc/es/channel_screen_tour_co.png new file mode 100644 index 0000000..f97a28f Binary files /dev/null and b/doc/es/channel_screen_tour_co.png differ diff --git a/doc/es/channellist_screen_co.png b/doc/es/channellist_screen_co.png new file mode 100644 index 0000000..65a3ef6 Binary files /dev/null and b/doc/es/channellist_screen_co.png differ diff --git a/doc/es/checkidentities.png b/doc/es/checkidentities.png new file mode 100644 index 0000000..eaa7342 Binary files /dev/null and b/doc/es/checkidentities.png differ diff --git a/doc/es/colorchooser_screen.png b/doc/es/colorchooser_screen.png new file mode 100644 index 0000000..0ceedae Binary files /dev/null and b/doc/es/colorchooser_screen.png differ diff --git a/doc/es/colorize.png b/doc/es/colorize.png new file mode 100644 index 0000000..ec6bf07 Binary files /dev/null and b/doc/es/colorize.png differ diff --git a/doc/es/common/1.png b/doc/es/common/1.png new file mode 100644 index 0000000..4d8ae23 Binary files /dev/null and b/doc/es/common/1.png differ diff --git a/doc/es/common/2.png b/doc/es/common/2.png new file mode 100644 index 0000000..b42b4d1 Binary files /dev/null and b/doc/es/common/2.png differ diff --git a/doc/es/common/3.png b/doc/es/common/3.png new file mode 100644 index 0000000..42797b5 Binary files /dev/null and b/doc/es/common/3.png differ diff --git a/doc/es/common/4.png b/doc/es/common/4.png new file mode 100644 index 0000000..c2da7bf Binary files /dev/null and b/doc/es/common/4.png differ diff --git a/doc/es/common/5.png b/doc/es/common/5.png new file mode 100644 index 0000000..10430be Binary files /dev/null and b/doc/es/common/5.png differ diff --git a/doc/es/common/6.png b/doc/es/common/6.png new file mode 100644 index 0000000..35c4ea7 Binary files /dev/null and b/doc/es/common/6.png differ diff --git a/doc/es/common/7.png b/doc/es/common/7.png new file mode 100644 index 0000000..61e7ada Binary files /dev/null and b/doc/es/common/7.png differ diff --git a/doc/es/common/8.png b/doc/es/common/8.png new file mode 100644 index 0000000..6c8ab5b Binary files /dev/null and b/doc/es/common/8.png differ diff --git a/doc/es/common/9.png b/doc/es/common/9.png new file mode 100644 index 0000000..78a87c0 Binary files /dev/null and b/doc/es/common/9.png differ diff --git a/doc/es/configure.png b/doc/es/configure.png new file mode 100644 index 0000000..a5135e8 Binary files /dev/null and b/doc/es/configure.png differ diff --git a/doc/es/dccstatus_screen_co.png b/doc/es/dccstatus_screen_co.png new file mode 100644 index 0000000..8442c4d Binary files /dev/null and b/doc/es/dccstatus_screen_co.png differ diff --git a/doc/es/first_channel_co.png b/doc/es/first_channel_co.png new file mode 100644 index 0000000..88dd2c4 Binary files /dev/null and b/doc/es/first_channel_co.png differ diff --git a/doc/es/first_serverlist_co.png b/doc/es/first_serverlist_co.png new file mode 100644 index 0000000..fbabfbe Binary files /dev/null and b/doc/es/first_serverlist_co.png differ diff --git a/doc/es/highlighting_screen_co.png b/doc/es/highlighting_screen_co.png new file mode 100644 index 0000000..a5897db Binary files /dev/null and b/doc/es/highlighting_screen_co.png differ diff --git a/doc/es/identities_adv_co.png b/doc/es/identities_adv_co.png new file mode 100644 index 0000000..e411f27 Binary files /dev/null and b/doc/es/identities_adv_co.png differ diff --git a/doc/es/identities_away_co.png b/doc/es/identities_away_co.png new file mode 100644 index 0000000..4b523e0 Binary files /dev/null and b/doc/es/identities_away_co.png differ diff --git a/doc/es/identities_gen_co.png b/doc/es/identities_gen_co.png new file mode 100644 index 0000000..a53c03e Binary files /dev/null and b/doc/es/identities_gen_co.png differ diff --git a/doc/es/irc_admin.png b/doc/es/irc_admin.png new file mode 100644 index 0000000..3aeef2e Binary files /dev/null and b/doc/es/irc_admin.png differ diff --git a/doc/es/irc_away.png b/doc/es/irc_away.png new file mode 100644 index 0000000..ad9044d Binary files /dev/null and b/doc/es/irc_away.png differ diff --git a/doc/es/irc_halfop.png b/doc/es/irc_halfop.png new file mode 100644 index 0000000..d0ea2b6 Binary files /dev/null and b/doc/es/irc_halfop.png differ diff --git a/doc/es/irc_normal.png b/doc/es/irc_normal.png new file mode 100644 index 0000000..d3aaee6 Binary files /dev/null and b/doc/es/irc_normal.png differ diff --git a/doc/es/irc_op.png b/doc/es/irc_op.png new file mode 100644 index 0000000..b00f5d4 Binary files /dev/null and b/doc/es/irc_op.png differ diff --git a/doc/es/irc_owner.png b/doc/es/irc_owner.png new file mode 100644 index 0000000..2e2bd40 Binary files /dev/null and b/doc/es/irc_owner.png differ diff --git a/doc/es/irc_voice.png b/doc/es/irc_voice.png new file mode 100644 index 0000000..1fc438b Binary files /dev/null and b/doc/es/irc_voice.png differ diff --git a/doc/es/kaddressbook.png b/doc/es/kaddressbook.png new file mode 100644 index 0000000..2954cd0 Binary files /dev/null and b/doc/es/kaddressbook.png differ diff --git a/doc/es/kimproxy_create_screen2.png b/doc/es/kimproxy_create_screen2.png new file mode 100644 index 0000000..26fb2af Binary files /dev/null and b/doc/es/kimproxy_create_screen2.png differ diff --git a/doc/es/kimproxy_create_screen_co.png b/doc/es/kimproxy_create_screen_co.png new file mode 100644 index 0000000..b023890 Binary files /dev/null and b/doc/es/kimproxy_create_screen_co.png differ diff --git a/doc/es/led_blue_off.png b/doc/es/led_blue_off.png new file mode 100644 index 0000000..2a9beb7 Binary files /dev/null and b/doc/es/led_blue_off.png differ diff --git a/doc/es/led_blue_on.png b/doc/es/led_blue_on.png new file mode 100644 index 0000000..24ea507 Binary files /dev/null and b/doc/es/led_blue_on.png differ diff --git a/doc/es/led_green_off.png b/doc/es/led_green_off.png new file mode 100644 index 0000000..0a5e99e Binary files /dev/null and b/doc/es/led_green_off.png differ diff --git a/doc/es/led_green_on.png b/doc/es/led_green_on.png new file mode 100644 index 0000000..b075e3b Binary files /dev/null and b/doc/es/led_green_on.png differ diff --git a/doc/es/led_red_off.png b/doc/es/led_red_off.png new file mode 100644 index 0000000..36ade01 Binary files /dev/null and b/doc/es/led_red_off.png differ diff --git a/doc/es/led_red_on.png b/doc/es/led_red_on.png new file mode 100644 index 0000000..fc39e10 Binary files /dev/null and b/doc/es/led_red_on.png differ diff --git a/doc/es/led_yellow_off.png b/doc/es/led_yellow_off.png new file mode 100644 index 0000000..e51d9e4 Binary files /dev/null and b/doc/es/led_yellow_off.png differ diff --git a/doc/es/led_yellow_on.png b/doc/es/led_yellow_on.png new file mode 100644 index 0000000..58fc244 Binary files /dev/null and b/doc/es/led_yellow_on.png differ diff --git a/doc/es/logviewer_co.png b/doc/es/logviewer_co.png new file mode 100644 index 0000000..17288b9 Binary files /dev/null and b/doc/es/logviewer_co.png differ diff --git a/doc/es/nicksonline_co.png b/doc/es/nicksonline_co.png new file mode 100644 index 0000000..1e6c91b Binary files /dev/null and b/doc/es/nicksonline_co.png differ diff --git a/doc/es/nickthemes_screen_co.png b/doc/es/nickthemes_screen_co.png new file mode 100644 index 0000000..f3cb041 Binary files /dev/null and b/doc/es/nickthemes_screen_co.png differ diff --git a/doc/es/notification_screen_co.png b/doc/es/notification_screen_co.png new file mode 100644 index 0000000..ea8aeb1 Binary files /dev/null and b/doc/es/notification_screen_co.png differ diff --git a/doc/es/notifylist_screen_co.png b/doc/es/notifylist_screen_co.png new file mode 100644 index 0000000..3ad4587 Binary files /dev/null and b/doc/es/notifylist_screen_co.png differ diff --git a/doc/es/osd_demo.png b/doc/es/osd_demo.png new file mode 100644 index 0000000..03061f2 Binary files /dev/null and b/doc/es/osd_demo.png differ diff --git a/doc/es/osd_screen_co.png b/doc/es/osd_screen_co.png new file mode 100644 index 0000000..142a7dd Binary files /dev/null and b/doc/es/osd_screen_co.png differ diff --git a/doc/es/quickbuttons_screen.png b/doc/es/quickbuttons_screen.png new file mode 100644 index 0000000..1d400e6 Binary files /dev/null and b/doc/es/quickbuttons_screen.png differ diff --git a/doc/es/quickconnect_screen.png b/doc/es/quickconnect_screen.png new file mode 100644 index 0000000..d2f7d41 Binary files /dev/null and b/doc/es/quickconnect_screen.png differ diff --git a/doc/es/serverlist_co.png b/doc/es/serverlist_co.png new file mode 100644 index 0000000..eadf213 Binary files /dev/null and b/doc/es/serverlist_co.png differ diff --git a/doc/es/urlcatcher_screen_co.png b/doc/es/urlcatcher_screen_co.png new file mode 100644 index 0000000..35d7abc Binary files /dev/null and b/doc/es/urlcatcher_screen_co.png differ diff --git a/doc/es/webbrowser_screen_co.png b/doc/es/webbrowser_screen_co.png new file mode 100644 index 0000000..a2430c0 Binary files /dev/null and b/doc/es/webbrowser_screen_co.png differ diff --git a/doc/et/Makefile.am b/doc/et/Makefile.am new file mode 100644 index 0000000..1284321 --- /dev/null +++ b/doc/et/Makefile.am @@ -0,0 +1,2 @@ +KDE_LANG = et +KDE_DOCS = konversation diff --git a/doc/et/index.docbook b/doc/et/index.docbook new file mode 100644 index 0000000..ad85732 --- /dev/null +++ b/doc/et/index.docbook @@ -0,0 +1,5981 @@ + + + + + IRC"> + CTCP"> + nickname"> + Nickname"> + LED"> + OSD"> + URL"> + MIME"> + + + + + + +]> + + + + + + + + + + + + +&konversation;i käsiraamat + + + Gary R. Cramblitt garycramblitt@comcast.net +Marek Laane
bald@starman.ee
Tõlge eesti keelde
+
+ + + + +2003-2005 +Gary R. Cramblitt + + + + +&FDLNotice; + + + +2005-05-23 +0.18 + + + + +&konversation; on K Töölaua Keskkonna kasutajasõbralik &irc; klient. + + + + + +KDE +kdeextragear-2 +Konversation +irc +interneti retranslatsioonivestlus +vestlus +side + + +
+ + + + + + +Sissejuhatus + + + +&konversation; on &irc; klient &kde; töökeskkonnale (versioon 3.2 või uuem). See pakub järgmisi võimalusi: + + + +SSL toetus. +Kasutajasõbralik kaartidega liides. +Kohandatavad kiirnupud sagedamini kasutatavatele käskudele. +Automaatne taasühendumine ja taasliitumine. +Failide saatmine ja saamine (DCC). +Võimalus jälgida, millises olekus on teised kasutajad. +Visuaalsed ja helilised märguanded paljudele sündmustele, näiteks sõnumitele, kus esineb sinu hüüdnimi või kui hüüdnimi, mis on sinu jälgitavate hüüdnimede nimekirjas, tuleb võrku või lahkub võrgust. +Kohandatav sõnumite esiletõstmine hüüdnime või regulaaravaldise alusel. +Võimalus hüüdnime automaatselt lõpetada. +Kõigi &URL;-ide hankimine sõnumist ja nende salvestamine. +Sõnumite esitamine ekraanil isegi rakenduse minimeerimisel. +Võimalus panna hüüdnimesid ignoreeritavate nimekirja. +Automaatne logimine ja logide haldamise võimalused. +Ridade märkimine logifailides. +Skriptide kasutamine. +Põimimine &aadressiraamat;uga. + + + +&konversation;i veebilehekülg on &konviwebsite;. &konversation;i kohta käivaid küsimusi ja vastuseid saab esitada &konversation;-Users meililistis. Palun liitu sellega, kui soovid teada saada uutest võimalustest või anda teada vigadest jne. Ainult uutest väljalasetest saab teada, kui liituda meililistiga &konversation;-Announce. See on üsna väikese mahuga list, kus antakse ainult teada uutest väljalasetest või parandustest. + +&konversation;i arendajatega saab enamasti ühendust &irc; vahendusel irc.kde.org kanalil #konversation. + + + + +&konversation;i kasutamine + + + + +Kui sa ei ole varem &irc;-d kasutanud... + +Hästi lihtsalt öelduna on &irc; Interneti ametlike standarditega kindlaks määratud vestlusprotokoll, mis võib endale nõuda päris palju tunde sinu elust. &irc; kasutamiseks tuleb ühenduda serveriga ja seejärel kanaliga (see on umbes sama, mis jututuba) või siis alustada eravestlust. + +Serveri ja kanaliga ühendumiseks ava &konversation;. Ilmub serverite nimekiri. + + + +Serverite nimekiri + + + + + + + + + + + + + Serverite nimekiri + + + + + + + +Siin on kirjas seadistatud &irc; võrgud. &irc; võrk kujutab endast koostööd tegevate serverite kogumit. Sul tuleb võtta ühendust ainult ühe võrku kuuluva serveriga ning sa oled kohe ühendatud terve &irc; võrguga. Ühendumise järel võtab &konversation; automaatselt ühendust kõigi näidatud kanalitega. &konversation;i esmakordsel käivitamisel ootab sind juba ees Freenode'i võrk ja #kde kanal. Valimiseks klõpsa võrgule. +Siia klõpsates on võimalik määrata uus võrk, sealhulgas server, millega ühendus luuakse, ning kanalid, millega ühenduse loomise järel automaatselt liitutakse. Täpsemalt räägib sellest osa Uute võrkude, serverite ja automaatselt liituvate kanalite määramine. +Klõpsa siia valitud &irc; võrgu ja kanaliga ühendumiseks. + + + + +Kui klõpsad nupule Ühenda &konversation;i esmakordsel käivitamisel, näed järgmist teadet, mis ütleb, et sinu vaikimisi identiteet ei ole korrektselt määratud. + + + + Kontrolli identiteeti + + + + + + Kontrolli identiteeti + + + + + +&konversation; hangib esmakordsel käivitamisel info kasutaja kohta operatsioonisüsteemist ja täidab saadud infoga vaikimisi identiteedi. Kui operatsioonisüsteemi info kasutaja kohta pole täielik (puudub näiteks tegelik nimi), näed mainitud teadet. Probleemi lahendamiseks klõpsa nupule OK ja uuri lähemalt Identiteedi määramine. + + +Ilmub peaaken, mis näitab serverilt kliendile saadetavaid teateid (kui &konversation; serveriga ühendust ei saa, uuri osa Küsimused ja vastused). Kui serveri teated on üle ekraani jooksnud, liitub &konversation; valitud kanali või kanalitega. + + + +Kanal. + + + + + + + + + + + + + Kanal + + + + + + + + +Seda nimetatakse sisendreaks. Sõnumi saatmiseks kõigile kanalil viibijatele kirjuta siia ona sõnum ja vajuta klahvi &Enter;. Nagu kõigil teistelgi, ilmub sinu sõnum ülal pidevalt edasiliikuvasse kanaliaknasse. Igale sõnumile eelneb selle kirjutamise aeg ja kasutaja hüüdnimi. + +Võimalik on liituda mitme serveri ja kanaliga. Iga server, kanal, kanalite nimekiri või üldse mis tahes ekraan saab omaette kaardi. Kõigi saadaolevate kanalite nägemiseks vaata saadaolevate kanalite nimekirja. Kanaliga ühinemiseks kirjuta sisendreale /join #kanalinimi (pane tähele, et # on kindlasti vajalik). Käsu /join asemel võib anda ka lühema /j. Kanalilt lahkumiseks kirjuta /part. Mõnele muule serverile või kanalile lülitumiseks klõpsa vastavat kaarti. + +Seda nimetatakse hüüdnimede paneeliks. Siin on kirjas iga kanaliga ühinenud kasutaja hüüdnimi, kaasa arvatud sinu enda oma. + + + + +Need olid kõige olulisemad asjad. Kui soovid rohkem teada saada, loe edasi... + + + + + + +Identiteedi määramine + +Enne seda, kui hakkad regulaarselt &konversation;it kasutama, peaksid seadistustes kindlaks määrama, kuidas, kellena ja mismoodi sa võrgus esined. + +Vali menüükäsk Seadistused Identiteedid . Ilmub dialoog Identiteedid. Dialoogi Identiteedid saab avada ka klõpsuga nupule Muuda dialoogis Võrgu lisamine. + + + +Identiteedid (kaart Üldine) + + + + + + + + + + + + + + + + + Identiteedid (kaart Üldine) + + + + + + + +Klõpsa siia muudetava identiteedi valimiseks. +Nende nuppudega saab identiteeti lisada, duubeldada, ümber nimetada või eemaldada. +Kirjuta siia oma pärisnimi. &irc; ei ole mõeldud sinu varjamiseks sõprade või vaenlaste eest. Pea seda meeles, kui tekib kiusatus midagi kurja ette võtta. Võltsitud "pärisnimi" võib muidugi hoida sind eemal kõikvõimalikest sulle ebameeldivatest tegelastest, aga arvuti, mille taga sa töötad, on nagunii võimalik alati üles leida, nii et päris anonüümseks ei õnnestu sul nii või teisiti jääda. +Nuppudega Lisa, Muuda ja Kustuta saab hüüdnimega vastavaid toiminguid ette võtta. +Kirjuta siia oma hüüdnimed. Hüüdnimi on nimi, mille all teised kasutajad sind näevad. Võid siin määrata just sellise nime, nagu soovid. Esimene märk peab olema täht, ülejäänud võivad olla tähed, numbrid või ka erimärgid -[]\`_^{}|. + +Kuna hüüdnimi peab olema serveri ulatuses unikaalne, võib juhtuda, et server keeldub seda aktsepteerimast, kui kellelgi on juba samasugune hüüdnimi. Selleks oleks mõttekas lisada vastavatesse kastidesse alternatiivsed hüüdnimed. Kui server lükkab esimesena sisestatu tagasi, on valmis järgmine hüüdnimi, mida &konversation; sellisel juhul serverile saadab. + +RFC 2812 kohaselt võib hüüdnimi olla maksimaalselt üheksamärgiline, kuid tegelikult on see serveri otsustada. Serveri maksimumi selgitamiseks võta serveriga ühendust. Serveri sõnumite kaardil otsi üles sõnum [Support]. See võib olla näiteks selline: + + +[18:51] *Eisfuchs* [21:45] [Support] Eisfuchs MODES=4 MAXCHANNELS=20 NICKLEN=16 USERLEN=10 HOSTLEN=63 TOPICLEN=450 KICKLEN=450 CHANNELLEN=30 KEYLEN=23 CHANTYPES=# PREFIX=@+ CASEMAPPING=ascii CAPAB IRCD=dancer + + +NICKLEN määrab antud juhul, kui pikk tohib olla hüüdnimi. + + +Nende nuppudega saab muuta hüüdnimede järjekorda. Kõigepealt üritatakse kasutada esimesena seisvat hüüdnime, seejärel teist ja nii edasi. +Kui oled oma hüüdnime &irc; võrgus registreerinud, sisesta ka teenus ja oma hüüdnime autentimisel kasutatav parool. Kui &konversation; ühendust loob, saadab rakendus automaatselt serverile /msg teenus IDENTIFY parool. Kui sa ei tea, mida see tähendab, jäta need sisestamata. + + + + + +Klõpsa kaardile Eemalolek. + + + + Identiteedid (kaart Eemalolek) + + + + + + + + + + + + + Identiteedid (kaart Eemalolek) + + + + + + + +Kirjuta hüüdnimi, mis osutab, et oled eemal. Kui annad käsu /away sõnum mis tahes kanalil, millega oled ühinenud antud identiteeti kasutades, asub tegevusse &konversation; ja sinu hüüdnimi asendatakse eemaloleku hüüdnimega. Ühtlasi saadetakse eemalolekusõnum kõigile kanalitele, millega oled antud identiteeti kasutades liitunud. %s asemele pannakse sõnum. Kui annad käsu /away, muutub sinu hüüdnimi taas tavaliseks ja naasmissõnum saadetakse kõigile kanalitele, millega oled antud identiteeti kasutades liitunud. +Selle kasti märkimisel lisatakse kanali aknasse alati rõhtrida, kui annad käsu /away. See tähistab kohta, kus sa eemale läksid. Teised &irc; kasutajad seda ei näe. +Selle kasti märkimisel saadab &konversation; automaatselt eemalolekusõnumi kõigile kanalitele, millega oled antud identiteeti kasutades liitunud. %s asemele pannakse sõnum. Kui annad käsu /away, muutub sinu hüüdnimi taas tavaliseks ja naasmissõnum saadetakse kõigile kanalitele, millega oled antud identiteeti kasutades liitunud. + +Paljud kasutajad peavad eemalolekusõnumeid päris häirivaks, seepärast kasuta seda võimalust ettevaatlikult ja ürita arvestada teiste &irc; kasutajate huvidega. + + + + + + +Klõpsa kaardile Muud. + + + + Identiteedid (kaart Muud) + + + + + + + + + + + + + + + + Identiteedid (kaart Muud) + + + + + + + +Siia saab sisestada käsu, mis täidetakse enne serveriga ühendumist. Kui kasutad antud identiteeti mitmes serveris, täidetakse käsk neis kõigis. +See mõjutab seda, millises kodeeringus saadetakse sinu kirjutatud märgid serverile. Samuti mõjutab see sõnumite näitamist. &konversation;i esmakordsel käivitamisel hangib rakendus kodeeringu operatsioonisüsteemist. Kui sul aga tekib raskusi teiste kasutajate sõnumite nägemisega, võiksid proovida kodeeringut vahetad. +Ühendumisel esitavad paljud serverid sinu arvutile IDENT-päringu. Kui sinu arvutis IDENT-serverit ei tööta, saadab &konversation; siinmääratud vastuse. Tühikud ei ole vastuses lubatud. Vaikimisi kasutatakse sinu eesnime. +Kui lahkud kanalilt, saadetakse kanalile siinmääratud sõnum. +Kui sind kanalilt välja visatakse (tavaliselt saab seda teha &irc; operaator), saadetakse see sõnum kanalile. +Klõpsa siia tehtud muudatuste rakendamiseks. Et kõik rakenduks, tuleb ühendus serveriga katkestada ja siis uuesti ühendust võtta. Lihtsaim viis selleks on väljuda &konversation;ist ja see uuesti käivitada. + + + + + + + + + + +Uute võrkude, serverite ja automaatselt liituvate kanalite määramine + +&konversation;i käivitamisel avatakse aken Serverite nimekiri. See avatakse ka menüükäsuga Fail Serverite nimekiri . The Serverite nimekiri näitab gruppidesse jagatult sinu olemasolevaid &irc; võrke. &irc; võrk on koostööd tegevate serverite kogum. Võrgu mis tahes serveriga ühendudes saad ligipääsu kõigile võrgu kanalitele. &irc; võrgud on näiteks Freenode ja Undernet. + + + + Serverite nimekiri + + + + + + + + + + + + + + Serverite nimekiri + + + + + + + +Siin on kirjas sinu juba olemasolev võrk või võrgud, samuti identiteet, millega sa võrku ühendud, ning kanalid, millega ühendumisel automaatselt liitutakse. Kui oled määranud võrkudele grupi, näidatakse võrke grupis. Valimiseks klõpsa võrgu nimele. +Nupuga Lisa saab lisada uue võrgu, nupuga Muuda muuta valitud võrku ning nupuga Kustuta eemaldada valitud võrgu. +Sellele nupule klõpsates luuakse ühendus valitud võrguga ja suletakse serverite nimekiri. Soovi korral võid valida ka mitu võrku, sellisel juhul luuakse ühendus nende kõigiga. +Klõps sellele nupule ei tähenda mitte tehtud muudatustest loobumist, vaid lihtsalt seda, et sa ei soovi hetkel ühegi võrguga ühenduda. + + + + + +Klõpsuga nupule Lisa ilmub dialoog Võrgu lisamine. + + + + Võrgu lisamine + + + + + + + + + + + + + + + + + + + Võrgu lisamine + + + + + + + +Siia tuleb kirjutada võrgu nimi. Serverite nimekirjas võib olla ka ühesuguse nimega võrke just nii palju, kui sa vaid soovid. +Lisavõimalus. Kui siia midagi kirjutada, näidatakse serverite nimekirjas samasse gruppi kuuluvaid võrke üheskoos. +Vali olemasolev identiteet või klõpsa nupule Muuda, kui soovid lisada uue identiteedi või olemasolevat muuta. Identiteeti kasutatakse sinu tuvastamiseks ja sinu hüüdnime määramiseks ühenduse loomisel võrguga. +Lisavõimalus. See käsk saadetakse serverile pärast ühendumist. Näide: /msg NickServ IDENTIFY konvirocks. See näide käib freenode võrgu kohta, mis nõuab, et kasutaja ühendumisel oma hüüdnime parooli ja kasutajanimega registreeriks. konvirocks on parool hüüdnimele, mis on antud kaardil Vaikeidentiteet. Korraga võib anda ka mitu käsku, eraldades need semikooloniga. +Selle kasti märkimisel loob &konversation; automaatselt ühenduse antud võrguga &konversation;i käivitamisel. +See on võrgusolevate &irc; serverite nimekiri. Võrguga ühendumisel püüab &konversation; ühenduda nimekirjas kõige esimesena seisva serveriga. Kui see ei õnnestu, üritatakse ühenduda nimekirjas teisel kohal seisva serveriga, seejärel kolmandaga ja nii edasi. Määrata tuleb vähemalt üks server. Serveri saab valida selle nimele klõpsates. +Nupuga Lisa saab serveri lisada, nupuga Muuda valitud serverit muuta ning nupuga Kustuta valitud serveri eemaldada. Samuti saab muuta serverite järjekorda nimekirjas, mis muudab ka järjekorda, milles püütakse nendega ühendust luua. +Lisavõimalus. See on kanalite nimekiri, millega liitutakse automaatselt pärast seda, kui &konversation; on serveriga ühenduse loonud. Kui see tühjaks jätta, ei liituta automaatselt ühegi kanaliga. +Nupuga Lisa saab kanali lisada, nupuga Muuda valitud kanalit muuta ning nupuga Kustuta valitud kanali eemaldada. Muuta saab ka järjekorda, millega kanalitega liitutakse. + + + +Püüa mitte seada ühe ja sama võrgu alla erinevate &irc; võrkude kanaleid. Ürita vältida ühe ja sama serveri lisamist erinevatesse võrkudesse. Vastasel juhul ei pruugi korralikult toimida &konversation;i koostöö sinu aadressiraamatuga ning võrgusviibijate jälgimine. + + + + +Klõpsuga nupule Lisa sektsioonis Serverid ilmub serveri lisamise dialoog. + + + + Serveri lisamine + + + + + + + + + + + + + + Serveri lisamine + + + + + + + +Serveri nimi või IP aadress. Serverite nimekirja haldab irchelp.org. +Sisesta port, mida on vaja serveriga ühendumiseks. Enamasti peaks sobima 6667. +Kui server nõuab ühinemiseks parooli, anna see siin, muidu jäta tühjaks. +Selle märkimisel saab serveriga suhtlemiseks kasutada turvalise soklikihi (SSL) protokolli. See tagab sinu arvuti ja &irc; serveri suhtlemise privaatsuse. Selleks peab aga SSL protokolli toetama ka server. Kui server seda ei toeta, siin enamasti ei õnnestugi ühendust luua. + + + + + +Klõpsuga nupule Lisa sektsioonis Automaatne liitumine kanalitega ilmub kanali lisamise dialoog. + + + + Kanali lisamine + + + + + + Kanali lisamine + + + + + +Kirjuta siia kanali nimi. Ära unusta selle ette lisamast märki #. Kui kanal nõuab liitumiseks parooli, anna ka see siin, vastasel juhul jäta vastav lahter tühjaks. + + + + + + +Saadaolevate kanalite nimekiri + +Saadaolevate kanalite nägemiseks vali menüükäsk Aknad Kanalite nimekiri . Pärast hoiatusdialoogi luuakse uus kaart nimetusega Kanalite nimekiri. + + + +Kanalite nimekirja kaart. + + + + + + + + + + + + + + + + Kanalite nimekirja kaart. + + + + + + + + +Sisesta siia filtristring. + +Kanalite nimekirja saab kärpida, kui siin määrata sellel olevate kasutajate miinimum või maksimum. 0 tühistab vastava parameetri kasutamise. + +Klõpsa siia serverist kanalite nimekirja tõmbamiseks ja filtri rakendamiseks. + +Siin on näha kanalite nimekiri. Pane tähele, et kui sa ei kasuta regulaaravaldisi, näitab &konversation; kõiki kanaleid, mille nimi sisaldab sisestatud filtristringi. Kanali nimi ei pea ilmtingimata algama sisestatud filtristringiga. + +Vali klõpsuga kanal, millega soovid liituda. Paremklõps kanali nimel näitab kõiki kanali teemas mainitud veebiaadresse. + +Klõpsa siia kanaliga liitumiseks. Kanalile luuakse uus kaart. + + + + +Võimaluse korral tuleks vältida nupu Värskenda nimekirja kasutamist. Enamikul serveritest on tuhandeid kanaleid ning selle käsu andmine paneb serverile korraliku koormuse. Pealegi kulub selleks sõltuvalt sinu internetiühenduse võimekusest päris mitu minutit. Kui klient on liiga aeglane, võib server isegi sinuga ühenduse katkestada. + +Mõnikord on serveris "salajasi kanaleid", mida mõistagi kanalite nimekiri ei näita. Nendega saab siiski liituda, kui tead kanali täpset nime. Selleks kirjuta sisendreale /join #kanalinimi (# on kindlasti vajalik). Kanalile luuakse uus kaart. Kui liitud kanaliga ja hüüdnimede paneelil asetseb ainult sinu enda &nickname;, tähendab see, et antud kanalit ei olnud varem olemas. Server lõi selle ja sina oled sellel nüüd operaator. Sellisel juhul on usutavasti mõttekas kanal sulgeda, kirjutades käsu /part. + + + + + + +Peaakna tutvustus + +Vaatame lähemalt, mida siis sisaldab peaaken. Alltoodud pildil on see näha avatud kanalikaardiga. + + + +Peaaken. + + + + + + + + + + + + + + + + + + + Peaaken + + + + + + + + +See kannab nimetust sisendrida. See on näha ainult siis, kui tegemist on kanalikaardiga. Sõnumi saatmiseks kõigile kanalil viibijatele kirjuta siia oma sõnum ja vajuta klahvi &Enter;. Nagu teiste, nii ka sinu sõnum ilmub üleval vastavalt sõnumite kirjutamisele pidevalt edasiliikuvasse aknasse. Igale sõnumile eelneb selle kirjutamise aeg ja kirjutaja hüüdnimi. + + Teksti võib asetada ka lõikepuhvrist. Kui asetatud tekstis on enam kui üks rida (see tähendab, reavahetusi), ilmub dialoog. Redigeeri teksti, et see võtaks sulle meelepärase kuju ja klõpsa OK. + + Kui asetatud tekst on pikem kui 256 sümbolit või sisaldab enam kui ühe rea, ilmub hoiatus, mis teatab, et pikad sõnumid võivad põhjustada ühenduse katkestusi ja üleujutusi. Sa võid muidugi ka sellisel juhul sõnumi teele saata, kuid see pole üldse eriti hea mõte, sest üleujutus ei meeldi kindlasti teistele kasutajatele ja pealegi võib server sinuga ühenduse katkestada. Märksa mõttekam oleks saata sõnum teele lühemate tükkidena. + + + + Paljudel kanalitel on kombeks lisada konkreetsele kasutajale mõeldud sõnumi ette ka tema hüüdnimi. &konversation; pakub mugava võimaluse hüüdnimi automaatselt lõpetada. Alusta kirjutamist ja kui hüüdnime on juba paari tähe jagu kirja pandud, vajuta klahvi Tab. &konversation; hoolitseb ise selle eest, et hüüdnimi saaks korrektselt lõpetatud ja ka koolon selle järele lisatud. Lõpetamisvõimaluse kohandamiseks vali menüükäsk Seadistused Konversationi seadistamine , ava ilmuvas dialoogis kaart Käitumine, seejärel Üldinening siis Lõpetamise režiim + + Siia võib ka sisestada mõne &irc; käsu, kirjutades kõigepealt / ja seejärel mõne kehtiva &irc; käsu (vaata osa Sagedamini kasutatavad &irc; käsud). Mõne serveri korral võib anda käsu /help, mis näitab saadaolevaid käske, või siis /help käsk, mis näitab abi konkreetse käsu kohta. + + + +Liituda võib mitme serveri ja kanaliga. Iga server ja kanal saab peaaknas eraldi kaardi. Kõigi kanalite nimekirja saamise kohta vaata osa Saadaolevate kanalite nimekiri. Kanaliga liitumiseks anna sisendreal käsk /join #kanalinimi (# on kindlasti vajalik). Kanalilt lahkumiseks anna käsk /part. Kaardid on näha ka siis, kui avad kanalite nimekirja, pead privaatvestlust, avad &URL; püüdja või ühe või rohkem konsooli. Teisele kaardile lülitumiseks klõpsa vastava kaardi tähisele või kasuta nende vahel liikumiseks hiireratast. + +Kaartide kohandamiseks vali menüükäsk Seadistused Konversationi seadistamine ning ilmuvast dialoogist Käitumine ja Üldine. + + + +Need tulukesed (&led;) hakkavad vilkuma, kui kaardil juhtub midagi, mida sa veel näinud pole. &led; vilgub aeglasemalt, kui nägemata sõnumid on kõigest käsud join, part, quit või on kellegi hüüdnimi muutunud. Nad vilguvad aga kiiremini, kui tegemist on päris sõnumiga. Värvid tähendavad järgmist: + + Kanal + + + Serveri sõnumid, kanalite nimekiri või &URL; püüdja. + + + Konsool või DCC olek. + + + Privaatsõnum (päring). + + + + +Klõpsa siia kaardi sulgemiseks. Kanali kaardi sulgemisega lahkud kanalilt. Serveri sõnumite kaardi sulgemisega lahkud kõigilt kanalitelt, millega olid liitunud, sulged kõik avatud päringud antud serveris ja katkestad ühenduse serveriga. + +Sellele nupule klõpsates saad muuta oma hüüdnime. See on näha ainult siis, kui tegemist on kanalikaardiga. Nupu peitmiseks vali menüükäsk Seadistused Konversationi seadistamine , ava kaart Välimus ja seejärel Vestlusaken ning eemalda märge kastist Kasti näitamine oma hüüdnime muutmiseks. + +Siin näeb kanali teemat. Hiirt teema kohal seisma jättes näeb seda täies pikkuses. Teemat saab muuta sellest vasakul asuvale nupule klõpsates. Kanali teema peitmiseks vali menüükäsk Seadistused Konversationi seadistamine , ava kaart Välimus ja seejärel Vestlusaken ning eemalda märge kastist Kanali teema näitamine. + +Need nupud näitavad kanalirežiimide parajasti kehtivat olekut. Kui režiim kehtib, on nupp alla vajutatud. Kui sul on vastavad õigused, võid kanali režiime muuta neile nuppudele või siis teemast vasakul asuvale nupule klõpsates. Kanalirežiimi nuppude peitmiseks vali menüükäsk Seadistused Konversationi seadistamine , ava kaart Välimus ja seejärel Vestlusaken ning eemalda märge kastist Kanalirežiimi nuppude näitamine. + + +Seda nimetatakse hüüdnimede paneeliks. Seda näidatakse alati, kui avatud on kanalikaart. Siin on kirjas iga kanaliga liitunud kasutaja hüüdnimi, kaasa arvatud sinu enda oma. Hiirt mõne hüüdnime kohale viies näeb antud kasutaja kohta lisainfot. Seda, millist ikooni näidatakse hüüdnimede juures, saab muuta hüüdnimede ikooniteemat vahetades. Täpsemalt räägib sellest osa Hüüdnimeteemade seadistamine. Teema Big Bullets korral, mida näeb siinsel pildi, kasutatakse järgmisi ikoone: + + + tavaline kasutaja + + + + häälega kasutaja, kes võib kõnelda modereeritaval kanalil. + + + + kanali pooloperaator + + + + kanali operaator + + + + kanali omanik + + + + kanali administraator + + + + + +Kui kasutaja on eemal, näidatakse ikooni peal väikest punast risti. + +Kui valida mõni hüüdnimi ja klõpsata sellel &HPN;ga, ilmub kontekstimenüü operatsioonidega, mida antud hüüdnime puhul on võimalik ette võtta. Näiteks on võimalik saata fail hüüdnimele. Samuti saab nii luua seose hüüdnime ja sinu aadressiraamatus oleva kontakti vahel. + +Hüüdnimede paneeli peitmiseks vali menüükäsk Aken Peida hüüdnimede nimekiri . + + + +Need on niinimetatud kiirnupud. Vaikimisi neid ei näidata. Sellest, kuidas neid näha, räägib Kiirnuppude seadistamine. Sul on võimalik kõiki nendega seotud käske omatahtsi määrata. + + + + +Märkus: sul on võimalik määrata, kuidas näidatakse kanali- ja päringuakendes üle ekraani kerivaid sõnumeid. Sa võid näiteks muuta sõnumite värvi, lasta esitada heli teatud stringi sisaldava sõnumi saabumisel või lasta automaatselt teatud sõnumitele vastata. Täpsemalt räägib sellest osa Sõnumite esiletõstmine. + +Märkus: kanalinimede alguses seisab mõnikord &, + või !. Kanalinime esimene märk määrab selle tüübi (RFC 2811 kohaselt) järgmiselt: # -tavalised kanalid. ! -tavalised kanalid. & - kohalikud kanalid, nendega saab ühineda ainult kanalit pakkuvast serverist (kõigi muude kanalitega saab liituda mis tahes serverist). + - kanalid, mis ei toeta kanalirežiime. See tähendab, et sisse ei ole lülitatud ühtki režiimi, välja arvatud kanali lipp 't'. Kanalinimed võivad olla kuni 200 sümbolit pikad ning sisaldada mis tahes sümboleid, välja arvatud tühik, koma ja Ctrl+G. + + + + + + +Kiirühendumine + +Võib juhtuda, et sul on soov ühineda serveriga ilma kogu uue serveri loomist serverite nimekirjas läbi tegemata. + +Selleks vali menüükäsk Fail Kiirühendus . Ilmub dialoog Kiirühendus. + + + +Kiirühenduse aken. + + + + + + Kiirühenduse aken + + + + + +Sisesta serveri aadress kasti Server, meelepärane hüüdnimi kasti Hüüdnimi ja klõpsa nupule Ühenda. Kui &konversation; on serveriga ühenduse loonud, anna kanaliga liitumiseks käsk /join #kanalinimi. + + + + + + +Sagedamini kasutatavad &irc; käsud + +Siin on ära toodud sagedamini kasutatavad &irc; käsud. Nende täieliku nimekirja annab RFC 2812, samuti leiab selle veebileheküljelt irchelp.org. Kui soovid näha käske, mida &konversation; spetsiaalselt kohtleb, vaata osa &konversation;i käsud. + + + + + +/help +Näitab kõiki antud serveris saadaolevaid käske. Kõik serverid seda käsku ei toeta. + + + +/help käsk +Näitab abi käsu kohta. Kõik serverid seda käsku ei toeta. + + + +/join #kanal +Käsk #kanaliga liitumiseks. Kui kanalit ei ole olemas, see luuakse ja sa saad selle operaatoriks. + + + +/part +Käsk antud kanalilt lahkumiseks, sulgeb ka peaakna kaardi. + + + +/part #kanal +Käsk #kanalilt lahkumiseks, sulgeb peaakna kaardi. Sama, mis /leave + + + +/me sõnum +Saadab sõnumi kanalile, selle ette lisatakse sinu hüüdnimi. Kui näiteks hüüdnimi on Tux, siis kirjutades /me joob parajasti teed, ilmub sõnum Tux joob parajasti teed. Kui kasutajad ei ole just mingil põhjusel rakendanud filtrit teatud sõnumite mittenäitamiseks, peaksid seda nägema kõik kanalil viibijad. Tavaliselt kasutatakse selliseid sõnumeid mitteverbaalse info edastamiseks, näiteks enda tunnete edastamiseks või teatamiseks, mida parajasti tehakse. Kui lahkud aga mõneks ajaks arvuti juurest, kasuta käsku /away. + + + +/away sõnum +Kui keegi püüab sulle privaatsõnumit saata või sind mõnele kanalile kutsuda, saab ta sõnumiga teada, et oled parajasti eemal. + + + +/away +Katkestab käsu /away sõnum kehtivuse. + + + +/query hüüdnimi +Loob uue kaardi kasutajaga hüüdnimi privaatvestluse alustamiseks. Tavaliselt nimetatakse seda &irc;-s päringuks. Kõik, mida siin kirjutatakse, on näha ainult sulle ja sinu partnerile. + + + +/msg hüüdnimi sõnum +Saadab sõnumi kasutajale, kelle hüüdnimi on määratud muutujaga hüüdnimi. Ainult hüüdnimi näeb seda sõnumit. Pikema vestluse jaoks kasuta käsku /query. + + + +/invite hüüdnimi +Kutsub kasutaja, kelle hüüdnimi on määratud muutujaga hüüdnimi, kanaliga liituma. See on eriti kasulik siis, kui kanaliga saabki liituda ainult kutse alusel. + + + + + + + + + + +Privaatvestlused (päringud) + +Privaatvestlus on vestlus, mida näed ainult sina ja sinu partner. &konversation; nimetab privaatvestlusi "päringuks". Selle alustamiseks kirjuta sisendreale /query hüüdnimi, kus hüüdnimi on selle kasutaja hüüdnimi, kellega soovid vestlust alustada. Võimalik on ka leida kasutaja hüüdnimi hüüdnimede paneelil, klõpsata sellel &HPNga; ja valida Ava päring. Luuakse uus kaart. Anna seejärel endast teada juba sõnumit saates. + +Päringud on nagu kanalid, ainult et sellel kanalil on võimalik tegutseda vaid sinul ja veel ühel isikul. + +Päringu lõpetamiseks sulge lihtsalt kaart. Pane siiski tähele, et kui sinu partner saadab sulle veel sõnumeid, avatakse see kaart uuesti. + +Kõigi päringute sulgemiseks vali menüükäsk Aken Sulge kõik avatud päringud või vajuta klahvi F11. + +Kui keegi tahab sinuga privaatvestlust alustada, loob &konversation; uue kaardi, kus osaleb siis see kasutaja ja sina. Kui sa ei soovi vestelda, sulge kaart. + + + + + + +Märguannete määramine + +Märguanded on toimingud, mida &konversation; võtab ette teatud sündmuste toimumisel. Oletame, et &konversation; töötab, kuid on minimeeritud või varjatud töölaual teiste avatud akende taha. Kui keegi soovib nüüd sinuga suhelda või mõni sinu sõber kanaliga liitub, oleks hea, kui sa sellest teada saaksid. Selleks ongi märguanded. + +Märguannete seadistamiseks vali menüükäsk Seadistused Märguannete seadistamine . Ilmub dialoog Märguannete seadistused. + +Klõpsa kohe nupule Muud valikud. + + + +Märguannete seadistustedialoog. + + + + + + + + + + + + + Märguannete seadistustedialoog + + + + + + + + +Klõpsa siia sündmuse valimiseks. + +Märgi, millist tüüpi märguannet peaks kasutama, kui vastav sündmus toimub (Näidatakse tegumireal paneb ikooni tegumireal vastava sündmuse korral vilkuma). + + + + +Korda seda, valides uue sündmuse ja meelepärase märguande. Kui oled seadistanud kõik vajalikud märguanded, klõpsa nupule Rakenda. + + + + +Kui oled juba märguanded seadistanud, saad siin lubada või keelata mis tahes toimingud. Näiteks võid soovida, et kõlaks mingi heli, kui sinu hüüdnimi esineb mõnes sõnumis. Kui oled oma arvuti taga, võid helid välja lülitada, aga näiteks arvuti juurest kuhugi lähedusse ära minnes need sisse lülitada, et huvipakkuvast sündmusest kohe teada saada. + + + + +Sa võid lasta ka endale märku anda, kui keegi mainib sinu hüüdnime oma sõnumis. kasutades selleks &konversation;i esiletõstmise võimalust. + + + + + + +Võrgusviibijate jälgimine + +&konversation; võib sulle teada anda, kas sinu sõbrad on parajasti &irc; võrguga ühenduses või mitte. + +Sa võid seostada hüüdnimed oma aadressiraamatu kirjetega. Sellisel juhul lisatakse aadressiraamatu kontaktile sinu sõbra hüüdnimi ja &irc; võrk, milles hüüdnimi parajasti tegutseb. &irc; võrk pannakse kirja seepärast, et hüüdnimi on konkreetses &irc; võrgus unikaalne. Üks ja sama hüüdnimi kahes erinevas &irc; võrgus ei pruugi olla sugugi üks ja sama isik, kuid üldjuhul on üks ja sama hüüdnimi ühe ja sama &irc; võrgu erinevates serverites just üks ja sama isik. + +Seepärast ongi oluline kasutada sama võrku kõigi ühe ja sama &irc; võrgu serverite jaoks võrke, servereid ja automaatselt liituvaid kanaleid määrates. + +Sa võid muidugi lasta jälgida ka sellist hüüdnime, keda sinu aadressiraamatus ei esine. Sellisel juhul on iga hüüdnimi seotud &irc; võrguga. Vaata täpsemalt allpool. + +Hüüdnime jälgimiseks vali menüükäsk Aknad Jälgitavad hüüdnimed võrgus. Ilmub dialoog Jälgitavad hüüdnimed võrgus. + + + + Jälgitavad hüüdnimed võrgus. + + + + + + + + + + + + + + + + Jälgitavad hüüdnimed võrgus + + + + + + + +Siin on kirjas sinu jälgimisnimekirjas olevad hüüdnimed, samuti sinu aadressiraamatu kirjetega seostatud hüüdnimed. Need on ära toodud nendega seotud &irc; võrkude all. Kui kirjas pole ühtegi hüüdnime, siis sa kas pole määranud ühtegi hüüdnime, mida jälgida, või tuleb sul veel hüüdnime jälgimise võimalsus aktiveerida (vaata allpool). Võrgusolevaid hüüdnimesid avades näed kanaleid, millega antud hüüdnimi on parajasti liitunud. Ikoonid kanalite ees on samad ikoonidega kanaliakende hüüdnimede paneelil. +Siin näeb hüüdnime kohta teadaolevat infot. Dialoogi Jälgitavad hüüdnimed võrgus esmakordsel avamisel on info üsna kesine. Iga 8 sekundi järel saadetakse serverile automaatselt käsk WHOIS kõigi hüüdnimede kohta, kelle kohta info puudub. Seda käsku korratakse seni, kuni kõigi hüüdnimede kohta on info olemas. +Hüüdnimed, kes ei ole ühenduses ühegi &irc; võrguga, millega sina oled ühenduses, on kirjas sektsioonis Pole võrgus. +Hüüdnimede juures, mis on seotud kirjega sinu aadressiraamatus, näeb vastavat ikooni (). +Nende nuppudega saab siduda hüüdnime kirjega aadressiraamatus, seose eemaldada või avada aadressiraamatu, et kontakti infot muuta. Vaata ka &aadressiraamat;u käsiraamatut, kus saad põhjalikumalt teada, kuidas ja mida aadressiraamatuga saab ette võtta. + + + +Uute jälgitavate hüüdnimede lisamiseks klõpsa nupule Muuda jälgimisnimekirja. Ilmub dialoog Jälgitavad hüüdnimed. + + + +Jälgitavad hüüdnimed + + + + + + + + + + + + + + + Jälgitavad hüüdnimed + + + + + + + + +Märgi see kastike hüüdnimede jälgimise sisselülitamiseks. + +Kui soovid, et aken Jälgitavad hüüdnimed võrgus avataks automaatselt &konversation;i käivitamisel, märgi ära see kastike. + +Siin on kirjas nende kasutajate hüüdnimed, keda soovid jälgida. Iga hüüdnimega on seotud &irc; võrk. + +Nende nuppudega on võimalik hüüdnimi nimekirja lisada või sealt eemaldada. + +Võimalus Jälgitavad hüüdnimed võrgus saadab perioodiliselt vastava päringu serverile. Siin saab määrata, kui sageli selline päring saadetakse. Ära anna vähemat väärtust kui 20 sekundit, sest see seab serverile muidu liiga ränga koormuse. + +Ülalnäidatud aknas Jälgitavad hüüdnimed võrgus võib hüüdnimel topeltklõpsu tehes saata serverile päringu. Muutuja %u asendatakse hüüdnimga. Käsu lõpus peab olema %n. + + + + +Klõpsa OK, kui iga soovitud hüüdnimi on nimekirja lisatud või sealt eemaldatud. + +Märkus: kui avad akna Jälgitavad hüüdnimed võrgus, kulub veidi aega, enne kui iga vajalik hüüdnimi seal näha on, sest &konversation; peab kõigepealt serverilt andmed hankima. Tavaliselt oleks mõttekas aken Jälgitavad hüüdnimed võrgus üldse lahti jätta. + +&konversation; näitab ka teadet kõigil kanalitel, kui kasutaja, kes on sinu jälgitavate hüüdnimede nimekirjas, serveriga liitub või lahkub. See sõnum näeb välja umbes selline: + +[17:52] [Märguanne] psn on võrgus (irc.kde.org). + + + + + + +Sõnumite esiletõstmine + +Sul on võimalik määrata, kuidas näidatakse sõnumeid kanali- ja päringuaknas. + +Esiletõstmise sisselülitamiseks vali menüükäsk Seadistused &konversation;i seadistamine. Ilmub dialoog Seadistused. + + + +Esiletõstmiste dialoog. + + + + + + + + + + + + + + + + + + + Esiletõstmiste dialoog + + + + + + + + +Klõpsa siia Esiletõstmiste dialoogi valimiseks. +Klõpsa siia uue elemendi lisamiseks esiletõstude nimekirja. Nimekirjas mõne elemendi valimisel saab seda allpool muuta. +Kirjuta siia otsingumuster. Kõik saabuvad sõnumid, milles leitakse antud mustrile vastav tekst, tõstetakse esile. Kui sinu süsteemi on paigaldatud &kde; regulaaravaldiste redaktor, saad seda kasutada mustrist paremal asuvale nupule klõpsates. See redaktor aitab sul vähese vaevaga luua ka väga keerulisi mustreid (&kde; regulaaravaldiste redaktor kuulub paketti kdeutils). +Kui sõnumis leitakse muster, näidatakse kogu sõnumit siin valitud värviga. +Soovi korral võib &konversation; mustri esinemisel ka heli esitada. Klõpsa sellele nupule esitatava helifaili valimiseks. Testinupule klõpsates saad heli kuulda. +Kui soovid, et &konversation; saadaks mustri esinemisel automaatselt vastussõnumi, kirjuta selle tekst siia. Kasuta seda võimalust siiski ettevaatlikult, sest sellised sõnumid võivad pahandada teisi &irc; kasutajaid, eriti kui neid peaks sageli saadetama. Siin võib anda ka &irc; või &konversation;i käske. +Kui oled mõne esiletõstu jaoks määranud heli, saad kõik need keelata sellest kastist märget eemaldades. +Selle kasti märkimisel näidatakse juhul, kui keegi mainib sinu hüüdnime oma sõnumis, antud sõnum paremal valitavas värviga. +Tavaliselt ei tõsteta esile sõnumeid, mida sa ise kirjutad. Kui aga soovid lasta esile tõsta ka enda kirjutatud sõnumeid, märgi see kast ja vali paremal pool värv. + + + + + + + + + +Ekraaniesituse (&osd;) seadistamine + +Ekraaniesitus (On Screen Display ehk &osd;) on &konversation;i unikaalne omadus. &osd; sisselülitamisel ilmuvad kanali sõnumid otse ekraanile ka siis, kui &konversation; on minimeeritud. Siin on näha &osd; tegevus. Sõnum ekraani ülemises vasakpoolses osas on pärit &konversation;ist, mis ise aga töötab süsteemsesse salve minimeerituna. + + + +Ekraaniesituse näide + + + + + + Ekraaniesituse näide + + + + + +&osd; sisselülitamiseks vali menüükäsk Seadistused &konversation;i seadistamine. Ilmub dialoog Seadistused. + + + +Ekraaniesituse dialoog. + + + + + + + + + + + + + + + Ekraaniesituse dialoog + + + + + + + + +Klõpsa siia elemendi Märguanne avamiseks. + +Klõpsa siia OSD valimiseks. + +Märgi see kastike &osd; sisselülitamiseks. + +Klõpsa sellele nupule &osd; fondi valimiseks. Märkus: mitte kõik fondid ei sobi; kindlasti sobivad näiteks Luxi Sans 22 ja Impact 22. + +Märgi siin kastid vastavalt sellele, millist laadi sõnumeid soovid ekraanile ilmumas näha, ja klõpsa siis nupule Rakenda. + + + + + + + + + +Värviliste sõnumite saatmine + +Iga sõnumi võib saata ka värvilisena. Selleks hakka mis tahes kanali sisendreal sõnumit kirjutama. Klõpsa &irc; värvi lisamise nupp &irc; värvi lisamise nupule või vali menüükäsk Lisamine &irc; värv . Ilmub &irc; värvivalija. + + + +&irc; värvivalija. + + + + + + &irc; värvivalija + + + + + +Vali värv ja klõpsa nupule OK. Jätka sõnumi kirjutamist sisendireal. Kui soovid uuesti värvi muuta, klõpsa taas nupule Lisa &irc; värv. Vali mõni muu värv ja klõpsa nupule OK. + + + + + + +Hüüdnimeteemade seadistamine + +Sul on võimalik muuta ikoone, mida näidatakse kanalikaartidel hüüdnimede paneelil hüüdnimede juures. Hüüdnimeteema muutmiseks vali menüükäsk Seadistused Konversationi seadistamine . Ilmub dialoog Seadistused. Klõpsa kirjele Välimus ja seejärel Teemad, mis avab dialoogi Teemad. + + + +Teemade dialoog. + + + + + + + + + + + + + + Teemade dialoog + + + + + + + + +Klõpsa siia hüüdnimede teema valimiseks. +Vali teema. +Teema valimisel näidatakse mõningaid näidisikoone. +Kui oled tõmmanud hüüdnimedeteema kusagilt mujalt, klõpsa selle paigaldamiseks. + + + + + + + + + +Kiirnuppude seadistamine + +Kui valida peaaknas kanali kaart, ilmub nähtavale kaheksa kiirnuppu. Kiirnuppude näitamiseks vali menüükäsk Seadistused Konversationi seadistamine . Ilmub dialoog Seadistused. Vali kaart Käitumine ja seejärel Vestlusaken, märgi ära kasti Kiirnuppude näitamine ja klõpsa OK. + +Kiirnuppe võib oma maitse järgi seadistada, pannes nad sooritama &irc; mõningaid kõige sagedamini ettetulevaid käske. Kiirnuppude seadistamiseks vali menüükäsk Seadistused Konversationi seadistamine. Ilmub dialoog Seadistused. Klõpsa kirjele Käitumine ja seejärel Kiirnupud, mis avab dialoogi Kiirnupud. + + + +Kiirnupud + + + + + + Kiirnupud + + + + + +Siin on kaheksa kiirnuppu. Muutmiseks klõpsa vajalikule kirjele. Veerus Nupu nimi on nimi, mille all nupp on näha peaaknas. Püüa nimed võimalikult lühikesed hoida. Veerus Nupu toiming on toiming, mis sooritatakse, kui klõpsad kiirnupule. Toimingute määramisel saab näha ka vihjeid. + +Muudatuste rakendamiseks klõpsa nupule OK. + +Näide: + + + + + Nupu nimi: Sõnum + + Nupu toiming: Msg %u (siin tuleb jätta tühik %u järele) + + + + + +Nupu kasutamiseks peaaknas vali hüüdnimi hüüdnimede paneelilt ja klõpsa siis nupule. Näed, et sisendreale ilmub /MSG , millele järgneb valitud hüüdnimi. Kirjuta nüüd sõnum, mida soovid antud isikule saata, ja vajuta klahvi &Enter;. Sõnum saadetakse valitud kasutajale ja seda sõnumit näebki peale sinu veel ainult tema. + +Märkus: kiirnuppe ei saa lisada ega kustutada. + + + + + + +Failide saatmine ja saamine + +&irc; võimaldab saata faile teistele võrgusviibivatele kasutajatele või neilt faile vastu võtta. + + +HOIATUS: ära kunagi ava sulle saadetud faili, kui seda ei ole saatnud usaldusväärne isik. Nii võidakse levitada ka viiruseid. + + +Faili saatmiseks mõnele kanalilviibijale vali &HPN;ga klõpsates soovitud isiku hüüdnimi hüüdnimede paneelil (peaaknas). Vali käsk Saada fail . Ilmuvas dialoogis saad valida, millist faili saata. Seejärel ilmub uus kaart DCC olek. + + + +DCC oleku kaart + + + + + + + + + + + + + DCC oleku kaart + + + + + + + + +Siin on näha vastuvõtja hüüdnimi ja faili nimi. + + +Veerg Olek näitab faili saatmise või vastuvõtmise olekut järgmiselt: + + + + + + Pakkumine + + + Püüad saata faili ja &konversation; ootab vastuvõtmisega soostumist. + + + + + Ühendumine + + + &konversation; püüab luua partneriga ühendust. + + + + + Saatmine + + + &konversation; saadab faili. + + + + + Saamine + + + &konversation; saab faili. + + + + + Tehtud + + + Fail on edukalt edastatud. + + + + + Seiskunud + + + Edastus algas, aga peatus mingil põhjusel. + + + + + Katkestatud + + + Kas klõpsasid sina nupule Katkesta või katkestas partner edastuse. + + + + + Ebaõnnestus + + + Tekkis viga, edastus ei õnnestunud. + + + + + Järjekorras + + + Edastusega oldi nõus ning see algab kohe, kui selleks on valmis saaja tarkvara. + + + + + Otsimine + + + &konversation; püüab leida saatja IP aadressi. + + + + + Jätkamine + + + Kui edastuse alates leitakse, et fail on juba kasutaja süsteemis olemas, päritakse kasutajalt: Fail on juba olemas. Kas jätkata edastust? See staatus annab märku, et kasutaja on edastust jätkanud. + + + + + + + + +Kui keegi soovib sulle faili saata, luuakse kaart DCC olek (kui seda juba olemas ei ole). Klõpsa selle nägemiseks kaardi DCC olek tähisel ja kui seejärel klõpsad faili vastuvõtmisega nõustumise nuppu, algabki edastus. Märkus: &konversation; on võimalik panna faile automaatselt vastu võtma ( Seadistused Konversationi seadistamine DCC seadistused ). + + + + + +Kui sul on failide saatmise või saamisega probleeme, blokeerib võib-olla tulemüür või ruuter DCC porte. Vaata osa Küsimused ja vastused. + + + + + + +Põimimine &aadressiraamat;uga. + +Iga hüüdnimi on võimalik seostada &aadressiraamat;us leiduva kontaktiga. Kui oled seda teinud, näitab &konversation; hüüdnimede paneelil hüüdnime järel sulgudes ka tema tegelikku nime. + +Et seostada hüüdnimi kontaktiga &aadressiraamat;us, klõpsa &HPNga; peaakna hüüdnimede paneelil vajaliku isiku hüüdnimel. Vali Keson , mis näitab infot, mille põhjal saad kindlaks teha kasutaja tegeliku nime. Nüüd tee &HPNga; veel kord klõps isiku hüüdnimel ja vali Aadressiraamatu seosed . Avaneb alammenüüd. Kui hüüdnimi ei ole veel seotud mõne kontaktiga, vali Loo uus kontakt . Ilmub dialoog Kontakti muutmine. + + + +Kontakti muutmise dialoog. + + + + + + + + + + + + + Kontakti muutmise dialoog. + + + + + + + + +Siin on hüüdnimi automaatselt ette antud. Kui tead isiku tegelikku nime, kustuta hüüdnimi ja kirjuta tegelik nimi asemele. + + +Pane tähele, et hüüdnimi ei ole siin näha. Selleks... + + + +klõpsa siia akna IM aadressid avamiseks. + + + + + + + IM aadresside aken. + + + + + + IM aadresside aken. + + + + + +Pane tähele, et &konversation; annab ise hüüdnime IRC protokolli tarbeks juba ette. + +Vaata ka &aadressiraamat;u käsiraamatut, kus saad põhjalikumalt teada, kuidas ja mida &kde; aadressiraamatuga saab ette võtta. + +Anna hüüdnime kohta kõikvõimalik lisainfo, mida soovid ja tead, ning klõpsa nupule OK. Seejärel näitab &konversation; hüüdnimede paneelil hüüdnime järel sulgudes ka isiku tegelikku nime. Tegelik nimi ilmub nähtavale ka siis, kui viia hiirekursor hüüdnime kohale. + +Kui hüüdnimi on seostatud kontaktiga &aadressiraamat;us, võid teha hüüdnimede paneelil isiku hüüdnime peal klõpsu &HPNga; ning muuta seostatud kontakti, seostada hüüdnime mõne muu kontaktiga või seose kustutada. + +Kui hüüdnimi on kontaktiga seostatud, aga kasutaja muudab oma hüüdnime ajal, mil sinul &konversation; töötab, muudetakse automaatselt seost ning uus hüüdnimi seostatakse kontaktiga, säilitades samas ka algse seose. + +Kui seostada &irc; hüüdnimi kontaktiga &kopete;s, näeb seda seost ka &konversation;is ning vastupidi. + +Märkus: hüüdnimede paneelil on võimalik ära märkida ka enam kui üks hüüdnimi, klõpsata neil &HPN;ga ja luua mitmikseosed. + + + + + + +&URL;-i hankimine sõnumist + +Igal kanalil edastavad kasutajad mõnikord huvipakkuvate veebilehekülgede või muude internetiressursside &URL;-e. Kui teed sellisel &URL;-il topeltklõpsu, käivitab &konversation; &URL;-iga seonduva rakenduse. Käivitatav rakendus sõltub &URL;-i &MIME; tüübist. Näiteks &URL;, mille alguses seisab http:, avab sinu vaikeveebilehitseja ja näitab veebilehekülge (sa võid ka määrata, millist veebilehitsejat kasutada). Kui &URL; sõnumite reas üle ekraani libiseb, võib olla üpris keeruline seda uuesti üles leida. &konversation; suudab aga sinu eest mugavalt vajalikud &URL;-id meeles pidada. Selleks vali menüükäsk Aknad &url; püüdja . Luuakse uus kaart nimetusega &url; püüdja. + + + +&url; püüdja. + + + + + + + + + + + + + + + + &url; püüdja. + + + + + + + + +See on &URL;-ide nimekiri, mis on esinenud alates &konversation;i käivitamisest. Veerus Hüüdnimi on selle isiku hüüdnimi, kes &URL;-i edastas. Kui hüüdnimi puudub, esines see serveri sõnumite kaardil (&URL;-e, mis esinevad liitumis- ja lahkumisteadetes, nimekiri ei kajasta). Valimiseks klõpsa soovitud &URL;-il. + +Klõpsa siia valitud &URL;-iga seonduva rakenduse käivitamiseks. Käivitatav rakendus sõltub antud &URL;-i &MIME; tüübist. Näiteks &URL;, mille alguses seisab http:, käivitab sinu vaikeveebilehitseja ja avab vastava veebilehekülje. Veebiviitade puhul on sul võimalik ka määrata, millist veebilehitsejat kasutada. + +Klõpsa siia valitud &URL;-i kopeerimiseks &kde; lõikepuhvrisse. + +Klõpsa siia valitud &URL;-i kustutamiseks nimekirjast. + +Klõpsa siia &URL;-ide nimekirja salvestamiseks failina. + +Klõpsa siia nimekirja puhastamiseks. + + + + + + + + + +Eelistatud veebilehitseja määramine + +Kui klõpsad &konversation;is esile tõstetud &URL;-ile, avatakse see rakendusega, mida &kde; vaikimisi seostab antud &URL;-i &MIME; tüübiga. Näiteks klõps &URL;-ile, mille alguses seisab http, avab &konqueror;i ja näitab veebilehekülge. Sa võid siiski määrata mõne muu rakenduse kui &kde; vaikevalik, näiteks kasutada veebilehitsejat Mozilla. + +Muu veebilehitseja määramiseks vali menüükäsk Seadistused &konversation;i seadistamine. Ilmub dialoog Seadistused. + + + +Veebilehitseja dialoog + + + + + + + + + + + + + Veebilehitseja dialoog + + + + + + + + +Klõpsa siia veebilehitseja dialoogi avamiseks. + +Klõpsa siia kinnitamaks, et soovid kasutada muud veebilehitsejat. + +Kirjuta käsk, millega soovitud veebilehitseja käivitada. Kui klõpsad &URL;-ile, asendatakse %u &URL;-iga. + + + + +Vihje: (ainult &UNIX; süsteemides) Vaikekäsk on mozilla '%u', mis käivitab uue Mozilla protsessi iga kord, kui klõpsad &URL;-ile. Kui eelistad, et Mozilla näitaks veebilehekülge juba töötava akna uuel kaardil, loo järgmise sisuga fail: + + +#!/bin/sh +mozilla -remote "openURL($@, new-tab)" || exec mozilla "$@"; + + + +Anna failile nimeks moz, kontrolli, et see asuks sinu otsinguteel (PATH) ja tee fail käivitataks (chmod a+x moz). Seejärel kirjuta ülalolevasse veebilehitseja käsureale moz '%u'. + +Märkus: veebilehitseja seadistused ei rakendu mailto: &URL;-idele. mailto: &URL;-id käivitavad alati &kde; vaikimisi e-posti rakenduse. + +Klõpsa muudatuste rakendamiseks nupule Rakenda. Et kõik rakenduks, tuleb ühendus kõigi serverite ja kanalitega katkestada ja siis uuesti ühendust võtta. Lihtsaim viis selleks on väljuda &konversation;ist ja see uuesti käivitada. + + + + + + +Kanali- ja päringulogide märkimine + +Sul on võimalik lisada marker kanali ja päringu aknasse, mis aitab kiiresti vajaliku info üles leida. Selleks vali menüükäsk Lisamine Meelespidamisrida või kasuta kiirklahvi &Ctrl;R. See tekitab aknas teksti alla rea, mis kerib edasi koos ülejäänud tekstiga. + +Kui soovid lisada meelespidamisrea kõigile kanalitele ja päringutele korraga, vali menüükäsk Seadistused Konversationi seadistamine , ava kaart Käitumine ja seejärel Vestlusaken ning märgi ära kast Meelespidamisrea näitamine kõigil kanalitel/päringutes. + +Seda, kuidas &konversation; lisab automaatselt meelespidamisrea, kui annad käsu /away sõnum. selgitab Identiteedi määramine. + + + + + + +Logimine + +Kui logimine on lubatud, peab &konversation; logi iga serveri, kanali ja privaatvestluse (päringu) seansi kohta. Kõik seansid salvestatakse kettal logifaili. Kui avad sama seansi uuesti, lisab &konversation; uued andmed logifaili lõppu. Logi kasvab suuruseni, mille sa saad ise kindlaks määrata (vaata allpool). Suuruspiirini jõudes hakatakse vanemaid teateid kustutama. + +Seansi taasavamisel loetakse eelmise seansi lõpust umbkaudu 1024 märki ning näidatakse ekraanil. + +Seansi kestel liiguvad sõnumid üle ekraani ja kaovad silmist. Nende nägemiseks saad tagasi kerida. Lõpuks hakatakse siiski selleks, et mälu mitte liigselt kurnata, vanemaid sõnumeid kustutamata. See kannabki nime tagasikerimise limiit. Sõnumid, mis tagasikerimise limiidi tõttu ekraanilt kaovad, jäävad siiski alles logifaili - seda mõistagi juhul, kui logimine on sisse lülitatud. + +Seansi logifaili nägemiseks klõpsa seansi kaardil, millega muudad antud seansi aktiivseks seansiks, ning vali menüükäsk Aken Ava logifail . Ilmub uus kaart, mis näitabki logifaili. + + + +Logifail + + + + + + + + + + + + + + + Logifail + + + + + + + +Siin näeb logifaili sõnumeid. Vanemad teated on ülal, uusimad all. +Klõpsa sellele nupule logifaili salvestamiseks teise failina. +Klõpsa siia logifaili värskendamiseks. Logifaili vaatamise ajal ei lisata pärast faili avamist seanssi tekkinud sõnumeid automaatselt vaatesse. Selle nupuga saab neid aga näidata lasta. +Klõpsa siia logifaili vaate ning kettale salvestatud logifaili puhastamiseks. +Siin saab määrata logifaili maksimaalse suuruse. See hakkab kehtima pärast &konversation;i taaskäivitamist. Igal logifailil võib maksimaalne suurus olla teistest erinev. + + + +Tagasikerimise limiiti saab muuta, kui valida menüükäsk Seadistused &konversation;i seadistamine ning ilmuvast dialoogist Käitumine ja Vestlusaken. Kui kastis Tagasikerimise limiit valida Piiramatu, ei hakatagi ekraanil sõnumeid kustutama. + +Logimise saab lubada või keelata ning selle valikuid määrata menüükäsuga Seadistused &konversation;i seadistamine ning ilmuvast dialoogist Käitumine ja Logimine valides. + + + + + + +&konversation;i käsud + +Allpool on toodud käsud, mida &konversation; iseseisvalt tõlgendab ja mis võivad erineda standardsetest &irc; käskudest. Nurksulgudes asuv osa ei ole kohustuslik. Püstkriipsuga (|) on eraldatud käsu erinevad vormid. Käsud, mida siin ei leitud, saadetakse serverile nii, nagu need sisestatakse. + + + + + +/me sõnum +Saadab sõnumi kanalile, selle ette lisatakse sinu hüüdnimi. Kui näiteks hüüdnimi on Tux, siis kirjutades /me joob parajasti teed, ilmub sõnum Tux joob parajasti teed. Kui kasutajad ei ole just mingil põhjusel rakendanud filtrit teatud sõnumite mittenäitamiseks, peaksid seda nägema kõik kanalil viibijad. Tavaliselt kasutatakse selliseid sõnumeid mitteverbaalse info edastamiseks, näiteks enda tunnete edastamiseks või teatamiseks, mida parajasti tehakse. Kui lahkud aga mõneks ajaks arvuti juurest, kasuta käsku /away. + + + +/ame sõnum +Nagu käsk /me, ainult et sõnum saadetakse kõigile kanalitele ja päringutele, mis on avatud ükspuha millises serveris, millega &konversation; on ühendatud. + + + +/join kanal [parool] +Ühineb kanaliga. Kui server seda lubab ja kanalit ei ole olemas, luuakse sellenimeline kanal ja sa saad selle operaatoriks. Kui kanal nõuab liitumiseks parooli, anna see pärast kanali nime (parool). Enamasti seisab kanalinime alguses #. + + + +/j kanal [parool] +Sama, mis /join. + + + +/part [kanal] [põhjus] +Lahkub kanalilt toodud põhjusel ja sulgeb vastava kanali kaardi. &konversation;i kanali või päringukaardil võib anda lihtsalt käsu /part, mis sulgeb antud kanali või päringu vaikepõhjusega, mille saab määrata kindlaks seadistustedialoogis. + + +/leave [kanal] [põhjus] +Sama, mis /part. + + +/quit +Kanali, päringu või DCC kaardil antuna katkestab ühenduse vastava serveriga ja sulgeb kõik sellel serveril avatud kanali-, päringu- või DCC kaardid. + + +/notice hüüdnimi|kanal sõnum +Saadab sõnumi kasutajale, kelle hüüdnimi on määratud muutujaga hüüdnimi või kõigile antud kanalil. See võib välja näha näiteks selline (kanalikaardil): + +[17:14] [Teade] Teate "Ma arvan, et ma saan aru" saatmine kanalile #konversation + +Ja saajad näevad seda sellisena: + +[17:15] [Teade] -Eisfuchs- Ma arvan, et ma saan aru + + + + +/query hüüdnimi +Loob uue kaardi kasutajaga hüüdnimi privaatvestluse alustamiseks. Tavaliselt nimetatakse seda &irc;-s päringuks. Kõik, mida siin kirjutatakse, on näha ainult sulle ja sinu partnerile. Kui siin anda tühikutega eraldatult enam kui üks hüüdnimi, avatakse päringukaart iga hüüdnime tarbeks. Iga päringukaart ja seal kõneldav on nähtav ainult sulle ja konkreetsele partnerile. + + + +/msg hüüdnimi|kanal sõnum +Saadab sõnumi kasutajale, kelle hüüdnimi on määratud muutujaga hüüdnimi, või kõigile kasutajatele kanalil. Erinevalt käsust /query ei avata uut kaarti. Kui sõnum algab käsuga /me , vormindatakse sõnum samamoodi, nagu käsu /me korral. + +Näited: + +/msg Eisfuchs Mul läheks vaja veidi abi msg käsuga + +/msg #konversation Uus Konvi versioon on üleval! + +/msg Eisfuchs /me kompileerib parajasti käsiraamatut. + + + + + +/smsg hüüdnimi|kanal sõnum +Sama, mis /msg, ainult et sõnumit sinu ekraanil ei näidata. See on mõttekas näiteks paroolide ja muu tundliku info varjamiseks ekraanil või logimise vältimiseks. + + + +/amsg hüüdnimi|kanal sõnum +Sama, mis /msg, ainult et sõnum saadetakse kõigile kanalitele ja päringutele kõigis serverites, millega &konversation; on ühendatud. + + + +/op hüüdnimi +Kanalikaardil sisestatuna püüab anda kasutajale hüüdnimi kanali operaatori õigusi. See ei pruugi toimida, kui käsu andjal ei ole kanalil vastavaid õigusi (selleks peab ise olema eelnevalt kanali operaator). Soovi korral võib anda enam kui ühe hüüdnime, eraldajaks tühikud. + + + +/deop hüüdnimi +Kanalikaardil sisestatuna võtab kasutajalt hüüdnimi kanali operaatori õigused. Soovi korral võib anda enam kui ühe hüüdnime, eraldajaks tühikud. + + + +/oper [hüüdnimi] +Annab kasutajale, kelle hüüdnimi on määratud muutujaga hüüdnimi &irc;-Op ehk administraatori privileegid. See on võimalik ainult siis, kui hüüdnimi esineb serveri O: real. &irc; operaatoritel on õigus suvaline hüüdnimi kõrvaldada (/kill), ühendada serverid &irc; võrguga (/connect) ja veel palju muid õigusi. Kui jätta hüüdnimi sisestamata, püütakse &irc;-Op privileegid anda sulle endale. Nii või teisiti päritakse sinu käest igal juhul &irc;-Op kasutajanime ja parooli. + + + +/voice hüüdnimi +Teatud kanalitel (lipuga +m) ei saa kasutajad sõnumeid saata, kui neil ei ole niinimetatud hääleprivileegi. Selle käsuga püütakse anda kasutajale hüüdnimi just selline õigus. Selle andmiseks peab olema kanali operaator. Enamasti pruugitakse seda siis, kui tegemist on modereeritava kanaliga. + + + +/unvoice hüüdnimi +Võtab kasutajalt hüüdnimi kanalil hääleprivileegi. + + + +/topic [kanal] [sõnum] +Püüab määrata kanali teemaks sõnumi. Kanalikaardil sisestatuna võib kanali ära jätta, sellisel juhul eeldatakse vaikimisi kaardil aktiivset kanalit. Kui ära jätta sõnum, näidatakse kanali parajasti kehtivat teemat. Kanali teema muutmine ei pruugi aga õnnestuda, kui sul selleks õigusi pole. + + + +/away põhjus +Kui keegi püüab sulle privaatsõnumit saata või sind mõnele kanalile kutsuda, saab ta teada, et oled parajasti arvutist eemal toodud põhjusel. Oleku muutmiseks tagasi normaalseks anna käsk /away ilma põhjuseta. + + + +/aaway põhjus +Sama, mis /away, ainult et käsk saadetakse kõigile serveritele, millega &konversation; on ühendatud. + + + +/invite hüüdnimi [kanal] +Kutsub kasutaja, kelle hüüdnimi on määratud muutujaga hüüdnimi, kanaliga liituma. See on eriti kasulik siis, kui kanaliga saabki liituda ainult kutse alusel. Kanalikaardil sisestatuna võib kanali ära jätta. + + + +/exec skript [parameetrid] +Käivitab &konversation;iga ühilduva skripti nimega skript ja annab sellele vajadusel parameetrid. Rohkem infot skriptide kasutamise ja kirjutamise kohta annab osa Skriptide kasutamine. +Näited: + +/exec kdeversion + +Saadab kanalile sinu süsteemi &kde; ja &Qt; versiooni info. + +/exec cmd uname -a + +Saadab kanalile sinu &Linux; versiooni info. + + + + + +/notify [hüüdnimi] +Lisab või eemaldab kasutaja hüüdnimi sinu loendist Jälgitavad hüüdnimed võrgus. Kui hüüdnimi on juba nimekirjas, eemaldatakse ta sealt, kui mitte, siis lisatakse. Kui hüüdnimi ära jätta, näidatakse nimekirja, kus on kirjas iga parajasti jälgitav hüüdnimi. + + + + +/prefs [list|grupp] [list|võti] [väärtus] +Näitab või kehtestab &konversation;i seadistusi ilma seadistustedialoogi avamata. Kui parameetris esineb tühikuid, aseta see jutumärkidesse. + +Näited: + +/prefs list + +Näitab saadaolevaid võtmegruppe. + +/prefs "General Options" list + +Näitab võtmeid grupis General Options koos nende parajasti kehtivate väärtustega. + +/prefs "General Options" ShowTrayIcon + +Näitab parajasti kehtivat väärtust &konversation;i ikooni süsteemses salves näitamise seadistuse kohta. + +/prefs "General Options" ShowTrayIcon false + +Lülitab &konversation;i ikooni näitamise süsteemses salves välja. + + + + +/kick hüüdnimi põhjus +Kanalikaardil sisestatuna püüab lüüa kasutaja, kelle hüüdnimi on määratud muutujaga hüüdnimi, kanalilt minema toodud põhjusel. Kui jätta põhjus andmata, kasutatakse vaikepõhjust, mida saab määrata seadistustedialoogis. Seda käsku saab kasutada ainult kanalikaardil. + + + +/ban [-host|-domain| -userhost|-userdomain] [kanal] kasutaja|mask +Püüab pagendada kasutaja või maski kanalilt. Kanalikaardil sisestatuna võib kanali ära jätta. Rohkem infot masinate, domeenide ja maskide kohta leiab veebist irchelp.org. Kanalilt parajasti pagendatute nimekirja näeb käsuga /mode kanal b. + + + +/unban [kanal] muster +Tühistab varasema kanalilt pagendamise. Kanalikaardil sisestatuna võib kanali ära jätta. + + + +/ignore [-all] hüüdnimi +hüüdnimi lisatakse sinu ignoreeritavate loendisse. Anda võib ka enam kui ühe hüüdnime, eraldajaks tühikud. Kanali sõnumeid ignoreeritavate loendis olevatelt kasutajatelt ei näidata. Lisaks sellele ignoreeritakse -all andmisel üldse igasuguseid kasutajalt pärit sõnumeid (päringud, teadaanded, &CTCP;, DCC, erandid). + + + +/quote käsk +käsk saadetakse serverile. + + + +/say sõnum +Kanalikaardil sisestatuna saadab sõnumi kanalile. Sama, mis sõnumi sisestamine kanali sisendreal. Mõttekas &irc; käskude saatmiseks, kui sa ei soovi käske käivitada. Kaks käsumärki üksteise järel (//) tähendavad samuti /say. Seda kasutatakse ka skriptides sõnumite saatmiseks. + + + +/raw [open|close] +Seab serveri logi toorrežiimi (open) või peatab selle (close). Kui antud pole ei open ega close, eeldatakse vaikimisi, et mõeldud oli open. Toorrežiimis näitab logi iga serverilt saadud sõnumit &irc; loomupärases vormingus. + + + +/konsole +Avab uue kaardi &kde; Konsooliga. + + + +/server [url] [parool] +Võtab ühendust serveriga aadressil url. Kui url ära jätta, võetakse ühendust serveriga, mis on seotud kaardiga, millel käsk sisestati. See on kasulik taasühendumiseks serveriga, kui ühendus mingil põhjusel katkes. Kui server nõuab ühendumiseks parooli, anna see muutujaga parool. Kui server nõuab mingit muud porti kui vaikeport (6667), sisesta url kujul irc.kde.org:6665. + + + +/dcc SEND hüüdnimi [failinimi] +Saadab faili failinimi kasutajale, kelle hüüdnimi on määratud muutujaga hüüdnimi. Kui failinimi ära jätta, ilmub dialoog, kus saab faili valida. + + + +/dcc +Avab DCC oleku kaardi, + + + +/ctcp hüüdnimi|kanal ping +Saadab PING sõnumi kasutajale hüüdnimi või kanalile. Sellest on abi selgitamisel, kas isikul, kellega vestled, on äkki suur võrguviivitus või kas see on sul endal (kui saata käsk kanalile). + + + +/ctcp hüüdnimi|kanal sõnum +Saadab sõnumi kasutajale hüüdnimi või kõigile kasutajatele kanalil. Sama, mis /msg, ainult et sõnum saadetakse &CTCP; protokolli kasutades. Vastus sellele oleneb teise poole kasutatavast &irc; klientprogrammist. Näiteks teise &konversation;i kasutajaga vesteldes tagastab /ctcp Eisfuchs TIME Eisfuchsi arvuti süsteemse aja, /ctcp Eisfuchs VERSION aga Eisfuchsi arvutis töötava &konversation;i versiooni. + + + + + + + + + + +Skriptide kasutamine + +&konversation; pakub mitu vahvat skripti, mida saab käivitada otse rakendusest. Skripti käivitamiseks kanali-, päringu-, DCC või serverikaardil anna käsk kujul + +/exec skript [parameetrid] + +mis käivitab skripti nimega skript, edastades sellele (kui on määratud) parameetrid. + +Kirjuta näiteks kanalikaardil käsk + +/exec kdeversion + +mis edastab kanalile sinu süsteemi &kde; ja &Qt; versiooni. + +/exec cmd uname -a + +käivitab skripti cmd, edastades sellele parameetri uname -a. See saadab kanalile sinu &Linux; versiooni. + +Kõigi saadaolevate skriptide nägemiseks anna Konsoolis järgmine käsk: + +ls $KDEDIR/share/apps/konversation/scripts + +Skripte võib ka ise kirja panna. Need on shelliskriptid ning neid võib kirjutada mis tahes shellikeeles, näiteks bash, perl või python. Kui &konversation; skripti käivitab, saadetakse skriptile kõigepealt kolm parameetrit: + + + +Selle kaardi &irc; serveri pordi number, millel käsk /exec anti. + + +Serveri aadress. + +Kanali nimi. + + + +Toome siin näite shelliskriptist (cmd). + + +#!/bin/sh + +# Käivitab käsu ja saadab väljundi Konversationi. + +PORT=$1; +SERVER=$2; +TARGET=$3; +shift;shift;shift; + +$@ | while read line; do dcop $PORT Konversation say $SERVER "$TARGET" "$@: $line"; done + + + +Pane tähele, et skript kasutab &konversation;iga suhtlemisel &DCOP;-i. Käsk say sunnib väljundi kanalile tavalise sõnumina saatma. Millegi näitamiseks kaardil ilma seda teistele kasutajatele saatmata kasuta käsku info. Skriptide kirjutamisega aitab kindlasti paremini tutvuda näiteskriptide põhjalik uurimine. + +Kui soovid enda loodud skripti käivitada, tuleb see sul paigadalda, kopeerides skripti kataloogi $KDEDIR/share/apps/konversation/scripts või $HOME/.kde/share/apps/konversation/scripts. Failile tuleb anda ka käivitamisõigused, näiteks käsuga chmod a+x minuskript. + + + + + + + + +Käskude seletused + + + + + + +&konversation;i peaaken + + +Failimenüü + + + + F2 Fail Serverite nimekiri + Näitab serverite ja kanalite nimekirja. + + + F7 Fail Kiirühendus + Avab kiirühenduse dialoogi serveriga ühendumiseks. + + + Fail Ühenda uuesti + Loob uuesti ühenduse kõigi serveritega, millega see katkes võrguvea või mõne muu probleemi tõttu. + + + &Ctrl;J Fail Liitu kanaliga + Avab dialoogi, kus saad määrata kanali nime, millega soovid liituda. Sama, mis käsk /join #kanalinimi kanali- või serverikaardil. + + + &Alt; &Ctrl;Q Fail Määra globaalselt eemalolevaks + Muudab sinu hüüdnime oleku kõigil kanalitel eemalolevaks. + + + &Ctrl;Q Fail Välju + Lõpetab &konversation;i töö. + + + + + + +Menüü <guimenu +>Redigeerimine</guimenu +> + + + + &Ctrl;F Redigeerimine Otsi + + Otsib vajalikku teksti aktiivsel ekraanil. + + + + F3 Redigeerimine Otsi järgmine + + Otsib uuesti vajalikku teksti aktiivsel ekraanil, kasutades varem määratud otsingustringi. + + + + &Ctrl;L Redigeerimine Puhasta aken + + Puhastab aktiivse akna sisu. + + + + &Ctrl; &Shift;L Redigeerimine Puhasta kõik aknad + + Puhastab kõigi akende sisu. + + + + + + + +Menüü <guimenu +>Lisamine</guimenu +> + + + + &Ctrl;K Lisamine &irc; värv + + Vaata osa Värviliste sõnumite saatmine. + + + + &Ctrl;R Lisamine Meelespidamisrida + + Vaata osa Kanali- ja päringulogide märkimine. + + + + &Alt; &Shift;C Lisamine Erisümbol + + Lisab erimärgi, näiteks klaviatuuril mitteleiduva tähe. + + + + + + + +Menüü <guimenu +>Järjehoidjad</guimenu +> + + + + &Ctrl;B Järjehoidjad Lisa järjehoidja + + Lisab aktiivse võrgu ja kanali järjehoidjatesse + + + + Järjehoidjad Redigeeri järjehoidjaid + + Avab järjehoidjate redaktori + + + + Järjehoidjad Uus järjehoidjate kataloog + + Loob uue järjehoidjate kataloogi + + + + + + + +Menüü <guimenu +>Seadistused</guimenu +> + + + + &Ctrl;M Seadistused Menüüriba peitmine + + Peidab menüüriba. Selle taasnägemiseks kasuta kiirklahvi &Ctrl;M. + + + + Seadistused Tööriistariba peitmine + + Peidab tööriistariba. + + + + Seadistused Olekuriba peitmine + + Peidab akna allservas asuva olekuriba. + + + + Seadistused Identiteedid + Avab identiteetide dialoogi oma identiteediinfo määramiseks. + + + Seadistused Kiirklahvide seadistamine + + Võimaldab muuta &konversation;i kiirklahve. + + + + Seadistused Tööriistaribade seadistamine + + Võimaldab lisada nuppe &konversation;i tööriistaribale või neid sealt eemaldada. + + + + Seadistused Märguannete seadistamine + + Avab märguannete seadistamise dialoogi. + + + + Seadistused &konversation;i seadistamine + + Avab dialoogi Seadistused. + + + + + + + +Menüü <guimenu +>Aken</guimenu +> + + + + &Ctrl;. Aken Eelmine kaart + + Näitab järjekorras eelmist kaarti. + + + + &Ctrl;, Aken Järgmine kaart + + Näitab järjekorras järgmist kaarti. + + + + &Ctrl;W Aken Sulge kaart + + Sulgeb aktiivse kaardi. Kui see on kanal, lahkub kanalilt. Kui see on serveri teadete kaart, sulgeb kõik antud serveri avatud kanalid ja katkestab ühenduse serveriga. + + + + F11 Aken Sulge kõik avatud päringud + + Sulgeb kõik privaatvestlused (päringud). + + + + &Ctrl;H Aken Peida hüüdnimede nimekiri + + Peidab või toob nähtavale hüüdnimede paneeli kanalikaartidel. + + + + F4 Aken Jälgitavad hüüdnimed võrgus + + Näitab dialoogi Jälgitavad hüüdnimed võrgus. Vaata osa Võrgusviibijate jälgimine. + + + + F5 Aken Kanalite nimekiri + + Näitab serveris saadaolevate kanalite nimekirja. + + + + F6 Redigeerimine &url; püüdja + + Avab &url; püüdja dialoogi. + + + + Aken Uus konsool + + Avab terminaliakna. Avada võib nii mitu konsooliakent, kui süda lustib. + + + + &Ctrl;O Aken Ava logifail + + Avab dialoogi aktiivse kaardi logiteadetega. Toimib ainult kanali, serveri teadete ja päringute kaartide korral. Logimine peab olema sisse lülitatud ( Seadistused Konversationi seadistamine Käitumine Logimine ). + + + + + + + +<guimenu +>Abi</guimenu +>menüü +&help.menu.documentation; + + + + + + + +Küsimused ja vastused +&reporting.bugs; &updating.documentation; + + + +Tahaksin &konversation;i käivitades kohe ühenduda serveriga, aga mitte mõne konkreetse kanaliga. Kuidas seda teha? + + +Jäta dialoogis Serveri redigeerimine sektsioon Kanalid puutumata. + + + + + +&konversation; ei saa ühegi serveriga ühendust. Milles asi? + + +Sellel võib olla mitu põhjust. + + +Kontrolli, et serveri nimi ja port on dialoogis Serveri lisamine korrektselt sisestatud. + + +Kontrolli kaardi Serveri sõnumid teateid. Kas seal on teateid mingitest vigadest? Kas server keeldus ühendusest vigase parooli tõttu? Kas server keeldus seepärast, et talle on vajalik IDENTD, aga sinu arvuti serveri IDENTD soovile ei vastanud? Kas oled märkinud SSL protokolli kasutamist lubava kasti, aga server ei toeta SSL-i? + + +Kui oled tulemüüri taga, kontrolli, et korrektsed pordid oleks ikka lubatud. &konversation; vajab tööks järgmisi porte: + + + +Väljapoole TCP 6667 (või selle serveri port, millega ühendust soovid võtta) +Sissepoole TCP 113 (kui serverile on vajalik IDENTD) + + + + +Rohkem infot &irc; ühenduse probleemide kohta annab irchelp.org. + + + + + + + + + +Kui ma püüan valida käsku Aken Kanalite nimekiri , ei saa ma seda teha. Miks? + + + Aken Kanalite nimekiri on hall ja mittekasutatav, kui parajasti on avatud mingi kanaliväline kaart, näiteks Jälgitavad hüüdnimed võrgus. Et seda käsku valida, muuda aktiivseks mõne kanali või serveri kaart. + + + + + + + + + + +Autorid ja litsents + +&konversation; +Rakenduse autoriõigus 2002-2005: &konversation;i meeskond. +&konviwebsite; + +Kaasautorid: +Dario Abatianni eisfuchs@tigress.com +Peter Simonsson psn@linux.se +Christian Muehlhaeuser chris@chris.de +John Tapsel john@geola.geo.uk +Ismail Donmez ismail.donmez@boun.edu.tr +Shintaro Matsuoka shin@shoegazed.org +Gary Cramblitt garycramblitt@comcast.net +Matthias Gierlings gismore@users.sourceforge.net +&Alex.Zepeda; garbanzo@hooked.net +Stanislav Karchebny berkus@users.sourceforge.net +Mickael Marchand marchand@kde.org + + + +Tänusõnad: +Michael Goettsche michael.goettsche@kdemail.net +Benjamin Meyer ben+konversation@kdemail.net +Jacub Stachowski qbast@go2.pl +Sabastian Sariego segfault@kde.cl +Olivier Bedard www.konversation.org hosting +Frauke Oster frauke@frsv.de +Lucijan Busch lucijan@kde.org +Sascha Cunz mail@sacu.de +Steve Wollkind steve@njord.org +Thomas Nagy thomas.nagy@eleve.emn.fr +Tobias Olry tobias.olry@web.de +Ruud Nabben r.nabben@gawab.com + + + +Dokumentatsiooni autoriõigus © 2003-2005: Gary R. Cramblitt garycramblitt@comcast.net + +Tõlge eesti keelde: Marek Laane bald@starman.ee +&underFDL; &underGPL; + + +Paigaldamine + + + + +&konversation;i hankimine +&install.intro.documentation; &konversation;i uusima versiooni, sealhulgas lähtekoodi ja paigaldamise juhised leiab ka &konversation;i koduleheküljelt. + + + + + + +Nõuded + + + +&konversation;i edukaks kasutamiseks on vajalik &kde; 3.2 või uuem ning internetiühendus. Varasematel &kde; versioonidel puudusid mitmed huvitavad võimalused. Kui kasutad &konversation;i tulemüüri taga asudes, vaata osa Küsimused ja vastused. Kui soovid kasutada SSL protokolli, on vajalik OpenSSL. + + + + +&documentation.index; +
+ + diff --git a/doc/it/Makefile.am b/doc/it/Makefile.am new file mode 100644 index 0000000..9871d98 --- /dev/null +++ b/doc/it/Makefile.am @@ -0,0 +1,2 @@ +KDE_LANG = it +KDE_DOCS = konversation diff --git a/doc/it/addchannel.png b/doc/it/addchannel.png new file mode 100644 index 0000000..caaebaf Binary files /dev/null and b/doc/it/addchannel.png differ diff --git a/doc/it/addnetwork_co.png b/doc/it/addnetwork_co.png new file mode 100644 index 0000000..902ec13 Binary files /dev/null and b/doc/it/addnetwork_co.png differ diff --git a/doc/it/addserver_co.png b/doc/it/addserver_co.png new file mode 100644 index 0000000..7ef6faf Binary files /dev/null and b/doc/it/addserver_co.png differ diff --git a/doc/it/channel_screen_tour_co.png b/doc/it/channel_screen_tour_co.png new file mode 100644 index 0000000..8f286a2 Binary files /dev/null and b/doc/it/channel_screen_tour_co.png differ diff --git a/doc/it/channellist_screen_co.png b/doc/it/channellist_screen_co.png new file mode 100644 index 0000000..581f86a Binary files /dev/null and b/doc/it/channellist_screen_co.png differ diff --git a/doc/it/checkidentities.png b/doc/it/checkidentities.png new file mode 100644 index 0000000..f2f30cd Binary files /dev/null and b/doc/it/checkidentities.png differ diff --git a/doc/it/colorchooser_screen.png b/doc/it/colorchooser_screen.png new file mode 100644 index 0000000..24a899c Binary files /dev/null and b/doc/it/colorchooser_screen.png differ diff --git a/doc/it/first_channel_co.png b/doc/it/first_channel_co.png new file mode 100644 index 0000000..a9ffdbe Binary files /dev/null and b/doc/it/first_channel_co.png differ diff --git a/doc/it/first_serverlist_co.png b/doc/it/first_serverlist_co.png new file mode 100644 index 0000000..5d2127b Binary files /dev/null and b/doc/it/first_serverlist_co.png differ diff --git a/doc/it/identities_adv_co.png b/doc/it/identities_adv_co.png new file mode 100644 index 0000000..a7158ff Binary files /dev/null and b/doc/it/identities_adv_co.png differ diff --git a/doc/it/identities_away_co.png b/doc/it/identities_away_co.png new file mode 100644 index 0000000..fae3f4f Binary files /dev/null and b/doc/it/identities_away_co.png differ diff --git a/doc/it/identities_gen_co.png b/doc/it/identities_gen_co.png new file mode 100644 index 0000000..47128f0 Binary files /dev/null and b/doc/it/identities_gen_co.png differ diff --git a/doc/it/index.docbook b/doc/it/index.docbook new file mode 100644 index 0000000..de091b0 --- /dev/null +++ b/doc/it/index.docbook @@ -0,0 +1,5935 @@ + + + + + IRC"> + CTCP"> + nickname"> + Nickname"> + LED"> + OSD"> + URL"> + MIME"> + + + + + + +]> + + + + + + + + + + + + +Manuale di &konversation; + + + Gary R. Cramblitt garycramblitt@comcast.net +FedericoZenith
zenith@chemeng.ntnu.no
Traduzione della documentazione in italiano
+
+ + + + +2003-2005 +Gary R. Cramblitt + + + + +&FDLNotice; + + + +2005-05-23 +0.18 + + + + +&konversation; è un client &irc; facile da usare per l'ambiente desktop KDE. + + + + + +KDE +kdeextragear-2 +Konversation +irc +internet relay chat +chat +comunicazioni + + +
+ + + + + + +Introduzione + + + +&konversation; è un client &irc; per &kde; 3.2 o successivi. Offre le seguenti funzionalità: + + + +Supporto SSL. +Interfaccia a schede facile da usare. +Pulsanti rapidi personalizzabili per comandi usati di frequente +Riconnessione e riaccesso automatici. +Invio e ricezione DCC. +Elenco dei nick sorvegliati. +Notificazioni visive e sonore per un'ampia varietà di eventi, come messaggi contenenti il tuo nick, o nick nel tuo elenco di sorveglianza che si collegano o scollegano. +Evidenziazione personalizzabile dei messaggi per nick o espressione regolare. +Completamento dei nick. +Cattura e salvataggio di tutti gli &URL; che appaiono nei messaggi. +Vista a schermo dei messaggi, anche quando minimizzato. +Elenco dei nick ignorati. +Accesso automatico e gestione degli accessi. +Segnare le linee nei log. +Scripting. +Integrazione con &kaddressbook;. + + + +Il sito Web di &konversation; è &konviwebsite;. Si possono discutere domande e risposte su &konversation; sulla mailing list degli utenti di &konversation;. Iscrivitici per avere informazioni su nuove funzionalità, segnalare errori e così via. Per tenerti informato sulle nuove versioni, puoi entrare nella nostra mailing list degli annunci di &konversation;. È una mailing list a basso volume di traffico, usata solo per annunciare nuove versioni o correzioni. + +Gli sviluppatori di &konversation; possono spesso essere contattati su &irc; a irc.kde.org canale #konversation. + + + + +Uso di &konversation; + + + + +Se non hai mai usato &irc; prima d'ora... + +In parole povere, &irc; è un protocollo di chat, definito da standard Internet ufficiali, e capace di rubare parecchie ore della tua vita. Per usare &irc;, devi connetterti a un server, e quindi accedere a un canale (equivalente a una chat room) o limitarti a conversazioni private. + +Per connetterti a un server e a un canale, apri &konversation;. Apparirà la schermata Elenco dei Server. + + + +Elenco dei server + + + + + + + + + + + + + Elenco dei server + + + + + + + +L'elenco di Reti &irc; configurate è mostrato qui. Una rete &irc; è una raccolta di server che collaborano. Devi connetterti a solo uno dei server nella rete per essere connesso all'intera rete &irc;. Una volta connesso, &konversation; entrerà automaticamente nei Canali mostrati. Quanto &konversation; viene avviato per la prima volta, la rete Freenode e il canale #kde sono già stati inseriti per te. Fai clic su una rete per selezionarla. +Fai clic qui per definire una nuova Rete, incluso il server a cui connettersi, e i Canali in cui entrare automaticamente una volta connesso. Vedi Definire nuove reti, server ed entrare automaticamente nei canali per maggiori informazioni. +Fai clic qui per connetterti al server e canale &irc; selezionati. + + + + +Quando fai clic sul pulsante Connetti la prima volta che apri &konversation;, potresti vedere il messaggio seguente, che ti dice che la tua identità predefinita non è impostata correttamente. + + + + Controlla le identità + + + + + + Controlla le identità + + + + + +La prima volta che &konversation; viene aperto, ottiene delle informazione sull'utente attuale dal sistema operativo e inserisce dei valori predefiniti per l'identità. Se le informazioni sull'utente del sistema operativo non sono complete (per esempio, se non è definito un nome completo) potresti vedere il messaggio sopra. Per correggere il problema, fai clic su OK e vedi Impostare la tua identità per maggiori informazioni. + + +La schermata Principale mostrerà i messaggi inviati dal server al client (se &konversation; non si dovesse connettere al server, vedi Domande e risposte). Quando i messaggi del server avranno finito di scorrere, &konversation; entrerà nei canali scelti. + + + +Canale. + + + + + + + + + + + + + Canale + + + + + + + + +Questa è chiamata la Linea di input. Per inviare un messaggio a tutti nel canale, scrivi qui il messaggio e premi &Enter;. Il tuo messaggio, come quelli di tutti gli altri, appare nella schermata del canale sopra. Ogni messaggio è preceduto dall'ora e dal nick dell'utente. + +Puoi entrare in altri server e canali aggiuntivi. Ogni server, canale, elenco di canali, e altri schermi hanno qui una linguetta separata. Per mostrare un elenco dei canali disponibili, vedi Elencare i canali disponibili. Per entrare in un canale, scrivi: /join #nomecanale nella Linea di input (il segno # è necessario). Puoi anche scrivere /j come abbreviazione di /join. Per lasciare un canale, scrivi /part. Per passare a un server o canale diverso, fai clic sulla linguetta corrispondente. + +Questo è chiamato il Pannello dei nick. Elenca i nick di tutti gli utenti che sono entrati nel canale, incluso te stesso. + + + + +Questi sono i fondamenti, per informazioni più dettagliate, continua a leggere... + + + + + + +Impostare la tua identità + +Prima di iniziare a usare &konversation; regolarmente, dovresti impostare come sarai identificato sulla rete. + +Fai clic su Impostazioni Identità nel menu principale. Apparirà la schermata Identità. Puoi visualizzare la schermata Identità anche facendo clic sul pulsante Modifica nella schermata Aggiungi rete. + + + +Identità (scheda generale) + + + + + + + + + + + + + + + + + Identità (scheda generale) + + + + + + + +Fai clic qui per selezionare un'Identità da modificare. +Usa questi pulsanti per aggiungere, duplicare, rinominare o rimuovere un'Identità. +Inserisci qui il tuo vero nome. &irc; non è fatto per nasconderti dai tuoi amici o nemici. Tienilo a mente se ti tenta l'idea di comportarti male. Un falso "nome vero" può essere un buon modo di nascondere il tuo sesso a tutti gli sfigati che ci sono là fuori, ma il computer che usi può sempre essere tracciato, quindi non sarai mai del tutto anonimo. +Usa questi pulsanti per aggiungere, modificare o eliminare un nick. +Questo è il tuo elenco di nick. Un nick è il nome con il quale sarai noto agli altri utenti. Puoi inserire qualsiasi nome tu desideri. Il primo carattere deve essere una lettera, gli altri caratteri possono essere lettere, numeri, o i caratteri speciali -[]\`_^{}|. + +Siccome i nick devono essere univoci all'interno di un'intera rete &irc;, il nome che vuoi potrebbe essere respinto dal server perché qualcun altro sta già usando quel nick. Inserisci i tuoi nick alternativi nelle caselle apposite. Se la tua prima scelta è rifiutata dal server, &konversation; proverà con i nick alternativi. + +Secondo la RFC 2812, la lunghezza massima di un nick è 9, ma ciò in realtà è determinato dal server. Per determinare il massimo per un server, connettiti al server. Nella linguetta Messaggi del server, cerca un messaggio [Support]. Per esempio + + +[18:51] *Eisfuchs* [21:45] [Support] Eisfuchs MODES=4 MAXCHANNELS=20 NICKLEN=16 USERLEN=10 HOSTLEN=63 TOPICLEN=450 KICKLEN=450 CHANNELLEN=30 KEYLEN=23 CHANTYPES=# PREFIX=@+ CASEMAPPING=ascii CAPAB IRCD=dancer + + +Il parametro NICKLEN specifica la lunghezza massima dei nick. + + +Usa questi pulsanti per cambiare l'ordine dei nick. Il nick in cima viene provato per primo, quindi verrà provato il prossimo, e così via. +Se hai registrato il tuo nick sulla rete &irc;, inserisci il servizio e la password per autenticare il tuo nick. Quando &konversation; si connetterà, invierà automaticamente /msg servizio IDENTIFY password al server. Se non sai cosa vuol dire, lascia queste caselle vuote. + + + + + +Fai clic sulla linguetta Assente. + + + + Identità (scheda Assente) + + + + + + + + + + + + + Identità (scheda Assente) + + + + + + + +Inserisci un nick che indichi che sei assente. Ogni volta che eseguirai un comando /awaymsg in qualsiasi canale in cui sei entrato con questa Identità, &konversation; cambierà automaticamente il tuo nick nel Nick di assenza. Gli altri utenti potranno vedere che sei assente dal tuo computer. Ogni volta che effettui un comando /away in qualsiasi canale nel quale sei assente, &konversation; farà tornare automaticamente il tuo nick quello originale. Se non vuoi cambiare automaticamente il tuo nick quando sei assente, lascia in bianco. +Se segni questa casella, ogni volta che effettuerai un comando /away, apparirà una riga orizzontale nel canale, che segnerà il punto in cui te ne sei andato. Gli altri utenti &irc; non vedono questa riga. +Se segni questa casella, &konversation; invierà automaticamente il Messaggio di assenza a tutti i canali in cui sei entrato con questa Identità. %s è sostituito con msg. Ogni volta che eseguirai un comando /away, il Messaggio di ritorno sarà mostrato in tutti i canali in cui sei entrato con questa Identità. + +I messaggi di assenza sono spesso considerati fastidiosi dagli altri utenti. Usa questa opzione con attenzione, e con rispetto degli altri utenti &irc;. + + + + + + +Fai clic sulla linguetta Avanzate. + + + + Identità (scheda Avanzate) + + + + + + + + + + + + + + + + Identità (scheda Avanzate) + + + + + + + +Qui puoi inserire un comando che sarà eseguito prima di connettersi al server. Se questa identità viene usata per più di un server, il comando sarà eseguito per ogni server. +Questa impostazione influenza come sono codificati i caratteri che scrivi quando vengono inviati al server. Influenza anche come sono visualizzati i messaggi. Quando apri &konversation; per la prima volta, questa impostazione viene recuperata automaticamente dal sistema operativo. Se sembra che ci siano problemi a leggere i messaggi degli altri utenti, prova a cambiare questa impostazione. +Quando ti connetti, molti server interrogano il tuo computer per avere una risposta IDENT. Se il tuo computer non ha un server IDENT in esecuzione, questa risposta è inviata da &konversation;. Non sono ammessi spazi. Si suggerisce di usare il tuo nome. +Ogni volta che lasci un canale, questo messaggio sarà inviato al canale. +Ogni volta che sei cacciato da un canale (normalmente da un operatore &irc;), questo messaggio verrà inviato al canale. +Fai clic per applicare i tuoi cambiamenti. Per attivare tutti i cambiamenti, devi disconnetterti dal server e riconnetterti. Il modo più semplice per farlo è terminare &konversation; e riavviare. + + + + + + + + + + +Definire nuove reti, server ed entrare automaticamente nei canali + +La schermata Elenco dei server appare quando apri il programma &konversation;. Appare anche quando scegli FileElenco dei server nel menu principale. La schermata Elenco dei file elenca le tue reti &irc; definite esistenti, elencate per gruppo. Una rete &irc; è una raccolta di server cooperanti. Quando ti connetti a qualsiasi server in una rete, hai accesso a tutti i canali della rete. Esempi di reti &irc; sono Freenode e Undernet. + + + + Elenco dei server + + + + + + + + + + + + + + Elenco dei server + + + + + + + +Le tue reti esistenti definite sono elencate qui insieme all'Identità usata per connettersi alla rete, e i Canali in cui entri automaticamente quando ti connetti. Se hai specificato un gruppo delle tue reti, esse sono elencate indentate sotto il gruppo. Fai clic su una rete per selezionarla. +Usa questi pulsanti per aggiungere una nuova rete, modificare una rete evidenziata, o eliminare una rete evidenziata. +Fai clic su questo pulsante per connetterti alla Rete evidenziata e chiudere la schermata Elenco dei server. Puoi evidenziare più di una rete se vuoi, cosa che ti connetterà a tutte le reti evidenziate. +Fare clic su questo pulsante non cancella i cambiamenti che hai apportato. Significa semplicemente che in questo momento non vuoi connetterti a nessuna rete. + + + + + +Quando fai clic sul pulsante Aggiungi, appare la schermata Aggiungi rete. + + + + Aggiungi rete + + + + + + + + + + + + + + + + + + + Aggiungi rete + + + + + + + +Inserisci qui il nome della Rete. Puoi creare tante voci quante ne vuoi nella schermata Elenco dei server all'interno della stessa Rete. +Opzionale: se inserisci qualcosa qui, tutte le reti nello stesso Gruppo saranno elencate insieme nella schermata Elenco dei server. +Scegli un'Identità esistente o fai clic sul pulsante Modifica per aggiungerne una nuova o modificare una esistente. L'Identità ti identificherà e determinerà il tuo nick quando ti connetti alla rete. +Opzionale: questo comando sarà inviato al server dopo la connessione. Esempio: /msg NickServ IDENTIFY konvirocks. Questo esempio è è per la rete Freenode, che richiede che gli utenti registrino il loro nick con una password e accedano alla connessione. konvirocks è la password per il nick dell'Identità. Puoi inserire più di un comando separandoli con punti e virgola. +Segna qui se vuoi che &konversation; si connetta automaticamente a questa rete ogni volta che apri &konversation;. +Questo è un elenco di Server &irc; nella rete. Quando si connetterà alla rete, &konversation; proverà a connettersi al server in alto per primo. Se non funziona, proverà con il secondo. Se non funziona, proverà con il terzo, e così via. Deve essere specificato almeno un server. Fai clic su un server per evidenziarlo. +Usa questi pulsanti per aggiungere un server, modificare un server evidenziato, o eliminare un server evidenziato. Puoi anche regolare l'ordine dell'elenco dei server, e quindi l'ordine dei tentativi di connessione. +Opzionale: questo è un elenco dei canali in cui &konversation; entrerà automaticamente una volta connesso a un server. Puoi lasciarlo in bianco se non vuoi entrare automaticamente in nessun canale. +Usa questi pulsanti per aggiungere un canale, modificare un canale evidenziato, o eliminare un canale evidenziato. Puoi anche cambiare l'ordine in cui si entra nei canali. + + + +Evita di mischiare server su diverse reti &irc; sotto la stessa Rete. Evita di inserire lo stesso server in due reti diverse. Altrimenti, l'integrazione con la tua rubrica e il controllo dei nick collegati di &konversation; non funzioneranno correttamente. + + + + +Quando fai clic sul pulsante Aggiungi, nel riquadro Server, appare la schermata Aggiungi server. + + + + Aggiungi server + + + + + + + + + + + + + + Aggiungi server + + + + + + + +Il nome o numero IP del server. irchelp.org mantiene un elenco di server. +Inserisci il numero della porta che deve connettersi al server. Per la maggior parte dei server, dovrebbe essere 6667. +Se il server richiede una password per connettersi, inseriscila qui, altrimenti lascia in bianco. +Segna se vuoi usare il protocollo SSL (Secure Socket Layer) con il server. Ciò protegge la privacy delle comunicazioni tra il tuo computer e il server &irc;. Il server deve supportare il protocollo SSL affinché funzioni. La maggior parte dei casi, se il server non supporta SSL, la connessione cadrà. + + + + + +Quando fai clic sul pulsante Aggiungi nel riquadro Entra nel canali automaticamente, appare la schermata Aggiungi canale. + + + + Aggiungi canale + + + + + + Aggiungi canale + + + + + +Inserisci un nome di canale. Non dimenticarti del # di testa. Se il canale richiede una password per poterci entrare, inseriscila, altrimenti lascia in bianco. + + + + + + +Elencare i canali disponibili + +Per mostrare un elenco dei canali disponibili, scegli FinestreElenco canali nel menu principale. Dopo una schermata d'avvertimento, viene creata una nuova scheda chiamata Elenco canali. + + + +La scheda Elenco canali. + + + + + + + + + + + + + + + + La scheda Elenco canali. + + + + + + + + +Inserisci qui una stringa di filtraggio. + +Puoi qui limitare l'elenco canali a quei canali con un numero minimo o massimo di utenti. Scegliere 0 disattiva il criterio corrispondente. + +Fai clic qui per recuperare l'elenco dei canali dal server e applicare il filtro. + +L'elenco filtrato dei canali viene mostrato qui. Nota che se non usi espressioni regolari, &konversation; elenca ogni canale che contenga la stringa di filtraggio che hai inserito. Il nome del canale non deve necessariamente iniziare con la stringa che hai inserito. + +Scegli un canale in cui vuoi entrare facendoci clic. Fai clic destro sul canale per avere un elenco di tutti gli indirizzi Web menzionati nel titolo del canale. + +Fai clic qui per entrare nel canale. Verrà creata una nuova scheda per il canale. + + + + +Dovresti evitare di fare clic sul pulsante Aggiorna elenco. La maggior parte dei server hanno migliaia di canali, e fare questa operazione carica molto il server. D'altro canto, può richiedere diversi minuti per essere completata, a seconda della tua larghezza di banda di rete. Se il tuo client è troppo lento, il server potrebbe anche disconnetterti. + +A volte ci sono canali "segreti" sui server. Questi canali non sono elencati nella Elenco canali. Puoi però entrare in questi canali se ne conosci il nome. In una Linea di input, scrivi: /join #nomeDelCanale (il segno # è necessario). Viene creata una nuova scheda per il canale. Se entri in un canale e il Pannello dei nick elenca solo il tuo nick, significa che il canale prima non esisteva. Il server ha creato il canale e tu ne sei l'operatore. In questo caso, probabilmente vorrai chiudere il canale scrivendo: /part. + + + + + + +Una panoramica della schermata principale + +Impariamo di più sulla schermata Principale. La schermata è mostrata sotto con una scheda di canale selezionata. + + + +La schermata Principale. + + + + + + + + + + + + + + + + + + + La schermata Principale + + + + + + + + +Questa è chiamata la Linea di input. Appare solo quando la scheda corrente è un canale. Per mandare un messaggio a tutti quelli che sono nel canale, scrivi qui il messaggio e premi &Enter;. Il tuo messaggio, come quello di chiunque altro, appare nella finestra del canale sovrastante. Ogni messaggio è preceduto dall'ora e dal nick dell'utente. + + Puoi anche incollare testo dagli appunti. Se il testo incollato ha più di una riga (ritorni a capo), apparirà una finestra di dialogo. Modifica il testo come desideri e fai clic su OK. + + Se il testo incollato è più lungo di 256 caratteri, o contiene più di una riga, apparirà un messaggio di avvertimento che ti avvertirà che gli interventi di grandi dimensioni possono causare reimpostazioni della connessione e flooding. Puoi procedere con l'inserimento, ma farlo è una cattiva idea, perché il flooding darà fastidio agli altri nel canale, o potresti essere disconnesso dal server. È meglio mandare il messaggio in spezzoni più corti. + + + + Una convenzione usata in molti canali è far precedere i messaggi diretti a un utente dal suo nick. &konversation; fornisce una comoda funzionalità di completamento nick. Inizia a scrivere il nick dell'utente, quindi premi Tab. &konversation; completerà il resto del nick dell'utente seguito da due punti. Per personalizzare la funzionalità di completamento, scegli ImpostazioniConfigura Konversation dal menu principale, espandi Comportamento, fai clic su Generale, e fai clic sul riquadro Modalità di completamento. + + Qui puoi anche inserire un comando &irc; scrivendo prima / seguito da un comando &irc; valido. Vedi Comandi &irc; usati frequentemente. Su alcuni server, puoi scrivere /help per un elenco dei comandi disponibili, o scrivere /helpcomando per avere aiuto su un comando specifico. + + + +Puoi entrare in server e canali aggiuntivi. Ogni server e ogni canale ha qui una scheda separata. Per mostrare un elenco di canali disponibili, vedi Elencare i canali disponibili. Per entrare in un canale, scrivi: /join #nomeCanale nella linea di input (il segno # è necessario). Per lasciare un canale, scrivi /part. Qui appaiono schede anche quando apri un Elenco canali, partecipi in una conversazione privata, apri il Raccoglitore di &URL;, o apri una o più Konsole. Per far passare la vista schermo a un'altra schermata, fai clic sulla linguetta corrispondente, o usa la ruota del mouse per ruotare attraverso le schede. + +Per impostare altre opzioni per le schede, scegli Impostazioni Configura Konversation nel menu principale, espandi Comportamento e fai clic su Generale. + + + +Questi &led; lampeggeranno quando ci sarà qualcosa che non hai visto in quella scheda. Il &led; lampeggerà più lentamente quando i soli messaggi non visti sono join, part, quit o cambiamenti di nick. Lampeggeranno più velocemente se ci sono messaggi normali non visti. I colori sono come segue: + + Canale + + + Messaggi del server, Elenco canali, o Raccoglitore di &URL; + + + Konsole o Stato DCC. + + + Messaggio privato (query). + + + + +Fai clic qui per chiudere la scheda attuale. Chiudere una scheda Canale abbandonerà il canale. Chiudere una scheda Messaggi del server abbandonerà tutti i canali in cui sei entrato, tutte le conversazioni private aperte in quel server, e disconnetterà dal server. + +Fai clic su questo pulsante per cambiare il tuo nick. Appare solo quando la scheda attuale è un canale. Per nascondere questo pulsante, scegli Impostazioni Configura Konversation nel menu principale, espandi Aspetto, fai clic su Finestra di chat, e deseleziona la casella Mostra il riquadro per cambiare il proprio nick. + +Qui viene visualizzato il titolo del canale. Passa il mouse sul titolo per vedere il titolo esteso. Puoi cambiare il titolo facendo clic sul pulsante alla sua sinistra. Per nascondere i titoli dei canali, scegli Impostazioni Configura Konversation nel menu principale, espandi Aspetto, fai clic su Finestra di chat, e deseleziona la casella Mostra il titolo del canale. + +Questi pulsanti visualizzano lo stato attuale delle modalità dei canali. Un pulsante è premuto se quella modalità è attiva. Se hai i privilegi giusti, puoi anche cambiare le modalità dei canali facendoci clic, o facendo clic sul pulsante alla sinistra del titolo. Per nascondere i pulsanti delle modalità dei canali, scegli Impostazioni Configura Konversation nel menu principale, espandi Aspetto, fai clic su Finestra di chat, e deseleziona la casella Mostra i pulsanti per le modalità dei canali. + + +Questo è detto il Pannello dei nick. È visualizzato ogni qualvolta la scheda corrente sia un canale. Elenca i nick di tutti gli utenti che sono entrati nel canale, incluso te. Passa il puntatore del mouse su un nick per visualizzare informazioni aggiuntive sull'utente. Puoi cambiare come sono visualizzate le icone di fianco a ogni nick cambiando il tema di icone dei nick. Vedi Configurare i temi dei nick per maggiori informazioni. Il tema Big Bullets, come mostrato nella schermata sopra, usa le icone seguenti: + + + utente normale + + + + utente con parola. L'utente può parlare in un canale moderato. + + + + semioperatore del canale + + + + operatore del canale + + + + proprietario del canale + + + + amministratore del canale + + + + + +Inoltre, se un utente è assente, sarà disegnata una crocetta rossa nell'angolo dell'icona. + +Fai clic con il &RMB; su un nick qualsiasi per far apparire un menu contestuale di operazioni che puoi effettuare con quel nick. Per esempio, puoi inviare un file al nick. Questo è anche il posto dove puoi associare un nick a un contatto nella tua rubrica. + +Per nascondere il Pannello dei nick, scegli FinestraNascondi l'elenco dei nick dal menu principale. + + + +Questi sono chiamati i Pulsanti rapidi. Come impostazione predefinita, non sono visualizzati. Per visualizzarli, vedi Configurare i pulsanti rapidi. Puoi personalizzare le loro definizioni a qualsiasi comando tu voglia. + + + + +Nota: puoi controllare quanti messaggi sono visualizzati nel registro dei messaggi delle schede dei canali e delle conversazioni private. Per esempio, puoi cambiare il colore dei messaggi, riprodurre un suono quando viene ricevuto un messaggio che contiene una certa stringa, o rispondere automaticamente ai messaggi. Vedi l'evidenziazione dei messaggi per maggiori informazioni. + +Nota: a volte i nomi dei canali cominciano con &, +, o !. Il primo carattere del nome di un canale ne determina il tipo (RFC 2811) come segue: # - Canali normali. ! - Canali normali. & - Canali locali. Canali in cui si può entrare solo dal server che li ospita. Si può entrare in tutti gli altri canali da qualsiasi server nella rete. + - Canali che non supportano le modalità dei canali. Significa che tutte le modalità sono disattivate, con l'eccezione del flag di canale 't' che è attivo. I nomi dei canali sono lunghi fino a 50 caratteri e possono contenere qualsiasi carattere tranne spazio, virgola e Ctrl-G. + + + + + + +Connessione rapida + +A volte vorrai connetterti a un server senza passare di nuovo dalla creazione di un nuovo server nell'Elenco dei server. + +Scegli FileConnessione rapida nel menu principale. Apparirà la schermata Connessione rapida. + + + +La schermata Connessione rapida. + + + + + + La schermata Connessione rapida + + + + + +Inserisci l'indirizzo del server nella casella hHost del server, il nick che desideri vuoi nella casella Nick, e fai clic sul pulsante Connetti. Quando &konversation; si sarà connesso al server, inserisci il comando /join #nomeCanale per entrare in un canale. + + + + + + +Comandi &irc; usati di frequente + +Quello che segue è un breve elenco di comandi &irc; usati frequentemente. Vedi RFC 2812 per un elenco completo di tutti i comandi, o visita irchelp.org. Per un elenco dei comandi trattati specialmente da , vedi comandi di &konversation;. + + + + + +/help +Elenca i comandi disponibili sul server attuale. Non supportato da tutti i server. + + + +/help comando +Fornisce aiuto per comando. Non supportato da tutti i server. + + + +/join #canale +Entra in #canale. Se il canale non esiste già, viene creato e tu ne divieni l'operatore. + + + +/part +Abbandona il canale attuale e chiude la scheda canale. + + + +/part #canale +Abbandona #canale e chiude la scheda canale corrispondente. Sinonimo di /leave + + + +/me messaggio +Invia messaggio al canale preceduto dal tuo nick. Per esempio, se il tuo nick fosse Tux, scrivere /me fa una tazza di tè mostrerebbe il messaggio Tux fa una tazza di tè. A meno che abbiano filtrato questo tipo di messaggi, tutti gli utenti lo vedranno. Questo genere di messaggi è tipicamente usato per inviare messaggi non verbali, come il tuo stato emozionale attuale, o cosa stai facendo fisicamente. Se stai lasciando la tua macchina per poco tempo, usa piuttosto il comando /away. + + + +/away messaggio +Se qualcuno cerca di inviarti un messaggio privato o ti invita a un canale, gli sarà detto che sei via dalla tua macchina con messaggio. + + + +/away +Annulla un comando /away messaggio. + + + +/query nick +Crea una nuova scheda con il nick dell'utente per una conversazione privata, su &irc; nota anche come query. Ogni cosa scritta qui è visibile solo a te a al tuo compagno di conversazione privata. + + + +/msg nick messaggio +Invia messaggio all'utente con nick nick. Solo nick vede il messaggio. Usa /query per conversazioni più lunghe. + + + +/invite nick +Invita l'utente con nick nick a entrare in un canale. Questo comando è particolarmente utile se il canale è solo su invito. + + + + + + + + + + +Conversazioni private (query) + +Una conversazione privata è una che solo tu e l'altra persona potete vedere. Le conversazioni private sono spesso chiamate "query" in &irc;. Per avviare una conversazione privata, scrivi /query nick in una qualsiasi linea di input, dove nick è il nick della persona con cui vuoi parlare. Puoi anche fare clic con il &RMB; sul nick della persona nel Pannello dei nick e scegliere Apri conversazione privata. Una nuova scheda sarà creata. Annunciati mandando un messaggio. + +Le conversazioni private sono come i canali, eccetto che solo tu e l'altra persona potete partecipare al canale. + +Per abbandonare la conversazione privata, chiudi semplicemente la scheda. Tuttavia, nota che se l'altra persona ti invia un altro messaggio nella conversazione privata, la scheda si riaprirà. + +Per abbandonare tutte le conversazioni private, scegli FinestreChiudi tutte le conversazioni private aperte nel menu principale, o premi F11. + +Quando qualcun altro inizia una conversazione privata con te, &konversation; crea una nuova scheda con il suo nick. Se non vuoi parlare con quella persona, chiudi la scheda. + + + + + + +Impostare le notifiche + +Le Notifiche sono azioni che &konversation; eseguirà ogni qualvolta avviene un evento. Immagina di avere &konversation; in esecuzione, ma minimizzato o nascosto dietro a alle finestre di altre applicazioni sul tuo desktop. Se qualcuno vuole comunicare con te, o un tuo amico entra in un canale, vorresti esserne avvertito. Le notifiche fanno questo. + +Per configurare le notifiche, scegli ImpostazioniConfigura notifiche nel menu principale. Apparirà la schermata Impostazioni di notifica. + +Fai subito clic sul pulsante Più opzioni. + + + +La schermata Impostazioni di notifica. + + + + + + + + + + + + + La schermata Impostazioni di notifica + + + + + + + + +Fai clic qui per selezionare un evento. + +Segna il tipo di notifiche che vorresti avvenissero quando avviene l'evento (Segna la voce della barra delle applicazioni fa lampeggiare la voce nella barra delle applicazioni quando avviene l'evento). + + + + +Ripeti selezionando un altro evento e controllando le notifiche desiderate. Quando hai configurato tutte le notifiche desiderate, fai clic sul pulsante Applica. + + + + +Una volta che hai impostato le tue notifiche, puoi attivare o disattivare tutte le notifiche qui. Per esempio, puoi scegliere di riprodurre un suono ogni volta che il tuo nick viene nominato in un messaggio. Quando sei alla tua macchina, puoi disattivare i suoni, ma mentre sei nelle vicinanze puoi attivarli per avere la tua attenzione. + + + + +Puoi anche farti avvertire quando qualcuno nomina il tuo nick in un messaggio usando la funzionalità di evidenziazione di &konversation;. + + + + + + +Controllare chi è collegato + +&konversation; ti terrà informato su quando i tuoi amici sono connessi alla rete &irc;. + +Puoi associare i nick in rete a dei contatti nella tua rubrica. Quando lo fai, il nick e la rete &irc; dove il nick è collegato sono inseriti nel contatto della rubrica. La rete &irc; è registrata perché i nick sono univoci all'interno di una singola rete &irc;. Il nick in due reti &irc; diverse non è necessariamente la stessa persona, ma lo stesso nick all'interno della stessa rete &irc; è di solito la stessa persona. + +Per questo è importante usare la stessa Rete per tutti i server nella stessa rete &irc;, quando si definiscono reti, server e l'ingresso automatico nei canali. + +Puoi anche definire dei nick che vuoi sorvegliare che non sono nella tua rubrica. Anche in questo caso, ogni nick ha una rete &irc; associata. Vedi sotto. + +Per attivare la funzionalità di sorveglianza dei nick, scegli Finestre Nick sorvegliati collegati nel menu principale. Apparirà la schermata Nick sorvegliati collegati. + + + + Nick sorvegliati collegati. + + + + + + + + + + + + + + + + Nick sorvegliati collegati + + + + + + + +I nick nel tuo elenco di sorveglianza, e anche i nick associati a voci della tua rubrica, sono elencati qui. Sono elencati sotto la loro rete &irc; associata. Se non c'è nessun nick elencato, significa che non ne hai specificato nessuno da sorvegliare, o che devi attivare la funzionalità di sorveglianza dei nick (vedi sotto). Espandi ogni nick collegato per vedere un elenco di canali in cui il nick è entrato. Le icone di fianco a ogni canale sono le stesse che appaiono nel Pannello dei nick nelle schermate dei canali. +Le informazioni note sul nick sono visualizzate qui. Quando la schermata Nick sorvegliati collegati è visualizzata per la prima volta, queste informazioni sono scarse. Ogni otto secondi, viene automaticamente inviato al server un comando WHOIS per richiedere informazioni sui nick che non ne hanno. Questo continua fino a quando tutti i nick hanno informazioni. +I nick che non sono collegati a nessuna rete &irc; a cui sei connesso tu sono elencati nella parte Scollegati dell'elenco. +I nick che sono associati a contatti della tua rubrica hanno questa icona () di fianco alle loro informazioni. +Usa questi pulsanti per associare un nick a un contatto della tua rubrica, rimuovere un'associazione, o aprire la rubrica per modificare le informazioni del contatto. Vedi il Manuale di &kaddressbook; per istruzioni aggiuntive sull'uso della rubrica di &kde;. + + + +Per aggiungere altri nick da sorvegliare, fai clic sul pulsante Modifica l'elenco dei nick sorvegliati. Apparirà la schermata Nick sorvegliati. + + + +Nick sorvegliati + + + + + + + + + + + + + + + Nick sorvegliati + + + + + + + + +Segna questa casella per attivare la funzionalità Sorveglianza dei nick. + +Se vuoi che la schermata Nick sorvegliati collegati sia visualizzata automaticamente quando apri &konversation;, segna questa casella. + +I nick degli utenti che vuoi controllare sono elencati qui. Ogni nick ha una rete &irc; associata. + +Fai clic su questi pulsanti per aggiungere o rimuovere nick dall'elenco. + +La funzionalità Nick sorvegliati collegati funziona interrogando periodicamente il server. Questa casella imposta quanto spesso ciò avviene. Evita numeri inferiori a 20 secondi perché impongono un carico eccessivo sul server. + +Nella schermata Nick sorvegliati collegati sopra, puoi fare doppio clic su qualsiasi nick, e questo comando sarà inviato al server. %u sarà sostituito con il nick. La %n è necessaria alla fine del comando. + + + + +Fai clic sul pulsante OK quando hai finito di aggiungere o rimuovere nick. + +Nota: ogni qualvolta che mostri la schermata Nick sorvegliati collegati, ci potrebbe volere un po' prima che qualsiasi nick sia mostrato, fino a quando &konversation; non avrà interrogato il server. Normalmente, lascerai la schermata Nick sorvegliati collegati in esecuzione. + +&konversation; mostra inoltre un messaggio in tutti i canali ogni qualvolta un utente nel tuo elenco di Nick sorvegliati si connette o disconnette dal server. Il messaggio assomiglia a questo: + +[17:52] [Notifica] psn è collegato (irc.kde.org). + + + + + + +Evidenziazione dei messaggi + +Puoi controllare come sono visualizzati i messaggi nei canali e nelle schermate delle conversazioni private. + +Per attivare la funzionalità di evidenziazione, scegli ImpostazioniConfigura &konversation; dal menu principale. Apparirà la schermata Modifica preferenze. + + + +La schermata Evidenziazione. + + + + + + + + + + + + + + + + + + + La schermata Evidenziazione + + + + + + + + +Fai clic qui per selezionare la schermata Evidenziazione. +Fai clic qui per aggiungere un nuovo elemento nell'Elenco delle evidenziazioni. Quando viene selezionato un elemento dell'elenco, puoi modificarlo nel pannello sotto. +Inserisci qui uno schema di stringa. Ogni messaggio ricevuto che corrisponda a questo schema, in qualsiasi parte, attiverà l'evidenziazione del messaggio. Se hai il programma di modifica delle espressioni regolari di &kde; installato sul tuo sistema, il pulsante a destra dello schema sarà abilitato. Facci clic per visualizzare l'editor, che ti aiuterà a preparare degli schemi complessi. L'editor delle espressioni regolari di &kde; fa parte del pacchetto kdeutils. +Se lo schema viene trovato in un messaggio, tutto il messaggio sarà visualizzato nel colore che selezioni qui. +Se vuoi, &konversation; riprodurrà un suono quando si troverà una corrispondenza allo schema. Fai clic sul pulsante per scegliere un file audio da riprodurre. Fai clic sul pulsante di prova per sentire il suono. +Se volessi che &konversation; inviasse automaticamente un messaggio di risposta quando viene trovata una corrispondenza allo schema, inserisci qui il messaggio. Usa questa funzionalità con prudenza, perché potresti infastidire gli utenti &irc; con troppi messaggi. Qui puoi anche inserire comandi &irc; o di &konversation;. +Se hai configurato dei suoni per una qualsiasi delle tue evidenziazioni, puoi disabilitarli tutti deselezionando questa casella. +Se segni questa casella, ogni volta che qualcuno scriverà il tuo nick in un messaggio, il messaggio sarà visualizzato sulla destra nel colore che scegli. +Normalmente, l'evidenziazione non si applica ai messaggi che scrivi tu. Se vuoi evidenziare i messaggi che scrivi tu, segna questa casella e scegli un colore a destra. + + + + + + + + + +Configurazione della vista a schermo (&osd;) + +La Vista a schermo o On Screen Display (&osd;) è una funzionalità unica di &konversation;. Con l'&osd; attivato, i messaggi dei canali appariranno sul tuo desktop, anche se &konversation; è minimizzato. Ecco un esempio dell'&osd; in azione. Il messaggio nella parte in alto a sinistra dello schermo viene da &konversation;, che è in esecuzione minimizzata nel vassoio di sistema. + + + +Esempio di vista a schermo + + + + + + Esempio di vista a schermo + + + + + +Per attivare l'&osd;, scegli ImpostazioniConfigura &konversation; sul menu principale. Apparirà la schermata Modifica preferenze. + + + +La schermata Vista a schermo. + + + + + + + + + + + + + + + La schermata Vista a schermo + + + + + + + + +Fai clic qui per espandere l'elemento Notifica. + +Fai clic qui per selezionare la schermata Vista a schermo. + +Segna questa casella per attivare l'&osd;. + +Fai clic su questo pulsante per scegliere un tipo di carattere per l'&osd; (Nota: non tutti i tipi di carattere funzionano. È verificato che Luxi Sans 22 e Impact 22 funzionano). + +Segna queste caselle per selezionare i tipi di messaggi che vorresti veder apparire sullo schermo, quindi fai clic sul pulsante Applica. + + + + + + + + + +Inviare messaggi colorati + +Puoi aggiungere dei colori ai messaggi che invii in qualsiasi canale. Nella Linea di input di qualsiasi canale, inizia a scrivere il tuo messaggio. Fai clic sul Pulsante Inserisci colore &irc; pulsante Inserisci colore &irc; o scegli InserisciColore &irc; nel menu principale. Apparirà la schermata Scelta Colori &irc;. + + + +La schermata Scelta Colori &irc;. + + + + + + La schermata Scelta Colori &irc; + + + + + +Scegli un colore e fai clic su OK. Continua a scrivere il tuo messaggio nella Linea di input. Per cambiare ancora il tuo colore, fai clic sul pulsante Inserisci colore &irc;. Scegli un colore diverso e fai clic su OK. + + + + + + +Configurare i temi dei nick + +Puoi cambiare le icone visualizzate di fianco ai nick nel Pannello dei nick delle schede dei canali. Per cambiare il tema dei nick, scegli Impostazioni Configura Konversation dal menu principale. Apparirà la schermata Modifica preferenze. Fai clic suAspetto per espanderlo, quindi fai clic su Temi per visualizzare la schermata Temi. + + + +La schermata Temi. + + + + + + + + + + + + + + La schermata Temi + + + + + + + + +Fai clic per selezionare la schermata Temi dei nick. +Seleziona un tema. +Qui sono visualizzate icone campione del tema scelto. +Se hai scaricato un tema di nick da un'altra parte, fai clic per installarlo. + + + + + + + + + +Configurare i pulsanti rapidi + +Puoi abilitare la funzionalità di visualizzare i Pulsanti rapidi nella schermata principale; appariranno allora otto Pulsanti rapidi. Per visualizzare i pulsanti rapidi, scegli Impostazioni Configura Konversation nel menu principale. Apparirà la schermata Modifica preferenze. Fai clic su Aspetto per espanderlo, quindi fai clic su Finestra di chat. Segna la casella Mostra i pulsanti rapidi e fai clic su OK. + +I pulsanti possono essere personalizzati come vuoi per effettuare comandi &irc; usati di frequente. Per personalizzare i Pulsanti rapidi, scegli Impostazioni Configura Konversation dal menu principale. Apparirà la schermata Modifica preferenze. Fai clic su Comportamento per espanderlo, quindi fai clic su Pulsanti rapidi per mostrare la schermata Pulsanti rapidi. + + + +La schermata Pulsanti rapidi + + + + + + La schermata Pulsanti rapidi + + + + + +Ci sono 8 Pulsanti rapidi. Fai clic su di uno per cambiarlo. La colonna Nome del pulsante è il nome che apparirà sul pulsante nella schermata Principale. Usa nomi brevi. La colonna Azione del pulsante è l'azione che sarà effettuata quando farai clic sul Pulsante rapido. Sullo schermo sono dati dei suggerimenti per creare azioni. + +Fai clic su OK per completare i cambiamenti. + +Esempio: + + + + + Nome del pulsante: Msg + + Azione del pulsante: Msg %u (c'è uno spazio dopo %u) + + + + + +Per usare questo pulsante nella schermata Principale, fai clic su un nick nel Pannello dei nick, quindi fai clic sul pulsante. Apparirà /MSG nella Linea di input seguito dal nick scelto. Scrivi un messaggio che vuoi inviare a quella persona e premi &Enter;. Il messaggio sarà inviato all'utente. Solo quell'utente vedrà il messaggio. + +Nota: non puoi aggiungere o eliminare i Pulsanti rapidi. + + + + + + +Inviare e ricevere file + +Puoi inviare file via &irc; ad altri utenti collegati, o loro possono mandare dei file a te. + + +ATTENZIONE: Non aprire mai un file che qualcuno ti invia a meno che sia una fonte fidata. Potrebbe essere un virus. + + +Per inviare un file a qualcuno in un canale, fai clic con il &RMB; sul nick della persona nel Pannello dei nickdella schermata Principale. Scegli Invia file. Apparirà una finestra di dialogo per farti scegliere un file da inviare. Poi, apparirà una nuova scheda Stato DCC. + + + +La scheda Stato DCC + + + + + + + + + + + + + La scheda Stato DCC + + + + + + + + +Il nick del destinatario e il nome del file appaiono qui. + + +La colonna Stato indica lo stato dell'invio o della ricezione del file come segue: + + + + + + Offerta + + + Stai cercando di inviare un file al destinatario. &konversation; sta aspettando che il destinatario accetti il file. + + + + + Connessione + + + &konversation; sta cercando di stabilire una connessione con l'altro terminale. + + + + + Invio + + + &konversation; sta inviando il file all'altro terminale. + + + + + Ricezione + + + &konversation; sta ricevendo il file dall'altro terminale. + + + + + Fatto + + + Il file è stato trasferito con successo. + + + + + In stallo + + + Il trasferimento è stato avviato ma attualmente non sta procedendo. + + + + + Interrotto + + + O hai fatto clic sul pulsante Interrompi, o l'altra persona ha interrotto il trasferimento. + + + + + Non riuscito + + + È avvenuto un errore e il trasferimento non è riuscito. + + + + + In coda + + + Il trasferimento è stato accettato e comincerà quando il software sul lato ricevente risponderà. + + + + + Ricerca + + + &konversation; sta cercando di ottenere il numero IP del mittente. + + + + + Ripristino + + + Quando comincia un trasferimento ma il file esiste già sul sistema dell'utente, verrà chiesto all'utente Il file esiste già. Riprendere il trasferimento? Questo stato indica che l'utente ha ripreso il trasferimento. + + + + + + + + +Quando qualcuno vuole inviarti un file, sarà creata la scheda Stato DCC (se non è già stata creata). Fai clic sulla scheda Stato DCC per mostrarla. Fai clic sul file per selezionarlo, quindi fai clic su questo pulsante per accettare il file e il trasferimento avrà inizio. Nota: Puoi configurare &konversation; per accettare automaticamente invii da altre persone scegliendo ImpostazioniConfigura KonversationImpostazioni DCC nel menu principale. + + + + + +Se hai problemi a inviare o ricevere file, potrebbe essere il tuo firewall o router che sta bloccando le porte DCC. Vedi Domande e risposte. + + + + + + +Integrazione con &kaddressbook; + +Puoi associare qualsiasi nick con un contatto di &kaddressbook;. Una volta che l'hai fatto, &konversation; mostrerà il vero nome del contatto tra parentesi dopo il nick, nel Pannello dei nick. + +Per associare un nick con un contatto di &kaddressbook;, fai clic con il &RMB; sul nick della persona nel Pannello dei nick della schermata Principale. Scegli Chi è per mostrare delle informazioni per aiutarti a determinare il vero nome dell'utente. Poi, rifai clic con il &RMB; sul nick della persona e scegli Associazioni della rubrica. Apparirà un sottomenu. Se il nick non è già associato a un contatto, scegli Crea nuovo contatto. Apparirà la schermata Modifica contatto. + + + +La schermata Modifica contatto. + + + + + + + + + + + + + La schermata Modifica contatto. + + + + + + + + +Il nick è inserito automaticamente qui. Se conosci il nome vero della persona, sostituiscilo al nick. + + +Nota che il nick non appare qui. Invece, .. + + + +Fai clic qui. Apparirà la finestra Indirizzi IM. + + + + + + + La finestra Indirizzi IM. + + + + + + La finestra Indirizzi IM. + + + + + +Nota che &konversation; ti inserisce il nick con il protocollo IRC. + +Vedi il Manuale di &kaddressbook; per istruzioni aggiuntive sull'uso della rubrica di &kde;. + +Inserisci qualsiasi informazione aggiuntiva sul nick che sai e fai clic su OK. Il nome vero della persona apparirà tra parentesi di fianco al nick nel Pannello dei nick di &konversation;. Il nome vero apparirà anche quando il mouse passerà sopra il nick. + +Una volta che un nick è stato associato a un contatto di &kaddressbook;, puoi fare clic con il &RMB; sul nick della persona nel Pannello dei nick e modificare il contatto associato, associare in nick a un contatto diverso, o eliminare l'associazione. + +Se hai associato un nick con un contatto e l'utente cambia il suo nick mentre stai usando &konversation;, &konversation; assocerà automaticamente il nuovo nick con il contatto, mantenendo anche l'associazione originale. + +Se associ un nick &irc; con un contatto in &kopete;, l'associazione apparirà anche in &konversation; e viceversa. + +Nota: è possibile evidenziare più di un nick nel Pannello dei nick, fai clic con il &RMB; e fai associazioni multiple. + + + + + + +Raccogliere &URL; dai messaggi + +In qualsiasi canale, gli utenti a volte pubblicano gli &URL; di siti interessanti o altre risorse del Web. Puoi fare doppio clic su uno qualsiasi di questi &URL;, e &konversation; avvierà l'applicazione associata con l'&URL;. L'applicazione dipende dal tipo &MIME; dell'&URL;. Per esempio un &URL; che cominci per http: attiverà il tuo browser Web predefinito di &kde; e mostrerà la pagina web (Puoi anche specificare quale browser Web usare). Se l'&URL; scorre oltre la schermata, potresti aver problemi a ritrovarlo. &konversation; può tenerti un comodo elenco di tutti gli &URL;. Per attivare questa funzionalità, scegli FinestreRaccoglitore di &url; nel menu principale. Sarà creata una nuova scheda chiamata Raccoglitore di &url;. + + + +La scheda Raccoglitore di &url;. + + + + + + + + + + + + + + + + La scheda Raccoglitore di &url;. + + + + + + + + +Questo è l'elenco di &URL; visti da quando hai avviato &konversation;. La colonna Nick è il nick della persona che ha pubblicato la &nickname;. Se il nick è vuoto, la &url; è apparsa in una scheda Messaggi del server (gli &URL; che appaiono in messaggi di entrata e di uscita non sono elencati). Fai clic su un &URL; per selezionarlo. + +Fai clic qui per attivare l'applicazione associata con l'&URL; selezionato. L'applicazione avviata dipende dal tipo &MIME; dell'&URL;. Per esempio, un &URL; che comincia per http: attiverà il tuo browser Web predefinito e mostrerà la pagina Web. Per le pagine Web, puoi anche specificare il browser Web da usare. + +Fai clic qui per copiare l'&URL; selezionato agli appunti di &kde;. + +Fai clic qui per eliminare l'&URL; selezionato dall'elenco. + +Fai clic qui per salvare l'elenco di &URL; su un file. + +Fai clic qui per pulire l'elenco. + + + + + + + + + +Impostare il tuo browser Web preferito + +Quando fai clic su un &URL; evidenziato da qualsiasi parte in &konversation;, verrà avviata l'applicazione predefinita di &kde; associata al tipo &MIME; dell'&URL;. Per esempio, quando si fa clic su un &URL; che comincia per http, viene avviato &konqueror; per mostrare la pagina Web. Puoi specificare un'applicazione diversa da quella predefinita di &kde;. Per esempio, puoi usare Mozilla. + +Per scegliere un browser diverso, scegli ImpostazioniConfigura &konversation; sul menu principale. Apparirà la schermata Modifica preferenze. + + + +La schermata browser Web + + + + + + + + + + + + + La schermata browser Web + + + + + + + + +Fai clic qui per mostrare la schermata Browser Web. + +Fai clic qui per specificare che vuoi usare un browser Web personalizzato. + +Inserisci il comando per lanciare il tuo browser desiderato. Quando fai clic su un &URL; %u sarà sostituito con l'&URL;. + + + + +Suggerimento: (solo sistemi &UNIX;) il comando predefinito è mozilla '%u', che avvierà una nuova sessione di Mozilla ogni volta che fai clic su un &URL;. Se preferisci che Mozilla mostri la pagina Web in una nuova scheda di una sessione già avviata, crea un file contenente ciò che segue: + + +#!/bin/sh +mozilla -remote "openURL($@, new-tab)" || exec mozilla "$@"; + + + +Chiama il file moz, mettilo nel PATH, e rendilo eseguibile (chmod a+x moz). Quindi inserisci moz '%u' per il comando per il browser Web nella schermata sopra. + +Nota: l'impostazione Browser Web non si applica a &URL; mailto:. mailto: avvierà sempre il programma di posta predefinito di &kde;. + +Fai clic su Applica per salvare i tuoi cambiamenti. Devi riconnetterti a ciascun server e canale per rendere effettivi i cambiamenti. Il modo più semplice di farlo è terminare e riavviare &konversation;. + + + + + + +Segnale i log dei canali e delle conversazioni private + +Puoi un inserire un marcatore nelle schermate canale e conversazione privata per aiutarti a localizzare rapidamente delle informazioni. Per farlo, scegli InserisciSegnariga nel menu principale, o premi &Ctrl;R. Apparirà una riga in fondo al testo dello schermo. La riga scorrerà con il resto del testo nello schermo. + +Per fare in modo che il Segnariga sia subito inserito in tutti i canali e conversazioni private, scegli Impostazioni Configura Konversation nel menu principale, espandi Comportamento, fai clic su Finestra di chat, e segna la casella Mostra i segnarighe in tutti i canali/conversazioni private. + +Per far inserire a &konversation; un Segnariga ogni volta che esegui un comando /away msg, vedi Impostare la tua identità. + + + + + + +Log + +Se il log è abilitato, &konversation; manterrà un registro di ogni sessione dei Server, Canale, e Conversazione privata. Ogni sessione è conservata su disco in un file di log. Quando riapri la stessa sessione, &konversation; aggiunge al log. Il log cresce fino a un limite che puoi impostare (vedi sotto). Quando il limite è raggiunto, vengono cancellati i messaggi più vecchi. + +Ogni volta che riapri una sessione, circa gli ultimi 1024 caratteri della sessione precedente sono letti dalla coda del log e visualizzati sullo schermo. + +Mentre la tua sessione continua, i messaggi scorrono dalla cima dello schermo. Puoi scorrere all'indietro per vedere questi messaggi. Alla fine, per risparmiare memoria, i messaggi più vecchi sono cancellati dallo schermo. Questo si chiama Limite di scorrimento all'indietro. I messaggi che spariscono dallo schermo a causa del Limite di scorrimento all'indietro sono ancora disponibili nel file di log, se il log è abilitato. + +Per visualizzare il file di log di una sessione, fai clic sulla linguetta della sessione per renderla la sessione corrente, e scegli FinestraApri file di log dal menu principale. Apparirà una nuova scheda che visualizzerà il file di log. + + + +File di log + + + + + + + + + + + + + + + File di log + + + + + + + +I messaggi nel file di log sono visualizzati qui. I messaggi più vecchi sono in cima, e quelli più recenti sono in fondo. +Fai clic su questo pulsante per salvare il file di log in un altro file. +Fai clic per aggiornare la visualizzazione del file di log. Mentre guardi un file di log, i nuovi messaggi nella sessione corrispondente non sono aggiunti automaticamente alla visualizzazione del file di log. Usa questo pulsante per vedere i messaggi più recenti. +Fai clic per cancellare la visualizzazione del file di log e il file di log sul disco. +Usa questa casella per impostare la dimensione massima del file di log. Questa impostazione non avrà effetto finché non riavvierai &konversation;. Ogni file di log può avere un'impostazione diversa. + + + +Il Limite di scorrimento all'indietro può essere cambiato scegliendo Impostazioni Configura &konversation; nel menu principale, quindi espandendo Comportamento e facendo clic su Finestra di chat. La casella Limite di scorrimento all'indietro appare in questa schermata. Se la imposti a Illimitato, i messaggi non sono cancellati dallo schermo. + +Puoi abilitare o disabilitare il log e impostare altre opzioni di log scegliendo Impostazioni Configura &konversation; nel menu principale, quindi espandendo Comportamento e facendo clic su Log. + + + + + + +Comandi di &konversation; + +I comandi seguenti sono interpretati da &konversation; e potrebbero essere diversi dai comandi &irc; standard. Gli elementi tra parentesi quadre sono opzionali. Gli elementi separati da barre (|) sono forme alternative del comando. I comandi non elencati qui sono inviati al server come sono stati inseriti. + + + + + +/me messaggio +Invia messaggio al canale preceduto dal tuo nick. Per esempio, se il tuo nick fosse Tux, scrivere /me fa una tazza di tè mostrerebbe il messaggio Tux fa una tazza di tè. A meno che abbiano filtrato questo tipo di messaggi, tutti gli utenti lo vedranno. Questo genere di messaggi è tipicamente usato per inviare messaggi non verbali, come il tuo stato emozionale attuale, o cosa stai facendo fisicamente. Se stai lasciando la tua macchina per poco tempo, usa piuttosto il comando /away. + + + +/ame messaggio +Come il comando /me sopra, tranne che il messaggio è inviato a tutti i canali e conversazioni private che sono aperte su tutti i server con cui sei connesso con &konversation;. + + + +/join canale [password] +Entra nel canale. Se il server lo permette, e se il canale non esiste già, viene creato e ne sei l'operatore. Se il canale richiede una password per poterci entrare, specificala con password. La maggior parte dei nomi dei canali comincia per # + + + +/j canale [password] +Lo stesso di /join sopra. + + + +/part [canale] [ragione] +Lascia il canale per una ragione e chiude la scheda canale corrispondente. All'interno di un canale di &konversation; o di una scheda di conversazione privata, puoi semplicemente inserire /part che chiude quel canale o conversazione privata con la tua ragione predefinita come data nelle Impostazioni. + + +/leave [canale] [ragione] +Lo stesso di /part sopra. + + +/quit +Quando inserito in qualsiasi canale, conversazione privata o scheda DCC, disconnette dal server corrispondente e chiude tutte le schede di canali, conversazioni private, o DCC aperte su quel server. + + +/notice nick|canale messaggio +Invia il messaggio all'utente con nick nick o a tutti nel canale. Ciò che segue è un esempio di cosa appare quando sei nella scheda dei canali + +[17:14] [Comunicazione] Invio della comunicazione "Penso di capire" a #konversation + +E questo è quello che i destinatari vedono + +[17:15] [Comunicazione] -Eisfuchs- Penso di capire + + + + +/query nick +Crea una nuova scheda con il nick dell'utente per una conversazione privata, comunemente nota su &irc; anche come query. Tutto ciò che è scritto qui è visibile solo a te a al tuo compagno di conversazione privata. Puoi inserire più di nick separati da spazi e una scheda di conversazione privata sarà aperta per ogni nick. Ognuna di queste schede saranno private tra te e il compagno di conversazione. + + + +/msg nick|canale messaggio +Invia un messaggio privato all'utente con nick nick o a tutti gli utenti nel canale. Al contrario di /query, non apre una nuova scheda. Se il messaggio comincia con /me , il messaggio viene formattato allo stesso modo del comando /me. + +Esempi + +/msg Eisfuchs Ho bisogno di aiuto per il comando msg + +/msg #konversation È disponibile la nuova versione di Konvi! + +/msg Eisfuchs /me sta compilando adesso il manuale. + + + + + +/smsg nick|canale messaggio +Lo stesso che /msg eccetto che il messaggio non viene mostrato sul tuo schermo. È utile per evitare che password e altre informazioni sensibili rimangano esposte sul tuo schermo o siano registrate. + + + +/amsg nick|canale messaggio +Come il comando /msg sopra, eccetto che il messaggio è inviato a tutti i canali e conversazioni private che hai aperto su tutti i server su cui sei connesso in &konversation;. + + + +/op nick +Quando inserito in una scheda di canale, prova a dare privilegi di operatore del canale a nick. Potrebbe non funzionare se ti mancano i privilegi sufficienti nel canale (devi essere tu stesso un operatore del canale). Puoi inserire più nick separati da spazi. + + + +/deop nick +Quando inserito in una scheda di canale, toglie i privilegi di operatore del canale da nick. Puoi inserire più nick separati da spazi. + + + +/oper [nick] +Concede all'utente con nick nick privilegi di operatore &irc; (amministratore). Funziona soltanto se il nick è elencato nella riga O: del server. Gli operatori &irc; hanno il privilegio di eseguire /kill sui nick, /connect sui server per connetterli alla rete &irc;, e altro. Se nick non è inserito, cerca di concederti i privilegi di operatore &irc;. In ogni caso ti sarà chiesto il tuo nome utente da operatore &irc; e la password. + + + +/voice nick +In certi canali (con il flag +m), gli utenti non possono inviare messaggi a meno che abbiano i privilegi di parola. Questo comando prova a dare i privilegi di parola a nick. Devi avere privilegi di operatore di canale per eseguire questo comando. Questo comando è usato per lo più quando sei operatore di un canale moderato. + + + +/unvoice nick +Togli i privilegi di parola nel canale da nick. + + + +/topic [canale] [messaggio] +Prova a impostare il titolo del canale a messaggio. Quando inserito in una scheda di un canale, canale può essere omesso e assume come valore predefinito il canale attivo della scheda. Se il messaggio è omesso, mostra il titolo attuale del canale. Potrebbe non essere possibile cambiare il titolo di un canale se ti mancano i privilegi sufficienti. + + + +/away ragione +Se qualcuno cerca di inviarti un messaggio privato o ti invita a un canale, gli sarà detto che sei via dalla tua macchina per una ragione. Per far tornare il tuo stato alla normalità, inserisci /away senza una ragione. + + + +/aaway ragione +Come il comando /away sopra, eccetto che il comando è inviato a tutti i server con cui sei connesso in &konversation;. + + + +/invite nick [canale] +Invita l'utente con nick nick a entrare in un canale. Questo comando è particolarmente utile se il canale è solo su invito. Quando inserito in una scheda di canale, canale si può omettere. + + + +/exec script [parametri] +Esegue lo script di shell compatibile di &konversation; chiamato script, passandogli dei parametri. Vedi Scripting per maggiori informazioni sull'uso e la scrittura degli script. +Esempi: + +/exec kdeversion + +Invia i numeri di versione di &kde; e &Qt; del tuo sistema al canale. + +/exec comando uname -a + +Invia la tua stringa di versione di &Linux; al canale. + + + + + +/notify [nick] +Aggiunge o rimuove un nick dal tuo elenco dei nick sorvegliati collegati. Se il nick è già nell'elenco, ne è rimosso. Se non è nell'elenco, viene aggiunto. Se nick è omesso, mostra l'elenco corrente dei nick sorvegliati. + + + + +/prefs [list|gruppo] [list|opzione] [valore] +Mostra o imposta le impostazioni di &konversation; senza usare la schermata Impostazioni. Se un parametro contiene spazi, mettilo tra virgolette. + +Esempi: + +/prefs list + +elenca i gruppi di opzioni disponibili. + +/prefs "Opzioni generali" list + +elenca le opzioni disponibili nel gruppo Opzioni generali insieme ai loro valori attuali + +/prefs "Opzioni generali" MostraIconaVassoio + +Mostra il valore attuale dell'impostazione per mostrare l'icona di &konversation; nel vassoio di sistema. + +/prefs "Opzioni generali" MostraIconaVassoio false + +Togli l'icona di &konversation; dal vassoio di sistema. + + + + +/kick nick ragione +Quando inserito in una scheda di canale, prova a cacciare l'utente con nick nick dal canale con una ragione. Se la ragione non è inserita, assume come valore predefinito la ragione nelle Impostazioni. Questo comando può essere usato solo all'interno di una scheda di canale. + + + +/ban [-host|-domain| -userhost|-userdomain] [canale] utente|maschera +Prova a mettere al bando l'utente o la maschera dal canale. Quando inserito in una scheda di canale, canale può essere omesso. Per maggiori informazioni su host, domini e maschere, vedi il documento a irchelp.org. Per avere l'elenco attuale degli utenti messi al bando di un canale, inserisci /modecanale b. + + + +/unban [canale] schema +Annulla una messa al bando antecedente nel canale. Quando inserito in una scheda di canale, canale può essere omesso. + + + +/ignore [-all] nick +Aggiunge nick al tuo elenco da ignorare. Puoi specificare più nick separati da spazi. I messaggi sul canale provenienti da utenti nel tuo elenco da ignorare non sono visualizzati. Inoltre, se inserisci -all, tutti i tipi di messaggio (conversazioni private, &CTCP;, DCC ed eccezioni) dall'utente sono ignorati come i messaggi sul canale. + + + +/quote comando +Invia un comando al server. + + + +/say messaggio +Quando inserito in una scheda di canale, invia un messaggio al canale. Ciò è lo stesso che inserire il messaggio nella linea di input del canale. Utile per inviare comandi &irc; quando non vuoi eseguire il comando. Due caratteri di comando (//) in fila fanno la stessa cosa di /say. Usato anche dagli script per inviare messaggi. + + + +/raw [open|close] +Mette il log del server in modalità grezza (open) o chiude la modalità grezza (close). Se non viene specificato né openclose, assume open. In modalità grezza, il log visualizza ogni messaggio ricevuto dal server in formato &irc; nativo. + + + +/konsole +Apre una nuova scheda con la &konsole; di &kde;. + + + +/server [url] [password] +Connette al server all'indirizzo url. Se url è omesso, connette al server associato alla scheda dove inserisci il comando. È utile per riconnettersi a un server dopo una disconnessione. Se il server richiede una password per connettersi, inseriscila al posto di password. Se il server richiede un numero di porta diverso dal predefinito (6667), inserisci l'url come segue irc.kde.org:6665. + + + +/dcc SEND nick [nome file] +Invia nome file all'utente con nick nick. Se nome file è omesso, appare un dialogo per selezionare un file. + + + +/dcc +Apre una scheda di stato DCC. + + + +/ctcp nick|canale ping +Invia un messaggio di PING a un nick o canale. È utile per determinare se qualcuno con cui stai parlando ha un grande ritardo di connessione, o (quando inviato a un canale) se è il tuo sistema ad avere un grande ritardo. + + + +/ctcp nick|canale messaggio +Invia un messaggio a nick o a tutti gli utenti nel canale. È simile al comando /msg sopra, eccetto che il messaggio è inviato usando il protocollo &CTCP;. La risposta dall'altro capo dipende dal programma client &irc; che l'utente sta usando. Per esempio, quando stai conversando con un altro utente di &konversation;, /ctcp Eisfuchs TIME restituirà l'ora di sistema sul computer di Eisfuchs. /ctcp Eisfuchs VERSION restituirà il numero di versione di &konversation; sul computer di Eisfuchs. + + + + + + + + + + +Scripting + +&konversation; ha alcuni script utili che puoi eseguire dal programma. Per eseguire uno script in una scheda di canale, conversazione privata, DCC o server, scrivi un comando nella forma + +/exec script [parametri] + +che esegue lo script chiamato script passandogli dei parametri (opzionali). + +Per esempio, scrivi il comando seguente nella scheda di un canale + +/exec kdeversion + +per inviare i tuoi numeri di versione di &kde; e &Qt; al canale. + +/exec comando uname -a + +esegue lo script commando, passandogli uname -a. Invia la tua stringa della versione di &Linux; al canale. + +Per avere un elenco di tutti gli script disponibili, scrivi il comando seguente in uno schermo di &konsole;. + +ls $KDEDIR/share/apps/konversation/scripts + +Puoi scrivere i tuoi script. Gli script sono script di shell e possono essere scritti in qualsiasi linguaggio di shell, come bash, perl, o python. Quando &konversation; esegue uno script, i primi tre parametri inviati allo script sono: + + + +Il numero di porta per il server &irc; della scheda dove è stato inserito il comando /exec. + + +L'indirizzo del server. + +Il nome del canale. + + + +Ecco uno script shell di esempio (comando). + + +#!/bin/sh + +# Esegue un comando e stampa l'output in Konversation. + +PORT=$1; +SERVER=$2; +TARGET=$3; +shift;shift;shift; + +$@ | while read line; do dcop $PORT Konversation say $SERVER "$TARGET" "$@: $line"; done + + + +Nota che lo script usa &DCOP; per comunicare con &konversation;. Il comando say fa inviare l'output al canale come messaggio normale. Per mostrare qualcosa nella scheda senza inviarla ad altri utenti, usa piuttosto info. Guarda i file script esistenti per ulteriori esempi di come scrivere script. + +Per poter eseguire uno script che hai scritto tu, devi installarlo copiandolo in $KDEDIR/share/apps/konversation/scripts o in $HOME/.kde/share/apps/konversation/scripts. Devi anche dare al file privilegi di esecuzione, per esempio chmod a+x mioscript. + + + + + + + + +Riferimento comandi + + + + + + +La finestra principale di &konversation; + + +Il menu File + + + + F2 File Elenco dei server + Mostra l'elenco dei server e canali. + + + F7 File Connessione rapida + Mostra la schermata Connessione rapida per connettersi a un server. + + + File Riconnetti + Si riconnette a tutti i server che sono stati disconnessi per un errore di rete o per un altro problema. + + + &Ctrl;J File Entra nel canale + Visualizza una finestra per inserire il nome di un canale in cui entrare. Fa la stessa cosa di inserire /join #nomecanale in una scheda di canale o server. + + + &Alt; &Ctrl;Q File Imposta come assente globalmente + Cambia lo stato del tuo nick ad assente in tutti i canali. + + + &Ctrl;Q File Esci + Esce da &konversation; + + + + + + +Il menu <guimenu +>Modifica</guimenu +> + + + + &Ctrl;F Modifica Trova + + Cerca stringhe di testo nella schermata attuale. + + + + F3 Modifica Trova successivo + + Cerca di nuovo stringhe di testo nella schermata attuale usando la stringa di ricerca precedente. + + + + &Ctrl;L Modifica Pulisci finestra + + Pulisce la schermata corrente. + + + + &Ctrl; &Shift;L Modifica Pulisci tutte le finestre + + Pulisce tutte le schermate. + + + + + + + +Il menu <guimenu +>Inserisci</guimenu +> + + + + &Ctrl;K Inserisci Colore &irc; + + Vedi Inviare messaggi colorati. + + + + &Ctrl;R Inserisci Segnariga + + Vedi Segnare log di canali e conversazioni private. + + + + &Alt; &Shift;C Inserisci Carattere speciale + + Usato per inserire caratteri speciali, come i caratteri stranieri. + + + + + + + +Il menu <guimenu +>Segnalibri</guimenu +> + + + + &Ctrl;B Segnalibri Aggiungi segnalibro + + Aggiunge un segnalibro per la rete e il canale attuali + + + + Segnalibri Modifica segnalibri + + Apre l'editor dei segnalibri + + + + Segnalibri Nuova cartella di segnalibri + + Crea una nuova cartella di segnalibri + + + + + + + +Il menu <guimenu +>Impostazioni</guimenu +> + + + + &Ctrl;M Impostazioni Nascondi la barra dei menu + + Nasconde la barra dei menu. Premi &Ctrl;M per farla riapparire. + + + + Impostazioni Nascondi barra degli strumenti + + Nasconde la barra degli strumenti. + + + + ImpostazioniNascondi la barra di stato + + Nasconde la barra di stato in fondo allo schermo principale. + + + + Impostazioni Identità + Mostra la schermata Identità per impostare le tue informazioni di identificazione. + + + ImpostazioniConfigura scorciatoie + + Ti permette di cambiare le scorciatoie da tastiera di &konversation;. + + + + Impostazioni Configura barre degli strumenti + + Ti permette di aggiungere o rimuovere pulsanti dalla barra degli strumenti di &konversation;. + + + + ImpostazioniConfigura notifiche + + Mostra la schermata Impostazioni notifiche. + + + + ImpostazioniConfigura &konversation; + + Mostra la schermata Modifica preferenze. + + + + + + + +Il menu <guimenu +>Finestra</guimenu +> + + + + &Ctrl;. Finestra Scheda precedente + + Mostra la schermata corrispondente alla scheda precedente. + + + + &Ctrl;, Finestra Scheda successiva + + Mostra la schermata corrispondente alla scheda successiva. + + + + &Ctrl;W Finestra Chiudi scheda + + Chiude la schermata attuale. Se si chiude un canale, lascia il canale. Se si chiude una scheda Messaggi del server, chiude tutti i canali aperti su quel server e si disconnette dal server. + + + + F11 Finestra Chiudi tutte le conversazioni private aperte + + Chiude tutte le conversazioni private. + + + + &Ctrl;H Finestra Nascondi l'elenco dei nick + + Nasconde (o visualizza) il pannello dei nick nelle schede dei canali. + + + + F4 Finestra Nick sorvegliati collegati + + Mostra la schermata Nick sorvegliati collegati. Vedi Controllare chi è collegato. + + + + F5 Finestra Elenco dei canali + + Mostra un elenco di canali disponibili sul server. + + + + F6 Finestra Raccogliotore di &url; + + Mostra la schermata Raccoglitore di &url;. + + + + Finestra Nuova Konsole + + Mostra una schermata di terminale. Puoi aprire tante schede Konsole quante vuoi. + + + + &Ctrl;O Finestra Apri file di log + + Mostra una schermata con il log dei messaggi della scheda attuale. Funziona solo per schede di Canale, Messaggi del server e Conversazioni private. L'attività di log deve essere attivata in Impostazioni Configura Konversation Comportamento Log nel menu principale. + + + + + + + +Il menu <guimenu +>Aiuto</guimenu +> +&help.menu.documentation; + + + + + + + +Domande e risposte +&reporting.bugs; &updating.documentation; + + + +Quando avvio &konversation;, vorrei connettermi a un server senza entrare in nessun canale. Come si fa? + + +Nella schermata Modifica server, lascia vuoto il riquadro Canali. + + + + + +&konversation; non vuole connettersi a nessun server. Cosa c'è che non va? + + +Potrebbero non andare un po' di cose. + + +Assicurati di aver inserito il Nome del server giusto e la Porta giusta nella schermata Elenco dei server. + + +Controlla se ci sono messaggi d'errore nell'output nella schermata Messaggi del server. Il server ha rifiutato la connessione a causa di una password sbagliata? Il server ha rifiutato la connessione perché richiede IDENTD e il tuo sistema non ha risposto alla richiesta IDENT? Hai segnato la casella del protocollo SSL ma il server non supporta SSL? + + +Se sei dietro un firewall, assicurati che le porte giuste siano attivate. &konversation; ha bisogno delle seguenti porte attivate: + + + +TCP 6667 in uscita (o la porta del server a cui ti connetti) +TCP 113 in arrivo (se il server richiede IDENTD) + + + + +Per maggiori informazioni sui problemi di connessione in &irc;, riferisciti a irchelp.org. + + + + + + + + + +Quando vado a FinestraElenco dei canali, non posso selezionarlo. Perché? + + +La voce di menu FinestreElenco dei canali sarà scritta in grigio e inaccessibile se una scheda non di canale, per esempio Nick sorvegliati collegati, è attualmente visualizzata. Per farla tornare selezionabile, torna a una scheda di canale o alla scheda dei server. + + + + + + + + + + +Riconoscimenti e licenza + +&konversation; +Copyright del programma 2002-2005 della squadra di &konversation;. +&konviwebsite; + +Hanno contribuito: +Dario Abatianni eisfuchs@tigress.com +Peter Simonsson psn@linux.se +Christian Muehlhaeuser chris@chris.de +John Tapsel john@geola.geo.uk +Ismail Donmez ismail.donmez@boun.edu.tr +Shintaro Matsuoka shin@shoegazed.org +Gary Cramblitt garycramblitt@comcast.net +Matthias Gierlings gismore@users.sourceforge.net +&Alex.Zepeda; garbanzo@hooked.net +Stanislav Karchebny berkus@users.sourceforge.net +Mickael Marchand marchand@kde.org + + + +Grazie a: +Michael Goettsche michael.goettsche@kdemail.net +Benjamin Meyer ben+konversation@kdemail.net +Jacub Stachowski qbast@go2.pl +Sabastian Sariego segfault@kde.cl +Olivier Bedard www.konversation.org hosting +Frauke Oster frauke@frsv.de +Lucijan Busch lucijan@kde.org +Sascha Cunz mail@sacu.de +Steve Wollkind steve@njord.org +Thomas Nagy thomas.nagy@eleve.emn.fr +Tobias Olry tobias.olry@web.de +Ruud Nabben r.nabben@gawab.com + + + +Copyright della documentazione © 2003-2005 di Gary R. Cramblitt garycramblitt@comcast.net + +Federico Zenithzenith@chemeng.ntnu.no +&underFDL; &underGPL; + + +Installazione + + + + +Come ottenere &konversation; +&install.intro.documentation; Le ultime versioni di &konversation;, inclusi il codice sorgente e istruzioni di compilazione, possono essere ottenute dalla pagina Web di &konversation;. + + + + + + +Requisiti + + + +Per usare &konversation;, hai bisogno di &kde; 3.2 o successivo, e di una connessione di rete. Su versioni precedenti di &kde; alcune funzionalità potrebbero mancare. Se userai &konversation; da dietro un firewall, vedi Domande e risposte. Se vuoi usare un protocollo SSL, potresti aver bisogno di OpenSSL. + + + + +&documentation.index; +
+ + diff --git a/doc/it/nicksonline_co.png b/doc/it/nicksonline_co.png new file mode 100644 index 0000000..72cb251 Binary files /dev/null and b/doc/it/nicksonline_co.png differ diff --git a/doc/it/notification_screen_co.png b/doc/it/notification_screen_co.png new file mode 100644 index 0000000..0214750 Binary files /dev/null and b/doc/it/notification_screen_co.png differ diff --git a/doc/it/notifylist_screen_co.png b/doc/it/notifylist_screen_co.png new file mode 100644 index 0000000..ebb9547 Binary files /dev/null and b/doc/it/notifylist_screen_co.png differ diff --git a/doc/it/osd_demo.png b/doc/it/osd_demo.png new file mode 100644 index 0000000..f5ff785 Binary files /dev/null and b/doc/it/osd_demo.png differ diff --git a/doc/it/osd_screen_co.png b/doc/it/osd_screen_co.png new file mode 100644 index 0000000..666b7e2 Binary files /dev/null and b/doc/it/osd_screen_co.png differ diff --git a/doc/it/quickbuttons_screen.png b/doc/it/quickbuttons_screen.png new file mode 100644 index 0000000..cf7eaaa Binary files /dev/null and b/doc/it/quickbuttons_screen.png differ diff --git a/doc/it/quickconnect_screen.png b/doc/it/quickconnect_screen.png new file mode 100644 index 0000000..fe5f8b2 Binary files /dev/null and b/doc/it/quickconnect_screen.png differ diff --git a/doc/it/serverlist_co.png b/doc/it/serverlist_co.png new file mode 100644 index 0000000..b12b553 Binary files /dev/null and b/doc/it/serverlist_co.png differ diff --git a/doc/konversation/Makefile.am b/doc/konversation/Makefile.am new file mode 100644 index 0000000..e76f3ec --- /dev/null +++ b/doc/konversation/Makefile.am @@ -0,0 +1,9 @@ +####### kdevelop will overwrite this part!!! (begin)########## + +SUBDIRS = + +####### kdevelop will overwrite this part!!! (end)############ + +KDE_LANG = en +KDE_DOCS = konversation + diff --git a/doc/konversation/addchannel.png b/doc/konversation/addchannel.png new file mode 100644 index 0000000..e8a4727 Binary files /dev/null and b/doc/konversation/addchannel.png differ diff --git a/doc/konversation/addnetwork_co.png b/doc/konversation/addnetwork_co.png new file mode 100644 index 0000000..e9e8ae7 Binary files /dev/null and b/doc/konversation/addnetwork_co.png differ diff --git a/doc/konversation/addserver_co.png b/doc/konversation/addserver_co.png new file mode 100644 index 0000000..5dead32 Binary files /dev/null and b/doc/konversation/addserver_co.png differ diff --git a/doc/konversation/channel_screen_co.png b/doc/konversation/channel_screen_co.png new file mode 100644 index 0000000..6d70be8 Binary files /dev/null and b/doc/konversation/channel_screen_co.png differ diff --git a/doc/konversation/channel_screen_tour_co.png b/doc/konversation/channel_screen_tour_co.png new file mode 100644 index 0000000..fba877d Binary files /dev/null and b/doc/konversation/channel_screen_tour_co.png differ diff --git a/doc/konversation/channellist_screen_co.png b/doc/konversation/channellist_screen_co.png new file mode 100644 index 0000000..b816da9 Binary files /dev/null and b/doc/konversation/channellist_screen_co.png differ diff --git a/doc/konversation/checkidentities.png b/doc/konversation/checkidentities.png new file mode 100644 index 0000000..1e00219 Binary files /dev/null and b/doc/konversation/checkidentities.png differ diff --git a/doc/konversation/colorchooser_screen.png b/doc/konversation/colorchooser_screen.png new file mode 100644 index 0000000..6fb1d15 Binary files /dev/null and b/doc/konversation/colorchooser_screen.png differ diff --git a/doc/konversation/colorize.png b/doc/konversation/colorize.png new file mode 100644 index 0000000..f03856d Binary files /dev/null and b/doc/konversation/colorize.png differ diff --git a/doc/konversation/configure.png b/doc/konversation/configure.png new file mode 100644 index 0000000..7dce556 Binary files /dev/null and b/doc/konversation/configure.png differ diff --git a/doc/konversation/dccstatus_screen_co.png b/doc/konversation/dccstatus_screen_co.png new file mode 100644 index 0000000..983b3ff Binary files /dev/null and b/doc/konversation/dccstatus_screen_co.png differ diff --git a/doc/konversation/editserver_screen_co.png b/doc/konversation/editserver_screen_co.png new file mode 100644 index 0000000..6fc3932 Binary files /dev/null and b/doc/konversation/editserver_screen_co.png differ diff --git a/doc/konversation/first_channel_co.png b/doc/konversation/first_channel_co.png new file mode 100644 index 0000000..7f897c9 Binary files /dev/null and b/doc/konversation/first_channel_co.png differ diff --git a/doc/konversation/first_serverlist_co.png b/doc/konversation/first_serverlist_co.png new file mode 100644 index 0000000..58c2995 Binary files /dev/null and b/doc/konversation/first_serverlist_co.png differ diff --git a/doc/konversation/highlighting_screen_co.png b/doc/konversation/highlighting_screen_co.png new file mode 100644 index 0000000..b78f6aa Binary files /dev/null and b/doc/konversation/highlighting_screen_co.png differ diff --git a/doc/konversation/identities_adv_co.png b/doc/konversation/identities_adv_co.png new file mode 100644 index 0000000..7a09f04 Binary files /dev/null and b/doc/konversation/identities_adv_co.png differ diff --git a/doc/konversation/identities_away_co.png b/doc/konversation/identities_away_co.png new file mode 100644 index 0000000..aa6af8b Binary files /dev/null and b/doc/konversation/identities_away_co.png differ diff --git a/doc/konversation/identities_gen_co.png b/doc/konversation/identities_gen_co.png new file mode 100644 index 0000000..c38511e Binary files /dev/null and b/doc/konversation/identities_gen_co.png differ diff --git a/doc/konversation/index.docbook b/doc/konversation/index.docbook new file mode 100644 index 0000000..42f3a92 --- /dev/null +++ b/doc/konversation/index.docbook @@ -0,0 +1,3483 @@ + + + + + IRC"> + CTCP"> + nickname"> + Nickname"> + LED"> + OSD"> + URL"> + MIME"> + + + + + + +]> + + + + + + + + + + + + +The &konversation; Handbook + + + + + +Gary +R. +Cramblitt + +garycramblitt@comcast.net + + + + + + + +2003-2005 +Gary R. Cramblitt + + + + +&FDLNotice; + + + +2005-05-23 +0.18 + + + + + +&konversation; is a user-friendly &irc; client for the K Desktop Environment. + + + + + + +KDE +kdeextragear-2 +Konversation +irc +internet relay chat +chat +communications + + + + + + + + + +Introduction + + + + +&konversation; is an &irc; client for &kde; 3.2 or later. It offers the following features: + + + + +SSL support. +User-friendly tabbed interface. +Customizable Quick Buttons for often-used commands +Automatic reconnect and rejoin. +DCC send and receive. +&Nickname; watch list. +Visual and auditory notifications for a wide variety of events, such as messages containing + your &nickname;, or &nickname;s on your watch list going online or offline. + +Customizable highlighting of messages by &nickname; or +regular expression pattern. +&Nickname; completion. +Capture and save all &URL;s appearing in messages. +On-screen display of messages, even when minimized. +&Nickname; ignore list. +Automatic logging and log management. +Marking of lines in logs. +Scripting. +Integration with &kaddressbook;. + + + +The &konversation; website is +&konviwebsite;. + Questions and answers for &konversation; can be discussed on the + &konversation;-Users mailing list. Please subscribe to learn about new features, bug reports and the like. To stay informed of new releases, you can join our + &konversation;-Announce mailing list. This is a low volume mailing list only used to announce new releases or patches. + + +Developers for &konversation; can often be contacted via &irc; at irc.kde.org channel #konversation. + + + + + +Using &konversation; + + + + +If you haven't used &irc; before... + +Simply put, &irc; is a chat protocol, defined by official Internet +standards, and capable of stealing many hours of your life. To use +&irc;, you must connect to a server, and then join a channel (equivalent +to a chat room) or just engage in private conversations. + +To connect to a server and channel, open &konversation;. The Server List screen appears. + + + +Server List + + + + + + + + + + + + + Server List + + + + + + + +The list of configured &irc; +Networks are listed here. An &irc; network is a collection of cooperating servers. You need +only connect to one of the servers in the network to be connected to the entire +&irc; network. Once connected, &konversation; will automatically join the +Channels shown. When &konversation; is started for the first time, the +Freenode network +and #kde channel are already entered for you. Click on a network to select it. +Click here to define a new Network, including the server +to connect to, and the Channels to automatically join once connected. See Defining new networks, servers, and auto join channels for more information. +Click here to connect to the selected &irc; network and channel. + + + + +When you click the Connect button the first time you open +&konversation;, you may see the following message, telling you that your +default identity is not set up correctly. + + + + Check Identities + + + + + + Check Identities + + + + + +The first time you open &konversation; it obtains information +about the current user from the operating system and fills in defaults +for the Identity. If the operating system user information is not +complete, for example, no Full Name is defined, you may see the message +above. To correct this problem, click OK and +see Setting your identity for more +information. + + + +The Main screen will be displayed showing the messages sent by the server to the client. +(If &konversation; will not connect to the server, see Questions and Answers.) When the server messages have finished scrolling past, &konversation; will join the channel or channels chosen. + + + + +Channel. + + + + + + + + + + + + + Channel + + + + + + + + +This is called the Input Line. To send a message to everyone in the channel, type the message here and press &Enter;. + Your message, as well as everyone else's messages appear in the channel scroll above. + Each message is preceded by the time and user's &nickname;. + +You may join additional servers and channels. Each server, channel, channel list, and other screen gets a separate tab here. +To display a list of available channels, see Listing available channels. +To join a channel, +type: /join #channelname in +the Input Line. (The # is required.) You may also type /j as a shorthand to /join. To leave a channel, just type /part. To switch the display to a different server or channel, click the corresponding tab. + + +This is called the Nick Panel. It lists the &nickname;s of all the users who have joined the channel, including yourself. + + + + +That's the basics, for more detailed information, read on... + + + + + + +Setting your identity + +Before you start using &konversation; regularly, you should set how you will be identified on the network. + +Click + + Settings + Identities + + on the main menu. The Identities screen will appear. You can also display the Identities screen by clicking the Edit button on the + Add Network screen. + + + + +Identities (General tab) + + + + + + + + + + + + + + + + + Identities (General tab) + + + + + + + +Click here to select an Identity to edit. +Use these buttons to add, +duplicate, rename, or remove an Identity. +Enter your real name here. &irc; is not intended to keep you hidden from your friends or enemies. Keep this in mind if you are tempted to behave maliciously. A fake "real name" can be a good way to mask your gender from all the nerds out there, but the PC you use can always be traced so you will never be truly anonymous. +Use these buttons to +Add, Edit, or Delete a &nickname;. +This is your list of &nickname;s. +A &nickname; is the name that other users will know you by. +You may use any name you desire. The first character must be a letter. Other characters may be letters, numbers, or the special characters -[]\`_^{}|. + +Since &nickname;s must be unique across an entire &irc; network, your desired name may be rejected by the server because someone else is already using that &nickname;. Enter alternate &nickname;s for yourself. If your first choice is rejected by the server, &konversation; will try the alternate &nickname;s. + + + +According to RFC 2812, the maximum &nickname; length is 9, but +this is actually determined by the server. To determine the maximum for a server, connect to the server. In the +Server Messages tab, look for a [Support] message. +For example + + + +[18:51] *Eisfuchs* [21:45] [Support] Eisfuchs MODES=4 MAXCHANNELS=20 NICKLEN=16 USERLEN=10 HOSTLEN=63 TOPICLEN=450 KICKLEN=450 CHANNELLEN=30 KEYLEN=23 CHANTYPES=# PREFIX=@+ CASEMAPPING=ascii CAPAB IRCD=dancer + + + + +The NICKLEN parameter specifies the maximum &nickname; length. + + + +Use these buttons to change the +order of the &nickname;s. The top &nickname; is tried first, then the next +&nickname;, and so on. +If you have registered your &nickname; with the &irc; network, enter the service and password to authenticate your &nickname;. +When &konversation; connects, it will automatically send +/msg service IDENTIFY password to the server. +If you don't know what this is, leave these boxes blank. + + + + + +Click the Away tab. + + + + Identities (Away tab) + + + + + + + + + + + + + Identities (Away tab) + + + + + + + + +Enter a &nickname; that indicates you are away. Whenever you perform an +/away msg command in +any channel joined with this Identity, +&konversation; will automatically change your &nickname; to the Away nickname. Other users will be able to tell you are away +from your computer. +Whenever you perform an /away command +in any channel in which +you are away, &konversation; will automatically change your &nickname; back +to the original. If you do not wish to automatically change your +&nickname; when going away, leave blank. +If you check this box, +whenever you perform an /away command, a horizontal line will appear in the channel, marking the point where you +went away. Other &irc; users do not see this horizontal line. + +If you check this box, +&konversation; will automatically send the Away message to all channels joined with this Identity. +%s is replaced with +msg. +Whenever you perform an +/away command, the Return message will be displayed in all channels joined with this Identity. + +Away messages are often considered annoying by other users. +Use this option carefully, with consideration for your fellow &irc; users. + + + + + + + +Click the Advanced tab. + + + + Identities (Advanced tab) + + + + + + + + + + + + + + + + Identities (Advanced tab) + + + + + + + +You can enter a command +here that will be executed before connecting to the server. If this identity +is used for more than one server, the command will be executed for +each server. +This setting affects how +characters you type are encoded for sending to the server. It also affects +how messages are displayed. When you first open &konversation;, it +automatically retrieves this setting from the operating system. If you +seem to be having trouble seeing other user's messages correctly, try +changing this setting. +When you connect, many servers +query your computer for an IDENT response. If you computer is not running +an IDENT server, this response is sent by &konversation;. No spaces +are allowed. Your first name is suggested. +Whenever you leave a channel, +this message is sent to the channel. +Whenever you are kicked from +a channel (usually by an &irc; operator), this message is sent to the +channel. +Click to apply your changes. In order for all the changes to take effect, you must disconnect from the server and re-connect. The easiest way to do that is to quit &konversation; and restart. + + + + + + + + + + +Defining new networks, servers and auto join channels + +The Server List screen appears when you open the +&konversation; program. It also appears when you choose + +File +Server List + +on the main menu. The Server List screen +lists your existing defined &irc; Networks, listed by group. +An &irc; network is a collection of cooperating servers. When you connect +to any server in a network, you have access to all the channels of the network. +Examples of &irc; networks are +Freenode and +Undernet. + + + + + Server List + + + + + + + + + + + + + + Server List + + + + + + + +Your existing defined +Networks are listed here along with +the Identity used to connect to the network, +and the Channels automatically joined when connected. +If you have specified a group for your networks, networks are listed +indented under the group. Click on a network to select it. + +Use these buttons to +Add a new network, Edit +a highlighted network, or Delete a highlighted network. + +Click this button to connect +to the highlighted Network and close the +Server List screen. You may highlight +more than one network if you wish, which will connect to all the +highlighted networks. +Clicking this button does not +discard the changes you have made. It merely means you do not wish to +connect to any networks at this time. + + + + + +When you click the Add button, +the Add Network screen appears. + + + + Add Network + + + + + + + + + + + + + + + + + + + Add Network + + + + + + + +Enter the name of the +Network here. You may create as many entries +in the Server List screen with the same +Network as you like. +Optional. If you enter something +here, all the Networks with the same +Group will be listed together in the +Server List screen. +Choose an existing +Identity or click the Edit +button to add a new Identity or edit an existing one. The +Identity will identify you and determine +your &nickname; when you connect to the network. +Optional. This command will be sent to the server after connecting. Example: /msg NickServ IDENTIFY +konvirocks. This example is for the freenode network, which requires users to register their &nickname; +with a password and login when connecting. konvirocks +is the password for the &nickname; given in Identity. +You may enter more than one command by separating them with semicolons. +Check here if you want +&konversation; to automatically connect to this network whenever +you open &konversation;. +This is a list of &irc; +Servers in the network. When connecting to the network, +&konversation; will +attempt to connect to the top server first. If this fails, +it will attempt the second server. If this fails, it will attempt +the third, and so on. At least one server must be specified. +Click a server to highlight it. +Use these buttons to +Add a server, Edit a +highlighted server, or Delete a highlighted +server. You can also adjust the order of the server list and therefore +the order of connection attempts. +Optional. This is a list of the +channels that will be automatically joined once &konversation; +has connected to a server. You may leave this blank if you +wish to not automatically join any channels. +Use these buttons to +Add a channel, Edit a +highlighted channel, or Delete a highlighted +channel. You may also change the order the channels are joined. + + + + +Avoid mixing servers on different &irc; networks under the same +Network. Avoid entering the same server under +two different Networks. Otherwise, &konversation; +integration with your address book and +monitoring of online &nickname;s will not function +correctly. + + + + +When you click the Add button in the Servers frame, the Add Server screen appears. + + + + Add Server + + + + + + + + + + + + + + Add Server + + + + + + + +The name or IP number of the server. irchelp.org maintains a +list of servers. +Enter the port number required to connect to the server. For most servers, this should be 6667. +If the server requires a password +in order to connect, enter it here, otherwise leave blank. +Check if you want to use +Secure Socket Layer (SSL) protocol to communicate with the server. +This protects the privacy of your communications between your computer +and the &irc; server. The server must +support SSL protocol for this to work. In most cases, if the server +does not support SSL, the connection will fail. + + + + + +When you click the Add button in the +Auto Join Channels frame, the Add Channel +screen appears. + + + + Add Channel + + + + + + Add Channel + + + + + +Enter a channel name. Do not forget leading #. If the channel requires +a password in order to join, enter it, otherwise leave blank. + + + + + + + +Listing available channels + +To display a list of available channels, choose + + Windows + Channel List + on the main menu. + After a warning screen, a new tab is created called the Channel List. + + + + +The Channel List tab. + + + + + + + + + + + + + + + + The Channel List tab. + + + + + + + + +Enter a filter string here. + +You can limit the channel list to those channels with a minimum or maximum number of users here. Choosing 0 disables the respective criteria. + +Click here to retrieve the list of channels from the server and apply the filter. + +The filtered list of channels is displayed here. Notice that if you don't use regular expressions, &konversation; lists any channel whose name contains the filter string you entered. The channel name does not have to start with the string you entered. + +Select a channel you want to join by clicking on it. Right click on the channel to get a list of all web addresses mentioned in the channel's topic. + +Click here to join the channel. A new tab is created for the channel. + + + + +You should avoid clicking the Refresh List button. Most servers have thousands +of channels, and performing this puts a high load on the server. Besides, it can require several minutes to complete, +depending upon your network bandwidth. If your client is too slow, the server may even disconnect you. + + +Sometimes there are "secret" channels on servers. Such channels are not listed in the Channel List. +You can still join these channels if you know their name. In any Input Line, type: /join +#channelname. (The # is required.) A new tab is created for the channel. If you join a channel and the Nick Panel lists only your &nickname;, it means that the channel did not exist before. The server created the channel and you are the operator. In this case, you probably want to close the channel by typing: /part. + + + + + + + +A tour of the main screen + +Let's learn more about the Main screen. +The screen is shown below with a channel tab selected. + + + +The Main screen. + + + + + + + + + + + + + + + + + + + The Main screen + + + + + + + + +This is called the Input Line. +It appears only when the current tab is a channel. +To send a message to everyone in the channel, type the message here and press &Enter;. + Your message, as well as everyone else's messages appear in the channel scroll above. + Each message is preceded by the time and user's &nickname;. + + You can also paste text from the clipboard. If the pasted text has more than one line (newlines), + a dialog box appears. Edit the text as desired and click OK. + + + If the pasted text is longer than 256 characters, or it contains more than one line, a warning message + appears advising you that large postings can cause connection resets and flooding. You can still proceed with + the input, but doing so is a bad idea, as flooding will annoy other users in the channel, or you may + be disconnected from the server. It is better to send the message in shorter chunks. + + + + + A convention used in many channels is to precede messages directed at one user with their &nickname;. &konversation; + provides a convenient &nickname; completion feature. Start typing the user's &nickname;, then press Tab. &konversation; will complete the rest of the user's &nickname; followed by a colon. To customize the completion feature, choose + + Settings + Configure Konversation + from the main menu, expand Behavior, +click on General, and click the +Completion mode box. + + + + You can also enter an &irc; command here by first typing / + followed by a valid &irc; command. See Frequently-used &irc; commands. On some servers, you can type /help for a list of available commands, or type /help command for help + on a specific command. + + + + +You may join additional servers and channels. Each server and each channel gets a separate tab here. +To display a list of available channels, see Listing available channels. +To join a channel, type: /join +#channelname in the Input Line. (The # is required.) To leave a channel, just type /part. +Tabs also appear here if you open a Channel List, participate in a private conversation (query), open the &URL; Catcher, or open one or more Konsoles. To switch the display to a different screen, click the corresponding tab, +or use the mouse wheel to cycle through the tabs. + + + To set other options for tabs, choose + + Settings + Configure Konversation + from the main menu, expand Behavior, +click on General. + + + + +These &led;s will blink when there is something you haven't seen in that tab. +The &led; will blink slower when the only unseen messages are join, part, quit, or &nickname; changes. They blink faster if there are unseen regular messages. + The colors are as follows: + + + +Channel + + + + +Server Messages, Channel List, or +&URL; catcher + + + + +Konsole or DCC Status. + + + + +Private Message (Query). + + + + + +Click here to close the current tab. Closing a Channel tab will leave the channel. Closing a Server Messages tab will leave all channels you've joined, close all open queries at that server and disconnect from the server. + +Click this button to change your own &nickname;. It appears only when the current tab is a channel. To hide this button, choose + + Settings + Configure Konversation + from the main menu, expand Appearance, +click on Chat Window, and uncheck the +Show box to change own nickname box. + + +The channel topic is displayed here. +Hover the mouse over the topic to see long topics. You can change the topic by +clicking the button to the left of the topic. To hide channel topics, choose + + Settings + Configure Konversation + from the main menu, expand Appearance, +click on Chat Window, and uncheck the +Show channel topic box. + + +These buttons display the current state of channel modes. A button is down if that mode is on. If you have the correct privileges, you can also change channel modes by clicking on these buttons, or click the button to the +left of the topic. To hide channel mode buttons, choose + + Settings + Configure Konversation + from the main menu, expand Appearance, +click on Chat Window, and uncheck the +Show channel mode buttons box. + + + + +This is called the Nick Panel. It is displayed whenever the current tab is a channel. It lists the &nickname;s of all the users who have joined the channel, including yourself. Hover the mouse pointer over a &nickname; to display additional information +about the user. You may change how the icons are displayed next to each &nickname; by changing +the &nickname; icon theme. See Configuring &nickname; themes + for more information. +The Big Bullets theme, as shown in the screen above, uses the following icons: + + + + +normal user + + + + + +voiced user. User may talk in a moderated channel. + + + + + +channel halfop + + + + + +channel operator + + + + + +channel owner + + + + + +channel admin + + + + + + +In addition, if a user is away, a small red cross will be drawn in the corner of the icon. + + + +Click with the &RMB; on any &nickname; to display a context menu of operations you can perform with that &nickname;. +For example, you can send a file to the &nickname;. +This is also the place where you can associate a &nickname; to a contact in your address book. + + +To hide the Nick Panel, choose + + Window + Hide Nicklist + from the main menu. + + + + +These are called the Quick Buttons. +By default, they are not shown. To display them, see +Configuring Quick Buttons. +You can customize their definitions to whatever commands you wish. + + + + +Note You can control how messages are displayed in the +message scroll of channel and query tabs. For example, you can change the color +of messages, play a sound when a message containing a string +is received, or automatically reply to messages. +See +Message highlighting for more information. + + +Note: Channel names sometimes begin with &, +, +or !. The first character of a channel name determines the type of channel (RFC 2811) as follows: + + +# - Regular channels. + + +! - Regular channels. + + +& - Local. Channels that can only be joined from the server hosting the channel. + All other channels can be joined from any server in the network. + + ++ - Channels that do not support channel modes. This means + that all the modes are unset, with the exception of the 't' channel flag which is set. + + +Channel names are up to 50 characters long and may contain any characters except for space, comma, and Ctrl-G. + + + + + + + +Quick Connect + +Sometimes you want to connect to a server without going through the trouble +of creating a new server in the Server List. + + +Choose + + File + Quick Connect + + on the main menu. The Quick Connect screen will appear. + + + + +The Quick Connect screen. + + + + + + The Quick Connect screen + + + + + +Enter the server address in the Server host box, your desired +&nickname; in the Nick box, and click the Connect button. +When &konversation; has connected to the server, enter command +/join #channelname to +join a channel. + + + + + + + +Frequently-used &irc; commands + +The following is a short list of frequently-used &irc; commands. See RFC 2812 for a complete list of all commands, or +visit irchelp.org. For a list of commands +treated specially by &konversation;, see &konversation; commands + + + + + + +/help +Lists commands available on the current server. Not supported by all servers. + + + +/help cmd +Provides help for cmd. Not supported by all servers. + + + +/join #channel +Joins #channel. If the channel does not already exist, it is created and you are the channel operator. + + + +/part +Leaves the current channel and closes the channel tab. + + + +/part #channel +Leaves #channel and closes the corresponding channel tab. +Synonym for /leave + + + +/me msg +Sends msg to the channel preceded by your &nickname;. For example, if +your &nickname; were Tux, typing /me brews a cup a tea. displays the message Tux brews a cup of tea. Unless they've filtered against these types of messages, all users see it. This kind of message is typically used to convey non-verbal information, such as your current emotional state, or what you are physically doing. If you are leaving your workstation for a short time, use the /away command instead. + + + +/away msg +If anyone tries to send you a private message or invite you to a channel, they will be told that you are +away from your workstation with msg. + + + +/away +Cancels an /away msg command. + + + +/query nick +Creates a new tab with the user's nick for private conversation, commonly known on &irc; as a Query. Everything written here is only visible to you and your query partner. + + + +/msg nick msg +Sends msg to the user with &nickname; nick. +Only nick sees the message. +Use /query for longer conversations. + + + +/invite nick +Invites the user with &nickname; nick to join a channel. This command is especially useful if the channel is invite-only. + + + + + + + + + + +Private conversations (queries) + + +A private conversation is one that only you and one other person can see. Private conversations are called "queries" in &konversation;. To initiate a private conversation, +type /query nick in any input line, +where nick is the &nickname; of the person you want to talk with. You can also +click with the &RMB; on the person's &nickname; in the Nick Panel and choose + + Open Query + +A new tab will be created. Announce yourself by sending a message. + + + +Queries are just like channels, except that only you and the other person can participate in the channel. + + +To leave the query, just close the tab. Note however, that if the other person sends you another message in the query, the tab will open again. + +To leave all queries, choose + + Window + Close All Open Queries + on the main menu, or press +press F11. + + +When someone else initiates a query with you, &konversation; creates a new tab with their +&nickname;. If you don't wish to talk with the person, close the tab. + + + + + + + +Setting notifications + + +Notifications are actions that &konversation; will perform whenever an event occurs. Suppose you have &konversation; running, but minimized or hidden behind other application windows on your desktop. If someone wants to communicate with you, or your buddy joins a channel, you'd like to be alerted. Notifications will accomplish this. + + + +To configure notifications, choose + + Settings + Configure Notifications + + on the main menu. The Notification Settings screen will appear. + + +Immediately click the More Options button. + + + +The Notification Settings screen. + + + + + + + + + + + + + The Notification Settings screen + + + + + + + + +Click here to select an event. + +Check the types of notifications you'd like to happen when the event occurs. (Mark taskbar entry causes the entry in the taskbar to flash when the event occurs.) + + + + +Repeat by selecting another event and checking the notifications desired. When you've configured all the desired notifications, click the Apply button. + + + + +Once you've set up your notifications, you can enable or disable all notification actions here. For example, you can choose to play a sound whenever your &nickname; is mentioned in a message. When you are at your workstation, you can disable the sounds, but while you are away from your workstation but nearby, you can enable the sounds in order to get your attention. + + + + +You can also alert yourself when someone mentions your &nickname; +in a message using &konversation;'s +highlighting feature. + + + + + + +Monitoring who is online + + +&konversation; will keep you informed when your buddies are connected to the &irc; network +or not. + + +You can associate online &nickname;s with contact entries in your address book. +When you do this, the &nickname; and &irc; network where the &nickname; is online are +entered into the contact in the address book. The &irc; network is recorded because &nickname;s +are unique across a single &irc; network. The &nickname; in two different &irc; networks +is not necessarily the same person, but the same &nickname; on two different servers +within the same &irc; network generally is the same person. + +This is why it is important to use the same Network +for all servers in the same &irc; network, when +defining networks, servers, and auto join channels. + +You can also define &nickname;s you want watched that are not in your address book. +In this case also, each &nickname; has an associated &irc; network. See below. + +To activate the &nickname; watching feature, choose + + Windows + Watched Nicks Online + + on the main menu. The Watched Nicks Online screen will appear. + + + + + Watched Nicks Online. + + + + + + + + + + + + + + + + Watched Nicks Online + + + + + + + +The &nickname;s in your watch list and +also the &nickname;s associated with entries in your address book are listed here. +They are listed under their associated &irc; network. If no &nickname;s are listed, +either you haven't specified any &nickname;s to watch, or you need to activate +the &nickname; watching feature (see below). Expand each online &nickname; to see a list +of channels the &nickname; has joined. The icons next to each channel are the same as +the icons that appear in the Nick Panel in the +channel screens. + +The information known about the &nickname; +is displayed here. When the Watched Nicks Online screen is first +displayed, this information is sparse. Every 8 seconds, +one WHOIS command is automatically sent to the server +to request information for &nickname;s that do not have any information. This continues until +all &nickname;s have information. + +Nicknames that are not connected to any +of the &irc; networks you are connected to are listed in the Offline +part of the listing. + +Nicknames that are associated with +a contact entry in your address book have this icon +() next to their information. + +Use these buttons to associate a &nickname; +with a contact in your address book, remove an association, or open the address book +to edit the contact information. See the +&kaddressbook; Handbook for additional instructions +on using the &kde; address book. + + + + + +To add additional &nickname;s to watch, click the Edit Watch List button. +The Watched Nicknames screen appears. + + + + +Watched Nicknames + + + + + + + + + + + + + + + Watched Nicknames + + + + + + + + +Check this box to activate the nickname watcher feature. + +If you want the +Watched Nicks Online screen to automatically display when you +open &konversation;, check this box. + +The &nickname;s of the users you want to monitor are listed here. Each &nickname; has an associated &irc; network. + +Click these buttons to add or remove &nickname;s from the list. + +The Watched Nicks Online feature works by periodically polling the server. This box sets how often that occurs. Avoid numbers less than 20 seconds because it places excessive load on the server. + +In the Watched Nicks Online +screen above, you may double click on any &nickname; and this command will be sent to the +server. %u will be replaced with the +&nickname;. The %n is required at the +end of the command. + + + + +Click the OK button when you have finished adding or removing &nickname;s. + +Note: Whenever you display the Watched Nicks Online screen, it may take a while before any &nickname;s are displayed until &konversation; has polled the server. Normally, you leave the Watched Nicks Online screen running. + + +&konversation; also displays a message in all the channels whenever a user in +your Watched Nicknames list connects or disconnects from the server. The message looks like this: + + +[17:52] [Notify] psn is online (irc.kde.org). + + + + + + +Message highlighting + +You can control how messages are displayed in channel and query screens. + +To activate the highlighting feature, choose + + Settings + Configure &konversation; + + on the main menu. The Edit Preferences screen will appear. + + + + +The Highlighting screen. + + + + + + + + + + + + + + + + + + + The Highlighting screen + + + + + + + + +Click here to select the Highlighting screen. +Click here to add a new item +to the Highlight list. +When an item in the list is selected, you may edit it in the panel below. +Enter a string pattern here. +Any message received that matches this pattern, anywhere in the message, will activate +the highlighting for the message. If you have the &kde; Regular Expression Editor +utility installed on your system, the button to the right of the pattern will +be enabled. Click to display the editor, which will assist you +in preparing more complex patterns. (The &kde; Regular Expression Editor +is part of the kdeutils package.) + +If the pattern is found +in a message, the entire message will be displayed +in the color you select here. +If you wish, &konversation; will +play a sound when the pattern is matched. Click the button to choose +an audio file to be played. Click the test button to hear the sound. +If you'd like for &konversation; to +automatically send a reply message when the pattern is matched, enter the +message here. Use this feature with caution, as you may annoy &irc; users +with too much chatter if not careful. You can also enter +&irc; or &konversation; commands here. +If you have configured sounds +for any of your highlights, you can disable all of them by unchecking +this box. +If you check this box, +whenever someone mentions your &nickname; in a message, the message +will be displayed in the color you choose at the right. +Normally, highlighting +does not apply to messages you type. If you wish to highlight the +messages you type, check this box and choose a color at the right. + + + + + + + + + +Configuring On Screen Display (&osd;) + +On Screen Display (&osd;) is a unique feature of &konversation;. With &osd; turned on, + channel messages will appear on your desktop screen, even if &konversation; is minimized. Here's an example of &osd; in + action. The message in the upper lefthand part of the screen is from &konversation;, which is running +minimized in the system tray. + + + +Example of On Screen Display + + + + + + Example of On Screen Display + + + + + +To activate &osd;, choose + + Settings + Configure &konversation; + + on the main menu. The Edit Preferences screen will appear. + + + + +The On Screen Display screen. + + + + + + + + + + + + + + + The On Screen Display screen + + + + + + + + +Click here to expand the Notification item. + +Click here to select the On Screen Display screen. + +Check this box to activate &osd;. + +Click this button to choose a font for &osd;. (Note: Not all fonts work. Luxi Sans 22 and Impact 22 are known to work.) + +Check the boxes here to select the types of messages you'd like to appear on screen, then click the Apply button. + + + + + + + + + +Sending colorful messages + + +You can add color to the messages you send in any channel. In the Input Line of any channel, start typing your message. Click the + + + + + + Insert &irc; Color Button + + +Insert &irc; Color button or choose + + Insert + &irc; Color + + on the main menu. The &irc; Color Chooser screen will appear. + + + + +The &irc; Color Chooser screen. + + + + + + The &irc; Color Chooser screen + + + + + + +Choose a color and click OK. Continue typing your message in the Input Line. +To change the color again, click the Insert &irc; Color button. Choose a different color +and click OK. + + + + + + + +Configuring &nickname; themes + +You can change the icons displayed next to &nickname;s in the +Nick Panel of channel tabs. +To change the &nickname; theme, choose + + Settings + Configure Konversation + + on the main menu. The Edit Preferences screen will appear. + Click Appearance to expand it, then click Themes + to display the Themes screen. + + + + +The Themes screen. + + + + + + + + + + + + + + The Themes screen + + + + + + + + +Click to select the nick Themes screen. +Select a theme. +Sample icons are displayed here in the chosen theme. +If you have downloaded a nick theme +from elsewhere, click to install it. + + + + + + + + + +Configuring Quick Buttons + +You can enable a feature to display Quick Buttons on the Main screen, eight Quick Buttons appear. To display the Quick Buttons, choose + + Settings + Configure Konversation + +on the main menu. The Edit Preferences screen will appear. +Click Appearance to expand it, then click Chat Window. +Check the Show quick buttons box and click OK. + + +The buttons may be customized to your liking for performing often-used &irc; +commands. +To customize the Quick Buttons, choose + + Settings + Configure Konversation + + on the main menu. The Edit Preferences screen will appear. + Click Behavior to expand it, then click Quick Buttons + to display the Quick Buttons screen. + + + + +The Quick Buttons screen + + + + + + The Quick Buttons screen + + + + + + +There are 8 Quick Buttons. Click on an entry to change it. +The Button name column is the name that +will appear on the button in the Main screen. Keep the names short. +The Button Action column is the action that will be performed when you click the +Quick Button. Tips for creating actions are given on the screen. + + + +Click OK to complete the changes. + + +Example: + + + + + + Button Name: Msg + + + + Button Action: Msg %u (there is a space after %u) + + + + + + + +To use this button in the Main screen, +click on a &nickname; in the Nick Panel, then click the button. +/MSG will appear in the Input Line +followed by the chosen &nickname;. Type a message you want to send to that person and press +&Enter;. The message will be sent to the user. Only that user will see the message. + + + +Note: You cannot add or delete Quick Buttons. + + + + + + + +Sending and receiving files + + +You may send files via &irc; to other users online, or they may send you files. + + + +WARNING: Never open a file someone sends you unless they are a trusted source. It could be a virus. + + + +To send a file to someone in a channel, click with the &RMB; on the &nickname; of the person in the +Nick Panel of the Main screen. +Choose + + Send File + +A dialog appears for you to choose a file to send. Next, a new DCC Status tab appears. + + + + +DCC Status tab + + + + + + + + + + + + + DCC Status tab + + + + + + + + +The &nickname; of the recipient and file name appear here. + + +The Status column indicates the status of the file send or receive as follows: + + + + + + Offering + + + You are trying to send a file to the recipient. &konversation; is waiting for the recipient to accept the file. + + + + + + Connecting + + + &konversation; is trying to establish a connection with the other end. + + + + + + Sending + + + &konversation; is sending the file to the other end. + + + + + + Receiving + + + &konversation; is receiving the file from the other end. + + + + + + Done + + + The file has been successfully transfered. + + + + + + Stalled + + + The transfer was started but is not currently progressing. + + + + + + Aborted + + + Either you clicked the Abort button, or the other person aborted the transfer. + + + + + + Failed + + + An error occurred and the transfer was not successful.. + + + + + + Queued + + + The transfer has been accepted and will begin when the software on the receiving end acknowledges. + + + + + + Lookup + + + &konversation; is trying to get the IP number of the sender. + + + + + + Resuming + + + When a transfer begins but the file already exists on the user's system, the user will be prompted File already exists. Resume transfer? This status indicates the user resumed the transfer. + + + + + + + + + +When someone wants to send you a file, the DCC Status tab will be created (if not already created). Click the DCC Status tab to display it. Click the file to select it, then click this button to accept the file and the transfer will begin. Note: You may configure &konversation; to automatically accept sends from other +people by choosing + + Settings + Configure Konversation + DCC Settings + on the main menu. + + + + + + + +If you have trouble sending or receiving files, your firewall or router may be blocking DCC ports. +See Questions and Answers. + + + + + + + +Integrating with &kaddressbook; + +You can associate any &nickname; with a contact in &kaddressbook;. +Once you've done this, &konversation; will display the contact real name +in parenthesis after the &nickname; in the Nick Panel. + + + +To associate a &nickname; with a contact in &kaddressbook;, +click with the &RMB; on the &nickname; of the person in the +Nick Panel of the Main screen. Choose + + Whois + +to display information to help you determine the user's real name. +Next, click with the &RMB; on the &nickname; of the person again and choose + + Addressbook associations +. + A submenu appears. If the &nickname; is not already associated with a contact, +choose + + Create new contact +. + The Edit Contact screen appears. + + + + +The Edit Contact screen. + + + + + + + + + + + + + The Edit Contact screen. + + + + + + + + +The &nickname; is automatically filled in here. +If you know the person's real name, replace the &nickname; with the real name. + + + +Notice that the &nickname; does not appear here. Instead, .. + + + +Click here. The IM Addresses window appears. + + + + + + + The IM Addresses Window. + + + + + + The IM Addresses Window. + + + + + +Notice that &konversation; fills in the &nickname; for you with protocol +IRC. + + +See the +&kaddressbook; Handbook for additional instructions +on using the &kde; address book. + +Fill in any additional information about the &nickname; you know and click +OK. The real name of the person will appear inside +parenthesis next to the &nickname; in the Nick Panel +of &konversation;. The real name also appears when the mouse hovers over +the &nickname;. + +Once a &nickname; has been associated with a contact in &kaddressbook;, +you can click with the &RMB; on the &nickname; of the person in the +Nick Panel and edit the associated contact, associate +the &nickname; with a different contact, or delete the association. + + +If you have associated a &nickname; with a contact, and the user changes their &nickname; while you are running &konversation;, +it will automatically associate the new &nickname; with the contact, keeping the +original association as well. + +If you associate an &irc; &nickname; with a contact in +&kopete;, +the association will also appear in &konversation;, and vice versa. + +Note: It is possible to highlight more than one &nickname; in the +Nick Panel, click with the mouse &RMB;, and perform +multiple associations. + + + + + + + +Capturing &URL;s from messages + +In any channel, users sometimes post the &URL;s of interesting +websites or other resources on the web. You can double-click any such &URL; and &konversation; will launch +the application associated with the &URL;. +The application launched depends upon the &MIME; type of the &URL;. +For example, a &URL; beginning with +http: will activate your default &kde; web browser and display the web page. +(You can also specify the web browser to use.) +If the &URL; scrolls off the screen, you might have trouble finding it +again. &konversation; can keep a convenient list of all &URL;s for you. To activate this feature, choose + + Windows + &url; Catcher + on the main menu. +A new tab called &url; Catcher is created. + + + + +The &url; Catcher tab. + + + + + + + + + + + + + + + + The &url; Catcher tab. + + + + + + + + +This is the list of &URL;s seen since you started &konversation;. The Nick column is the &nickname; of the person who posted the &URL;. If the &nickname; is blank, the &url; appeared in a Server Messages tab. (&URL;s appearing in join and leave messages +are not listed.) Click on a &URL; to select it. + +Click here to activate the application associated with the selected &URL;. +The application launched depends upon the &MIME; type of the &URL;. For example, a &URL; beginning with +http: will activate your default web browser and display the web page. For web pages, you can +also specify the web browser to use. + +Click here to copy the selected &URL; to the &kde; clipboard.. + +Click here to delete the selected &URL; from the list. + +Click here to save the list of &URL;s to a file. + +Click here to clear the list. + + + + + + + + + +Setting your preferred web browser + +When you click on a highlighted &URL; anywhere in &konversation;, it will launch the default +&kde; application associated with the &MIME; type of the &URL;. For example, when clicking on +a &URL; beginning with http, &konqueror; is launched to display the +web page. You can specify an application different from the &kde; default. For example, you can +use Mozilla instead. + + +To choose a different web browser, choose + + Settings + Configure &konversation; + + on the main menu. The Edit Preferences screen will appear. + + + + +The Web Browser screen + + + + + + + + + + + + + The Web Browser screen + + + + + + + + +Click here to display the Web Browser screen. + +Click here to specify that you want to use a custom web browser. + +Enter the command to launch your desired web browser. +When you click on a &URL; %u will be replaced with the &URL;. + + + + +Tip: (&UNIX; systems only) The default command is mozilla '%u', which will +start a new instance of Mozilla each time you click on a &URL;. If you prefer that Mozilla display the web page +in a new tab of an already-running instance, create a file containing the following: + + + + +#!/bin/sh +mozilla -remote "openURL($@, new-tab)" || exec mozilla "$@"; + + + +Name the file moz, place it in the PATH, and +make it executable (chmod a+x moz). Then enter +moz '%u' for the web browser command in the screen above. + + +Note: The Web Browser setting does not apply to +mailto: &URL;s. mailto: &URL;s always launch the default +&kde; mailer. + + +Click Apply to save your changes. You must reconnect to each server and +channel for the changes to take effect. The easiest way to do this is to quit and restart &konversation;. + + + + + + + +Marking Channel and Query Logs + +You can insert a marker into channel +and query screens +to help you quickly locate information. To do this, choose + + Insert + Remember Line + +on the main menu, or press &Ctrl;R. + A line will appear at the bottom of the text on the screen. + The line will scroll with the rest of the text in the screen. + + +To make the Remember Line +be inserted in all channels and queries at once, choose + + Settings + Configure Konversation + from the main menu, expand Behavior, +click on Chat Window, and check the +Show remember line in all channels/queries box. + + +To make &konversation; automatically insert a +Remember Line whenever you do an +/away msg +command, see Setting your identity. + + + + + + + +Logging + +If logging is enabled, &konversation; keeps a log of each Server, +Channel, and +Private conversation (query) session. +Each session is stored in a log file on disk. +When you open the same session again, &konversation; appends to the log. +The log grows to a limit you can set (see below). When the limit is reached, the oldest +messages are discarded. + + +Whenever you open a session again, approximately the last 1024 characters +of the previous session are read from the tail of the log and shown on the screen. + + +As your session continues, messages scroll off the top of the display. +You can scroll backwards to view these messages. Eventually, in order to conserve +memory, the oldest messages are discarded from the scroll. This is called +the Scrollback limit. Messages that disappear from the display +because of the Scrollback limit are still available in the log +file, if logging is enabled. + +To view the logfile for a session, click the tab for the session to make it the +current session and choose + + Window + Open Logfile + from the main menu. A new tab appears displaying +the log file. + + + + +Logfile + + + + + + + + + + + + + + + Logfile + + + + + + + +The messages in the log file are displayed here. +The oldest messages are at the top and the most recent are at the bottom. +Click this button to save the log file to another file. +Click to refresh the log file display. +While you are viewing a log file, newer messages in the corresponding +session are not automatically added to the log file +display. Use this button to view the most recent messages. +Click to erase the log file display +and the log file on disk. +Use this box to set the maximum size +of the log file. This setting does not take effect until you restart +&konversation;. Each log file may have a separate setting. + + + +The Scrollback limit can be changed by choosing + + Settings + Configure &konversation; + on the main menu, then expand Behavior and +click on Chat Window. The Scrollback limit +box appears on this screen. If you set it to Unlimited, +messages are not discarded from the scroll. + + +You can enable or disable logging and set other logging options, by choosing + + Settings + Configure &konversation; + on the main menu, then expand Behavior and +click on Logging. + + + + + + + +&konversation; commands + +The following commands are interpreted by &konversation; and may differ from standard +&irc; commands. Items inside square brackets are optional. Items separated by bar (|) are +alternate forms of the command. Commands not listed here are sent to the server as entered. + + + + + + +/me msg +Sends msg to the channel preceded by your &nickname;. For example, if +your &nickname; were Tux, typing /me brews a cup a tea. displays the message Tux brews a cup of tea. Unless they've filtered against these types of messages, all users see it. This kind of message is typically used to convey non-verbal information, such as your current emotional state, or what you are physically doing. If you are leaving your workstation for a short time, use the /away command instead. + + + +/ame msg +Like the /me command above except that +the message is sent to all the channels and queries you have open on all the servers you have connected in &konversation;. + + + +/join channel [pwd] +Joins channel. If the server permits it, +and if the channel does not already exist, it is created and you are the channel operator. If the channel requires a password in order to join, specify as pwd. Most channel names begin with # + + + +/j channel [pwd] +Same as /join above. + + + +/part [channel] [reason] +Leaves channel with reason and closes the corresponding channel tab. +Within a &konversation; channel or query tab, you can just enter /part which closes that channel or query with your default reason +as given in the Settings. + + +/leave [channel] [reason] +Same as /part above. + + +/quit +When entered in any channel, query, or DCC tab, disconnects from the corresponding server +and closes all channel, query, or DCC tabs open on that server. + + +/notice nick|channel msg +Sends msg to the user with &nickname; nick or to everyone in channel. The following is an example +of what appears to you in the channel tab + +[17:14] [Notice] Sending notice "I think I understand" to #konversation + +And this is what the recipients see + +[17:15] [Notice] -Eisfuchs- I think I understand + + + + +/query nick +Creates a new tab with the user's nick for private conversation, commonly known on &irc; as a Query. Everything written here is only visible to you and your query partner. You may enter more than one &nickname; separated by spaces and a query tab will be opened for each &nickname;. Each such query tab will be private between you and the query partner. + + + +/msg nick|channel + message +Sends a private message to the user with &nickname; nick or to all users in channel. Unlike /query, +does not open a new tab. If message begins with /me , the message is formatted in the same manner as a +/me command. + +Examples + +/msg Eisfuchs I need some help with the msg command + +/msg #konversation New version of Konvi is online! + +/msg Eisfuchs /me is compiling the Handbook right now. + + + + + +/smsg nick|channel +message +Same as /msg except the message is not +displayed on your screen. This is useful for preventing passwords and other sensitive information from remaining exposed on your screen or being logged. + + + +/amsg nick|channel + message +Like the /msg command above except that +the message is sent to all the channels and queries you have open on all the servers you have connected in &konversation;. + + + +/op nick +When entered into a channel tab, attempts to give + nick operator privilege for the +channel. May not work if you lack sufficient privilege in the channel (you must be a +channel operator yourself). You may enter more than one &nickname; separated by spaces. + + + +/deop nick +When entered into a channel tab, takes away channel operator privilege from +nick. You may enter more than one &nickname; separated by spaces. + + + +/oper [nick] +Grants the user with &nickname; nick &irc;-Op (Administrator) privilege. This only works if the &nickname; is listed in the server's O: line. &irc;-Ops +have the privilege to /kill &nickname;s, +/connect servers to the &irc; network, and more. +If nick is not entered, +attempts to grant yourself &irc;-Op privilege. You will be prompted for your &irc;-Op user name and password in either case. + + + +/voice nick +In certain channels (with +m flag), users cannot send messages unless they have voice privilege. +This command attempts to give nick voice privilege. +You must have channel operator privilege to execute this command. This command is mostly used +when you are an operator for a moderated channel. + + + +/unvoice nick +Takes away voice privilege from nick in the channel. + + + +/topic [channel] [message] +Attempts to set the topic of channel to +message. When entered in a channel tab, channel may be omitted and defaults to the channel active in the tab. If message is omitted, displays the current +topic of the channel. Changing a channel topic may fail if you lack sufficient privilege. + + + +/away reason +If anyone tries to send you a private message or invite you to a channel, they will be told that you are +away from your workstation for reason. To change your state back to normal, enter /away without a reason. + + + +/aaway reason +Like the /away command above except that +the command is sent to all the servers you have connected in &konversation;. + + + +/invite nick [channel] +Invites the user with &nickname; nick to join channel. This command is especially useful if the channel is invite-only. When entered in a channel tab, channel may be omitted. + + + +/exec script [parameters] +Executes the &konversation;-compatible shell script named +script, passing it +parameters. See +Scripting for more information on using and writing +scripts. +Examples: + +/exec kdeversion + +Sends your system's &kde; and &Qt; version numbers to the channel. + +/exec cmd uname -a + +Sends your &Linux; version string to the channel. + + + + + +/notify [nick] +Adds or removes nick from +your Watched Nicks Online list. If the &nickname; is already +in the list, it is removed. If it is not in the list, it is added. If nick is omitted, displays the current list +of watched &nickname;s. + + + + +/prefs [list|group] [list|option] [value] +Displays or sets &konversation; settings without using the Settings screen. +If a parameter contains spaces, surround it with quotes. + +Examples: + +/prefs list + +lists the available option groups. + +/prefs "General Options" list + +lists the options available in group General Options along with their current values + +/prefs "General Options" ShowTrayIcon + +Displays the current value of the setting for displaying the &konversation; icon in the system tray. + +/prefs "General Options" ShowTrayIcon false + +Turns off the &konversation; icon in the system tray. + + + + +/kick nick reason +When entered in a channel tab, attempts to kick the user with &nickname; +nick from the channel with +reason. If reason is not entered, defaults to the +reason in the Settings. This command may only be used in +a channel tab. + + + +/ban [-host|-domain| +-userhost|-userdomain] [channel] user|mask +Attempts to ban the user or mask from channel. When entered in a channel tab, +channel may be omitted. For more information +on hosts, domains, and masks, see the documents at irchelp.org. +Too get the current ban list for a channel, enter +/mode channel b. + + + + +/unban [channel] pattern +Reverts a previous banning from a channel. When entered in a channel tab, +channel may be omitted. + + + + +/ignore [-all] nick +Adds nick to your Ignore list. +You may specify more than one &nickname; separated by spaces. Channel messages from users on your Ignore +list are not displayed. In addition, if you enter -all, all message types +(queries, notices, &CTCP;, DCC, and Exceptions) from the user are ignored as well as channel messages. + + + + +/quote cmd +Sends cmd to the server. + + + + +/say msg +When entered in a channel tab, sends msg to the channel. This is the same as entering msg +in the channel Input Line. Useful for sending &irc; commands when you don't want +to execute the command. Two command characters (//) in a row does the same thing as +/say. Also used by scripts to send messages. + + + + +/raw [open|close] +Places the server log in raw mode (open) or stops raw mode (close). If neither open or close is entered, defaults to open. In raw mode, the log displays every message received from the server in native &irc; format. + + + + +/konsole +Opens a new tab running a &kde; &konsole;. + + + + +/server [url] [pwd] +Connects to the server at address url. If +url is omitted, connects to the server associated +with the tab where you enter the command. This is useful for re-connecting to a server when +disconnected. If the server +requires a password in order to connect to it, enter it for pwd. If +the server requires a port number other than the default (6667), enter the url like this: irc.kde.org:6665. + + + + +/dcc SEND nick +[filename] +Sends filename to the user with +&nickname; nick. +If filename is omitted, a dialog appears for you to select +a file. + + + + +/dcc +Opens a DCC Status tab. + + + + +/ctcp nick|channel ping +Sends a PING message to nick +or channel. This is useful for +determining if someone you are talking with has a high network lag, or (when sent to +a channel) if your system has a high lag. + + + + +/ctcp nick|channel msg +Sends a message to nick +or all users in channel. This +is similar to the /msg command above, except that +the message is sent using the &CTCP; protocol. The response on the other end +depends on the &irc; client program the user is running. For example, when +conversing with another &konversation; user, +/ctcp Eisfuchs TIME will return +the system time on Eisfuch's computer. /ctcp Eisfuchs VERSION will return the &konversation; version number +from Eisfuch's computer. + + + + + + + + + + + +Scripting + +&konversation; comes with some handy scripts you can run from the program. To +run a script, in a channel, query, DCC, or server tab, type a command of the form + +/exec script + [parameters] + +which executes the script named script +passing it (optional) parameters. + +For example, type the following command in a channel tab + +/exec kdeversion + +to send your &kde; and &Qt; version numbers to the channel. + +/exec cmd uname -a + +executes the cmd script, +passing it uname -a. This sends your +&Linux; version string to the channel. + +To get a list of all available scripts, type the following command in a +&konsole; screen. + +ls $KDEDIR/share/apps/konversation/scripts + +You can write your own scripts. Scripts are shell scripts and can be written in +any shell language, such as bash, perl, or python. When &konversation; runs a script, the +first three parameters sent to the script are: + + + +The port number for the &irc; server of the tab where the +/exec command was entered. + + +The address of the server. + +The channel name. + + + +Here is a sample shell script (cmd). + + + +#!/bin/sh + +# Executes a command and prints the output into Konversation. + +PORT=$1; +SERVER=$2; +TARGET=$3; +shift;shift;shift; + +$@ | while read line; do dcop $PORT Konversation say $SERVER "$TARGET" "$@: $line"; done + + + +Notice that the script uses &DCOP; to communicate with &konversation;. The say command causes +the output to be sent to the channel as a normal message. To display something +in the tab without sending it to other users, use info +instead. Look at the existing script files for more examples of writing scripts. + +To be able to run a script you have written, you must install it by copying +it to $KDEDIR/share/apps/konversation/scripts or to $HOME/.kde/share/apps/konversation/scripts. You must also give the file execute +privilege, for example chmod a+x myscript. + + + + + + + + +Command Reference + + + + + + +The main &konversation; window + + +The File Menu + + + + + + F2 + + File + Server List + + Displays the list of servers and channels. + + + + + + F7 + + File + Quick Connect + + Displays the Quick Connect screen for connecting to a server. + + + + + File + Reconnect + + Reconnects to all servers that were disconnected + by a network error or other problem. + + + + + + &Ctrl;J + + File + Join Channel + + Displays a dialog for you to enter the name + of a channel to join. Does the same thing as entering + /join #channelname in a channel + or server tab. + + + + + &Alt; &Ctrl;Q + + File + Set Away Globally + + Changes your &nickname; status to away in all channels. + + + + + + &Ctrl;Q + + File + Quit + + Quits &konversation; + + + + + + +The <guimenu>Edit</guimenu> Menu + + + + + + &Ctrl;F + + Edit + Find + + + Searches for text strings in the current screen. + + + + + + F3 + + Edit + Find Next + + + Searches again for text strings in the current screen + using the previous search string. + + + + + + &Ctrl;L + + Edit + Clear Window + + + Clears the current screen. + + + + + + &Ctrl; &Shift;L + + Edit + Clear All Windows + + + Clears all screens. + + + + + + + +The <guimenu>Insert</guimenu> Menu + + + + + + &Ctrl;K + + Insert + &irc; Color + + + See Sending colorful messages. + + + + + + &Ctrl;R + + Insert + Remember Line + + + See Marking Channel and Query Logs. + + + + + + &Alt; &Shift;C + + Insert + Special Character + + + Used to enter special characters, such as foreign + characters. + + + + + + + +The <guimenu>Bookmarks</guimenu> Menu + + + + + + &Ctrl;B + + Bookmarks + Add Bookmark + + + Bookmarks current network & channel + + + + + Bookmarks + Edit Bookmarks + + + Opens bookmark editor + + + + + Bookmarks + New Bookmark Folder + + + Creates a new bookmark folder + + + + + + + +The <guimenu>Settings</guimenu> Menu + + + + + + &Ctrl;M + + Settings + Hide Menubar + + + Hides the main menu. Hit + &Ctrl;M + to display it again. + + + + + Settings + Hide Toolbar + + + Hides the toolbar. + + + + + Settings + Hide Statusbar + + + Hides the status bar at the bottom of the main screen. + + + + + Settings + Identities + + Displays the Identities screen + for setting your identification information. + + + + + Settings + Configure Shortcuts + + + Allows you to change keyboard shortcuts for &konversation;. + + + + + Settings + Configure Toolbars + + + Allows you to add or remove buttons from the &konversation; toolbar. + + + + + Settings + Configure Notifications + + + Displays the Notifications Settings screen. + + + + + Settings + Configure &konversation; + + + Displays the Edit Preferences screen. + + + + + + + +The <guimenu>Window</guimenu> Menu + + + + + + &Ctrl;. + + Window + Previous Tab + + + Displays the screen corresponding to the previous tab. + + + + + + &Ctrl;, + + Window + Next Tab + + + Displays the screen corresponding to the next tab. + + + + + + &Ctrl;W + + Window + Close Tab + + + Closes the current screen. If closing a channel, leaves the channel. If closing a + Server Messages tab, closes all open channels on that server + and disconnects from the server. + + + + + + + F11 + + Window + Close All Open Queries + + + Closes all Private conversations (queries). + + + + + + + &Ctrl;H + + Window + Hide Nicklist + + + Hides (or displays) the panel of &nickname;s in channel tabs. + + + + + + + F4 + + Window + Watched Nicks Online + + + Displays the Watched Nicks Online screen. See Monitoring who is online. + + + + + + F5 + + Window + Channel List + + + Displays a list of channels available on the server. + + + + + + F6 + + Window + &url; Catcher + + + Displays the &url; Catcher screen. + + + + + Window + New Konsole + + + Displays a terminal screen. You may open as many Konsole tabs as you like. + + + + + + &Ctrl;O + + Window + Open Logfile + + + Displays a screen with the log of messages from the current tab. Only works for + Channel, Server Messages, + and Query tabs. Logging must be enabled in + + Settings + Configure Konversation + Behavior + Logging + on the main menu. + + + + + + + + +The <guimenu>Help</guimenu> Menu + + + + + + +&help.menu.documentation; + + + + + + + + + +Questions and Answers + + + +&reporting.bugs; +&updating.documentation; + + + + + +When I start &konversation;, I'd like to connect to a server without joining any channels. How do I do that? + + +In the Edit Server screen, leave the Channels frame empty. + + + + + +&konversation; won't connect to any servers. What is wrong.? + + +There are several things that could be wrong. + + + +Make sure that you have entered the correct Server name and the correct Port in the Add Server screen. + + + + +Check the output in the Server Messages screen for any error messages. Did the server reject the connection because of a bad password? Did the server reject the connection because it requires IDENTD and +your computer did not respond to the IDENT request? Did you check +the SSL protocol box but the server does not support SSL? + + + + +If you are behind a firewall, make sure the correct ports are enabled. &konversation; needs the following ports enabled: + + + + +Outgoing TCP 6667 (or the port of the server you connect to) +Incoming TCP 113 (if the server requires IDENTD) + + + + +For more information on &irc; connection problems, see irchelp.org. + + + + + + + + + + +When I go to + +Window +Channel List +, I cannot select it. Why is that? + + + +The + +Windows +Channel List + menu entry will be greyed-out if a non-channel tab, ⪚ Watched Nicks Online, is currently being viewed. +To make it selectable again go back to a channel tab or the server tab. + + + + + + + + + + + +Credits and License + + +&konversation; + + +Program copyright 2002-2005 by the &konversation; team. + +&konviwebsite; + + +Contributors: + +Dario Abatianni eisfuchs@tigress.com +Peter Simonsson psn@linux.se +Christian Muehlhaeuser chris@chris.de +John Tapsel john@geola.geo.uk +Ismail Donmez ismail.donmez@boun.edu.tr +Shintaro Matsuoka shin@shoegazed.org +Gary Cramblitt garycramblitt@comcast.net +Matthias Gierlings gismore@users.sourceforge.net +&Alex.Zepeda; garbanzo@hooked.net +Stanislav Karchebny berkus@users.sourceforge.net +Mickael Marchand marchand@kde.org + + + + +Thanks to: + +Michael Goettsche michael.goettsche@kdemail.net +Benjamin Meyer ben+konversation@kdemail.net +Jacub Stachowski qbast@go2.pl +Sabastian Sariego segfault@kde.cl +Olivier Bedard www.konversation.org hosting +Frauke Oster frauke@frsv.de +Lucijan Busch lucijan@kde.org +Sascha Cunz mail@sacu.de +Steve Wollkind steve@njord.org +Thomas Nagy thomas.nagy@eleve.emn.fr +Tobias Olry tobias.olry@web.de +Ruud Nabben r.nabben@gawab.com + + + + +Documentation Copyright © 2003-2005 Gary R. Cramblitt garycramblitt@comcast.net + + + + +&underFDL; + + + +&underGPL; + + + + +Installation + + + + +How to obtain &konversation; + + + +&install.intro.documentation; + + +The latest versions of &konversation;, including source code and build instructions +can also be obtained from the +&konviwebsite; website. + + + + + + + +Requirements + + + + +In order to successfully use &konversation;, you need &kde; 3.2 or later and a network connection. +On earlier &kde; versions some features may be missing. +If you will be running &konversation; from behind a firewall, see Questions and Answers. If you wish to use SSL protocol, you may need OpenSSL. + + + + + +&documentation.index; + + + diff --git a/doc/konversation/irc_admin.png b/doc/konversation/irc_admin.png new file mode 100644 index 0000000..3aeef2e Binary files /dev/null and b/doc/konversation/irc_admin.png differ diff --git a/doc/konversation/irc_away.png b/doc/konversation/irc_away.png new file mode 100644 index 0000000..ad9044d Binary files /dev/null and b/doc/konversation/irc_away.png differ diff --git a/doc/konversation/irc_halfop.png b/doc/konversation/irc_halfop.png new file mode 100644 index 0000000..d0ea2b6 Binary files /dev/null and b/doc/konversation/irc_halfop.png differ diff --git a/doc/konversation/irc_normal.png b/doc/konversation/irc_normal.png new file mode 100644 index 0000000..d3aaee6 Binary files /dev/null and b/doc/konversation/irc_normal.png differ diff --git a/doc/konversation/irc_op.png b/doc/konversation/irc_op.png new file mode 100644 index 0000000..b00f5d4 Binary files /dev/null and b/doc/konversation/irc_op.png differ diff --git a/doc/konversation/irc_owner.png b/doc/konversation/irc_owner.png new file mode 100644 index 0000000..2e2bd40 Binary files /dev/null and b/doc/konversation/irc_owner.png differ diff --git a/doc/konversation/irc_voice.png b/doc/konversation/irc_voice.png new file mode 100644 index 0000000..1fc438b Binary files /dev/null and b/doc/konversation/irc_voice.png differ diff --git a/doc/konversation/kaddressbook.png b/doc/konversation/kaddressbook.png new file mode 100644 index 0000000..475a472 Binary files /dev/null and b/doc/konversation/kaddressbook.png differ diff --git a/doc/konversation/kimproxy_create_screen2.png b/doc/konversation/kimproxy_create_screen2.png new file mode 100644 index 0000000..4f902c9 Binary files /dev/null and b/doc/konversation/kimproxy_create_screen2.png differ diff --git a/doc/konversation/kimproxy_create_screen_co.png b/doc/konversation/kimproxy_create_screen_co.png new file mode 100644 index 0000000..c3a1b39 Binary files /dev/null and b/doc/konversation/kimproxy_create_screen_co.png differ diff --git a/doc/konversation/led_blue_off.png b/doc/konversation/led_blue_off.png new file mode 100644 index 0000000..2a9beb7 Binary files /dev/null and b/doc/konversation/led_blue_off.png differ diff --git a/doc/konversation/led_blue_on.png b/doc/konversation/led_blue_on.png new file mode 100644 index 0000000..24ea507 Binary files /dev/null and b/doc/konversation/led_blue_on.png differ diff --git a/doc/konversation/led_green_off.png b/doc/konversation/led_green_off.png new file mode 100644 index 0000000..0a5e99e Binary files /dev/null and b/doc/konversation/led_green_off.png differ diff --git a/doc/konversation/led_green_on.png b/doc/konversation/led_green_on.png new file mode 100644 index 0000000..b075e3b Binary files /dev/null and b/doc/konversation/led_green_on.png differ diff --git a/doc/konversation/led_red_off.png b/doc/konversation/led_red_off.png new file mode 100644 index 0000000..36ade01 Binary files /dev/null and b/doc/konversation/led_red_off.png differ diff --git a/doc/konversation/led_red_on.png b/doc/konversation/led_red_on.png new file mode 100644 index 0000000..fc39e10 Binary files /dev/null and b/doc/konversation/led_red_on.png differ diff --git a/doc/konversation/led_yellow_off.png b/doc/konversation/led_yellow_off.png new file mode 100644 index 0000000..e51d9e4 Binary files /dev/null and b/doc/konversation/led_yellow_off.png differ diff --git a/doc/konversation/led_yellow_on.png b/doc/konversation/led_yellow_on.png new file mode 100644 index 0000000..58fc244 Binary files /dev/null and b/doc/konversation/led_yellow_on.png differ diff --git a/doc/konversation/logviewer_co.png b/doc/konversation/logviewer_co.png new file mode 100644 index 0000000..9104e6f Binary files /dev/null and b/doc/konversation/logviewer_co.png differ diff --git a/doc/konversation/nicksonline_co.png b/doc/konversation/nicksonline_co.png new file mode 100644 index 0000000..7d8267a Binary files /dev/null and b/doc/konversation/nicksonline_co.png differ diff --git a/doc/konversation/nickthemes_screen_co.png b/doc/konversation/nickthemes_screen_co.png new file mode 100644 index 0000000..f57e707 Binary files /dev/null and b/doc/konversation/nickthemes_screen_co.png differ diff --git a/doc/konversation/notification_screen_co.png b/doc/konversation/notification_screen_co.png new file mode 100644 index 0000000..3da5a21 Binary files /dev/null and b/doc/konversation/notification_screen_co.png differ diff --git a/doc/konversation/notifylist_screen_co.png b/doc/konversation/notifylist_screen_co.png new file mode 100644 index 0000000..33020bc Binary files /dev/null and b/doc/konversation/notifylist_screen_co.png differ diff --git a/doc/konversation/osd_demo.png b/doc/konversation/osd_demo.png new file mode 100644 index 0000000..03061f2 Binary files /dev/null and b/doc/konversation/osd_demo.png differ diff --git a/doc/konversation/osd_screen_co.png b/doc/konversation/osd_screen_co.png new file mode 100644 index 0000000..4a64491 Binary files /dev/null and b/doc/konversation/osd_screen_co.png differ diff --git a/doc/konversation/prefs_identity_screen_co.png b/doc/konversation/prefs_identity_screen_co.png new file mode 100644 index 0000000..155aadd Binary files /dev/null and b/doc/konversation/prefs_identity_screen_co.png differ diff --git a/doc/konversation/quickbuttons_screen.png b/doc/konversation/quickbuttons_screen.png new file mode 100644 index 0000000..c15358e Binary files /dev/null and b/doc/konversation/quickbuttons_screen.png differ diff --git a/doc/konversation/quickconnect_screen.png b/doc/konversation/quickconnect_screen.png new file mode 100644 index 0000000..1a6d5f5 Binary files /dev/null and b/doc/konversation/quickconnect_screen.png differ diff --git a/doc/konversation/serverlist_co.png b/doc/konversation/serverlist_co.png new file mode 100644 index 0000000..9d6547b Binary files /dev/null and b/doc/konversation/serverlist_co.png differ diff --git a/doc/konversation/serverlist_screen_co.png b/doc/konversation/serverlist_screen_co.png new file mode 100644 index 0000000..c0eda8f Binary files /dev/null and b/doc/konversation/serverlist_screen_co.png differ diff --git a/doc/konversation/urlcatcher_screen_co.png b/doc/konversation/urlcatcher_screen_co.png new file mode 100644 index 0000000..08ef3b6 Binary files /dev/null and b/doc/konversation/urlcatcher_screen_co.png differ diff --git a/doc/konversation/webbrowser_screen_co.png b/doc/konversation/webbrowser_screen_co.png new file mode 100644 index 0000000..836d249 Binary files /dev/null and b/doc/konversation/webbrowser_screen_co.png differ diff --git a/doc/pt/Makefile.am b/doc/pt/Makefile.am new file mode 100644 index 0000000..be3f4f8 --- /dev/null +++ b/doc/pt/Makefile.am @@ -0,0 +1,2 @@ +KDE_LANG = pt +KDE_DOCS = konversation diff --git a/doc/pt/index.docbook b/doc/pt/index.docbook new file mode 100644 index 0000000..9239eda --- /dev/null +++ b/doc/pt/index.docbook @@ -0,0 +1,5959 @@ + + + + + IRC"> + CTCP"> + nickname"> + Nickname"> + LED"> + OSD"> + URL"> + MIME"> + + + + + + +]> + + + + + + + + + + + + +O Manual do &konversation; + + + Gary R. Cramblitt garycramblitt@comcast.net +JoséPires
jncp@netcabo.pt
Tradução
+
+ + + + +2003-2005 +Gary R. Cramblitt + + + + +&FDLNotice; + + + +2005-05-23 +0.18 + + + + +O &konversation; é um cliente de &irc; amigável para o Ambiente de Trabalho K. + + + + + +KDE +kdeextragear-2 +Konversation +irc +'internet relay chat' +conversa +comunicação + + +
+ + + + + + +Introdução + + + +O &konversation; é um cliente de &irc; para o &kde; 3.2 ou posteriores. Oferece as seguintes funcionalidades: + + + +Suporte de SSL. +Uma interface em páginas amigável. +Botões Rápidos Personalizáveis para os comandos mais usados +Voltar ligar e juntar automaticamente. +Envio e recepção DCC. +Lista de &Nickname;s a vigiar. +Notificações visuais e audíveis para uma grande variedade de eventos, como as mensagens que contêm o seu &nickname;, ou os &nickname;s na sua lista de vigias que se ligam ou desligam. +Realce personalizado das mensagens por &nickname; ou por um padrão de expressão regular. +Completação de &Nickname;s. +Captura e gravação de todos os &URL;s que aparecem nas mensagens. +Visualização no ecrã das mensagens, mesmo quando está minimizado. +Lista de &Nickname;s a ignorar. +Registo automático e gestão dos registos. +Marcação das linhas nos registos. +'Scripting'. +Integração com o &kaddressbook;. + + + +A página Web do &konversation; é a &konviwebsite;. As perguntas e respostas para o &konversation; podem ser discutidas na lista de correio &konversation;-Users. Por favor subscreva-se para saber das novas funcionalidades, de relatórios de erros e outras coisas do género. Para se manter informado das novas versões, poderá juntar-se à lista de correio &konversation;-Announce. Esta é uma lista de volume baixo que só é usada anunciar versões ou actualizações novas. + +Os programadores do &konversation; poderão ser contactados com frequência através do &irc; no canal do irc.kde.org #konversation. + + + + +Usar o &konversation; + + + + +Se você nunca usou o &irc; antes... + +De forma simples, o &irc; é um protocolo de conversação, definido pelas normas oficiais da Internet e que é capaz de roubar muitas horas da sua vida. Para usar o &irc;, precisa de se ligar a um servidor e depois de se juntar a um canal (o equivalente a uma sala de conversação) ou simplesmente entrar em conversas privadas. + +Para se ligar a um servidor e um canal, abra o &konversation;. O ecrã da Lista de Servidores irá então aparecer. + + + +Lista de Servidores + + + + + + + + + + + + + Lista de Servidores + + + + + + + +A lista de Redes de &irc; configuradas encontra-se aqui. Uma rede de &irc; é uma colecção de servidores em cooperação. Só precisa de se ligar a um dos servidores na rede para se ligar a toda a rede de &irc;. Logo que esteja ligado, o &konversation; irá ligar-se automaticamente aos Canais apresentados. Quando o &konversation; é iniciado pela primeira vez, é usada a rede Freenode e o canal #kde já estão introduzidos para si. Carregue numa rede para a seleccionar. +Carregue aqui para definir uma nova Rede, incluindo o servidor ao qual se ligar, e os Canais aos quais se ligar automaticamente. Veja em Definir redes, servidores e canais de ligação automáticos novos para mais informações. +Carregue aqui para se ligar ao servidor e canal &irc; seleccionados. + + + + +Quando carregar no botão Ligar da primeira vez que abrir o &konversation;, poderá ver a seguinte mensagem que lhe diz que a sua identidade por omissão não está configurada correctamente. + + + + Verificar Identidades + + + + + + Verificar Identidades + + + + + +Na primeira vez que usar o &konversation;, ele irá obter informações acerca do utilizador actual a partir do sistema operativo e tentará preencher os valores por omissão para a identidade. Se a informação do sistema operativo não estiver completa como, por exemplo, faltar o Nome Completo, poderá ver a mensagem acima. Para corrigir este problema, carregue em OK e veja a secção Configurar a sua identidade para mais informações. + + +O ecrã Principal aparecerá a mostrar as mensagens enviadas pelo servidor ao cliente (Se o &konversation; não se ligar ao servidor, veja as Perguntas e Respostas.) Quando as mensagens do servidor tiverem acabado de passar, o &konversation; juntar-se-á ao canal escolhido. + + + +Canal. + + + + + + + + + + + + + Canal + + + + + + + + +Esta é chamada de Linha de Entrada. Para enviar uma mensagem para todos no canal, escreva aqui a mensagem e carregue em &Enter;. A sua mensagem, assim como as mensagens de todos os outros, irão aparecer na área do canal em cima. Cada mensagem é antecedida da hora e do &nickname; do utilizador. + +Você poder-se-á ligar aos servidores e canais adicionais. Cada servidor, canal, lista de canais e outros ecrãs têm uma página diferente aqui. Para mostrar uma lista ocm os canais disponíveis, veja em Listar os canais disponíveis. Para se ligar a um canal, escreva: /join #nome_do_canal na Linha de Entrada. (O # é obrigatório.) Poderá também escrever /j como atalho para o /join. Para sair de um canal, basta escrever /part. Para mudar a visualização para outro servidor ou canal, carregue na página correspondente. + +Esta área é chamada de Lista de Alcunhas. Ela lista os &nickname;s de todos os utilizadores que se juntaram ao canal, incluindo você próprio. + + + + +Isto é o básico; para saber alguma informação mais detalhada, continue a ler... + + + + + + +Configurar a sua identidade + +Antes de começar a usar o &konversation; regularmente, você precisa de definir como é que será identificado na rede. + +Carregue em Configuração Identidades no menu principal. O ecrã de Identidades irá aparecer. Poderá também apresentar o ecrã de Identidades se carregar no botão Editar no ecrã Adicionar uma Rede. + + + +Identidades (Página geral) + + + + + + + + + + + + + + + + + Identidades (Página geral) + + + + + + + +Carregue aqui para escolher uma Identidade a editar. +Use estes botões para adicionar, duplicar, mudar o nome ou remover uma Identidade. +Indique aqui o seu nome verdadeiro. O &irc; não o pretende manter escondido dos seus amigos ou inimigos. Tenha isto em mente se se sentir tentado a comportar-se de forma maldosa. Um "nome verdadeiro" falso poderá ser uma forma de esconder o seu sexo dos palermas que existem por aí, mas o PC que usa poderá sempre ser localizado, como tal você nunca estará realmente anónimo. +Use estes botões para Adicionar, Editar ou Remover um &nickname;. +Esta é a sua lista de &nickname;s. Um &nickname; é o nome pelo qual os outros utilizador o irão reconhecer. Poderá indicar aqui qualquer nome que deseje. O primeiro carácter precisa de ser uma letra, enquanto os outros caracteres poderão ser letras, números ou os caracteres especiais -[]\`_^{}|. + +Dado que os &nickname;s devem ser únicos em toda uma rede de &irc;, o seu nome desejado poderá ser rejeitado pelo servidor, dado que alguns já estão a usar o seu &nickname;. Indique algumas alcunhas alternativas para si nos campos em baixo. Se a sua primeira escolha for rejeitada pelo servidor, o &konversation; irá tentar os &nickname;s alternativos. + +De acordo com o RFC 2812, o tamanho máximo do &nickname; é 9, mas isto é de facto determinado pelo servidor. Para determinar o valor máximo para um servidor, ligue-se a ele. Na página das Mensagens do Servidor, procure por uma mensagem [Support]. Por exemplo + + +[18:51] *Portugal* [21:45] [Support] Portugal MODES=4 MAXCHANNELS=20 NICKLEN=16 USERLEN=10 HOSTLEN=63 TOPICLEN=450 KICKLEN=450 CHANNELLEN=30 KEYLEN=23 CHANTYPES=# PREFIX=@+ CASEMAPPING=ascii CAPAB IRCD=dancer + + +O parâmetro NICKLEN indica o tamanho máximo do &nickname;. + + +Use estes botões para alterar a ordem dos &nickname;s. O &nickname; do topo é experimentado em primeiro lugar, depois o próximo, e assim por diante. +Se tiver registado o seu &nickname; com a rede de &irc;, indique o serviço e a senha com os quais irá autenticar o seu &nickname;. Quando o &konversation; se ligar, irá enviar automaticamente um /msg serviço IDENTIFY senha para o servidor. Se não souber o que é isto, deixe estes campos em branco. + + + + + +Carregue na página de Ausência. + + + + Identidades (Página ausência) + + + + + + + + + + + + + Identidades (Página ausência) + + + + + + + +Introduza um &nickname; que lhe indique que está ausente. Sempre que executar um /away mensagem em qualquer canal ligado com esta Identidade, o &konversation; irá mudar automaticamente o seu &nickname; para a Alcunha de ausência. Os outros utilizadores serão capazes de ver que você está ausente do seu computador. Sempre que executar um comando /away, o seu &nickname; irá voltar ao normal. Se não quiser mudar automaticamente o seu &nickname; quando se vai embora, deixe em branco. +Se tiver assinalado esta opção, sempre que executar um comando /away, irá aparecer uma linha horizontal no canal, a marcar o ponto em que você se ausentou. Os outros utilizadores do &irc; não irão ver esta linha horizontal. +Se assinalar esta opção, o &konversation; irá enviar automaticamente a Mensagem de ausência: para todos os canais associados a esta Identidade:. O %s será substituído pela mensagem. Sempre que executar um comando /away, a Mensagem de regresso será apresentada em todos os canais associados a esta Identidade. + +As mensagens de ausência são muitas vezes consideradas incómodas pelos outros utilizadores. Use esta opção com cuidado, tendo em consideração os outros utilizadores do &irc;. + + + + + + +Carrega na página Avançado. + + + + Identidades (Página avançado) + + + + + + + + + + + + + + + + Identidades (Página avançado) + + + + + + + +Poderá indicar aqui um comando que será executado, antes da ligação ao servidor. Se esta identidade for usada por mais que um servidor, o comando será executado para cada um deles. +Esta opção afecta a forma como os caracteres que você escreve são codificados para serem enviados para o servidor. Também afecta a forma como as mensagens são apresentadas. Quando abrir pela primeira vez o &konversation;, ele irá obter automaticamente esta opção do sistema operativo. Se achar que está a ter problemas ao ver as mensagens dos outros utilizadores, tente alterar esta opção. +Quando se ligar, vários servidores irão procurar no seu computador por uma resposta de IDENT. Se o seu computador não estiver a correr um servidor de IDENT, esta resposta é enviada pelo &konversation;. Não são permitidos espaços. É sugerido o seu nome próprio. +Sempre que abandonar um canal, esta mensagem é enviada para ele. +Sempre que você for expulso de um canal (normalmente por um operador do &irc;), esta mensagem é enviada para o canal. +Carregue aqui para aplicar as suas alterações. Para que todas as alterações façam efeito, você precisa de se desligar do servidor e voltar a ligar-se. A forma mais simples de fazer isto é sair do &konversation; e voltar a arrancar. + + + + + + + + + + +Definir novas redes, servidores e canais aos quais ligar automaticamente. + +O ecrã da Lista de Servidores aparece quando você abre o programa &konversation;. Também aparece quando você escolhe a opção Ficheiro Lista de Servidores no menu principal. O ecrã da Lista de Servidores indica as suas Redes de &irc; definidas, separadas por grupos. Uma rede de &irc; é uma colecção de servidores em cooperação. Quando se liga a qualquer servidor numa rede, terá acesso a todos os canais na rede. Alguns exemplos de redes de &irc; são o Freenode e o Undernet. + + + + Lista de Servidores + + + + + + + + + + + + + + Lista de Servidores + + + + + + + +As suas Redes definidas estão listadas em conjunto com a Identidade usada para se ligar à rede, assim como os Canais aos quais se liga automaticamente após a autenticação. Se tiver seleccionado um grupo para as suas redes, estas ficam indentadas dentro do grupo. Carregue numa rede para a seleccionar. +Use estes botões para Adicionar uma rede nova, Editar uma rede seleccionada ou Remover a mesma. +Carregue neste botão para se ligar à Rede seleccionada e fechar o ecrã da Lista de Servidores. Poderá seleccionar mais que uma rede se o desejar, o que irá estabelecer a ligação a todas as redes seleccionadas. +Se carregar neste botão não irá eliminar as alterações que tenha feito. Simplesmente significa que você não se deseja ligar a qualquer rede nesta altura. + + + + + +Quando carrega no botão Adicionar o ecrã Adicionar Rede irá aparecer. + + + + Adicionar Rede + + + + + + + + + + + + + + + + + + + Adicionar Rede + + + + + + + +Indique aqui o nome da Rede. Poderá criar tantos itens quantos desejar no ecrã da Lista de Servidores com a mesma Rede. +Opcional. Se introduzir algo aqui, todas as Redes com o mesmo Grupo serão listadas em conjunto no ecrã da Lista de Servidores. +Escolha uma Identidade ou carregue no botão Editar para adicionar uma Identidade nova ou editar uma existente. A Identidade identificá-lo-á e irá determinar o seu &nickname; quando se ligar à rede. +Opcional. Este comando será enviado para o servidor depois de se ligar a este. Exemplo:/msg NickServ IDENTIFY konvirocks. O exemplo aqui mostrado é para a rede 'freenode', a qual necessita que os utilizadores registem o seu &nickname; com uma senha e um utilizador ao ligar-se. O konvirocks é a senha para o utilizador indicada na Identidade. Poderá indicar mais do que um comando se os separar por ponto-e-vírgulas. +Carregue aqui se desejar que o &konversation; se ligue automaticamente a esta rede sempre que abrir o &konversation;. +Esta é uma lista de Servidores de &irc; na rede. Ao ligar-se à rede, o &konversation; irá tentar ligar-se ao servidor do topo em primeiro lugar. Se este falhar, irá tentar os segundo servidor. Se este também falhar, tentará o terceiro, e assim por diante. Terá de ser indicado pelo menos um servidor. Carregue num servidor para o seleccionar. +Use estes botões para Adicionar um servidor, Editar um servidor seleccionado ou Remover o mesmo. Poderá também ajustar a ordem da lista de servidores e, deste modo, a ordem de tentativas de ligação. +Opcional. Esta é uma lista dos canais que serão ligados automaticamente, logo que o &konversation; o tenha ligado a um servidor. Poderá deixar este campo em branco se não se quiser ligar a quaisquer canais. +Use estes botões para Adicionar um canal, Editar um canal seleccionado ou Remover um dado canal. Poderá também alterar a ordem pela qual se irá ligar aos canais. + + + +Evite misturar os servidores das diferentes redes de &irc; com a mesma Rede. Evite introduzir o mesmo servidor em duas Redes diferentes. Caso contrário, a integração com o seu livro de endereços e a monitorização dos &nickname;s ligados do &konversation; não irão funcionar correctamente. + + + + +Quando você carregar no botão Adicionar da área Servidores, irá aparecer o ecrã para Adicionar um Servidor. + + + + Adicionar Servidor + + + + + + + + + + + + + + Adicionar Servidor + + + + + + + +O nome ou endereço IP do servidor. O irchelp.org mantém uma lista de servidores. +Indique o número de porto necessário para se ligar ao servidor. Para a maioria dos servidores, este deverá ser o 6667. +Se o servidor necessita de uma senha para se ligar, indique-a aqui, caso contrário deixe vazio. +Verfique se deseja usar o protocolo Secure Socket Layer (SSL) para comunicar com o servidor. Isto protege a privacidade das suas comunicações entre o seu computador e o servidor de &irc;. O servidor terá de suportar o protocolo SSL para isto funcionar. Na maioria dos casos, se o servidor não suportar o SSL, a ligação irá falhar. + + + + + +Quando você carregar no botão Adicionar da área de Ligação Automática aos Canais, irá aparecer o ecrã para Adicionar um Canal. + + + + Adicionar Canal + + + + + + Adicionar Canal + + + + + +Indique um nome de canal. Não se esqueça do # inicial. Se o canal necessitar de uma senha para se ligar, indique-a, caso contrário deixe em branco. + + + + + + +Listar os canais disponíveis + +Para mostrar uma lista com os canais disponíveis, escolha a opção Janelas Lista de Canais no menu principal. Depois de um ecrã de aviso, é criada uma nova página chamada Lista de Canais. + + + +A página da Lista de Canais. + + + + + + + + + + + + + + + + A página da Lista de Canais. + + + + + + + + +Indique aqui o texto de filtragem. + +Poderá limitar a lista de canais àqueles que tenham um número mínimo ou máximo de canais aqui. Se escolher 0 irá desactivar o critério respectivo. + +Carregue aqui para obter a lista de canais do servidor e aplicar o filtro. + +A lista de canais filtrada é apresentada aqui. Repare que, se não usar as expressões regulares, o &konversation; lista qualquer canal cujo nome contenha o texto do filtro que tiver indicado. O nome do canal não tem de começar pelo texto que introduziu. + +Seleccione o canal a que se deseja juntar, carregando para tal nele. Carregue com o botão direito no canal para obter uma lista com todos os endereços Web mencionados no tópico do canal. + +Carregue aqui para se juntar ao canal. É criada uma página para o canal. + + + + +Você deverá evitar carregar no botão Actualizar a Lista. A maioria dos servidores têm milhares de canais e, ao executar isto, poderá colocar uma carga elevada no servidor. Para além disso, poderá necessitar de vários minutos para terminar, dependendo da largura de banda da sua rede. Se o seu cliente for demasiado lento, o servidor poderá até desligá-lo a si. + +Em alguns casos existem canais "secretos" nos servidores. Esses canais não aparecem na Lista de Canais. Poderá à mesma ligar-se a esses canais se souber os seus nomes. Em qualquer Linha de Entrada, escreva: /join #canal. (O # é obrigatório). É criada uma nova página para o canal. Se se ligar a um canal e o Painel de Alcunhas mostrar apenas o seu &nickname;, é porque o canal não existia anteriormente. O servidor criou o canal e você é o operador. Neste caso, provavelmente desejará fechar o canal, escrevendo: /part. + + + + + + +Uma viagem pelo ecrã principal + +Vamos aprender mais sobre o ecrã Principal. O ecrã é mostrado em baixo com uma página de canais seleccionada. + + + +O ecrã principal. + + + + + + + + + + + + + + + + + + + O ecrã principal + + + + + + + + +Esta área é chamada de Linha de Entrada. O texto introduzido aparece só quando a página actual for um canal. Para enviar uma mensagem para todos no canal, escreva aqui a mensagem e carregue em &Enter;. A sua mensagem, assim como as mensagens de toda a gente no canal vai aparecendo em cima. Cada mensagem é antecedida da hora e do &nickname; do utilizador. + + Poderá também colar texto a partir da área de transferência. Se o texto colado tiver mais do que uma linha (mudanças de linha), aparece uma janela. Edite o texto como desejar e carregue em OK. + + Se o texto colado tiver mais do que 256 caracteres, ou se contiver mais do que uma linha, aparece uma mensagem que o avisará que as publicações grandes poderão causar quebras na ligação e inundações. Poderá à mesma prosseguir com a introdução de texto, mas se o fizer será uma má ideia, dado que as inundações irão incomodar os outros utilizadores do canal ou poderá ser desligado do servidor. É melhor enviar a mensagem em pedaços menores. + + + + Uma convenção usada em vários canais é anteceder as mensagens direccionadas para um dado utilizador com o seu &nickname;. O &konversation; oferece uma funcionalidade conveniente de completação de &nickname;s. Comece a escrever o &nickname; do utilizador e carregue depois em Tab. O &konversation; irá completar o resto do &nickname; do utilizador, seguido de dois pontos (:). Para personalizar a funcionalidade de completação, escolha a opção Configuração Configurar o Konversation no menu principal, expanda o Comportamento, carregue em Geral e na opção do Modo de completação. + + Poderá também indicar aqui um comando do &irc; se escrever primeiro um / seguido de um comando válido do &irc;. Veja os Comandos de &irc; mais usados. Em alguns servidores, você poderá escrever /help para obter uma lista dos comandos disponíveis ou escrever /help comando para obter ajuda num comando específico. + + + +Pode-se ligar a servidores e canais adicionais. Cada servidor e cada canal irá ter uma página separada aqui. Para mostrar uma lista com os canais disponíveis, veja a secção Listar os canais disponíveis. Para se ligar a um canal, escreva: /join #canal na Linha de Entrada. (O # é obrigatório). Para abandonar um canal, basta escrever /part. As páginas também aparecem aqui se abrir uma Lista de Canais, participar numa conversa privada (pesquisa), abrir o Extractor de &URL;s ou abrir uma ou mais Konsoles. Para mudar a visualização para outro ecrã, carregue na página correspondente ou use a roda do rato para circular pelas várias páginas. + +Para definir outras opções das páginas, escolha a opção Configuração Configurar o Konversation do menu principal, expanda o Comportamento e carregue no Geral. + + + +Estes &led;s irão piscar quando existir algo que você não tenha visto nessa página. O &led; irá piscar de forma mais lenta quando as únicas mensagens não vistas forem o join, o part, o quit ou as mudanças de &nickname;. Eles piscarão mais depressa se existem mensagens por ler de forma regular. As cores são as seguintes: + + Canal + + + Mensagens do Servidor, Lista de Canais ou Extractor de &URL;s + + + Konsole ou Estado do DCC. + + + Mensagem Privada (Pesquisa). + + + + +Carregue aqui para fechar a página. Se fechar a página de um Canal irá abandonar o canal. Se fechar uma página com Mensagens do Servidor irá deixar todos os canais a que se juntou, fechar todas as pesquisas abertas nesse servidor e desligar-se-á do mesmo. + +Carregue neste botão para mudar o seu próprio &nickname;. Aparece apenas quando a página actual é um canal. Para esconder este botão, escolha a opção Configuração Configurar o Konversation do menu principal, expanda a Aparência, carregue na Janela de Conversação e assinale a opção Mostrar a opção para mudar a própria alcunha. + +O tópico do canal é mostrado aqui. Passe o rato sobre o tópico para ver os tópicos mais compridos. Poderá alterar o tópico se carregar no botão à esquerda do tópico. Para esconder os tópicos do canal, escolha a opção Configuração Configurar o Konversation do menu principal, expanda a Aparência, carregue na Janela de Conversação e desligue a opção Mostrar o tópico do canal. + +Estes botões mostram o estado actual dos modos dos canais. Um botão fica em baixo se esse modo estiver ligado. Se você tiver os privilégios correctos, poderá também mudar os modos do canal, carregando para tal nestes botões ou carregue no botão à esquerda do tópico. Para esconder os botões do modo do canal, escolha a opção Configuração Configurar o Konversation do menu principal, expanda a Aparência, carregue na Janela de Conversação e desligue a opção Mostrar os botões de modo do canal. + + +Esta área é chamada de Painel de Alcunhas. É mostrado sempre que a página actual é um canal. Ele indica os &nickname;s de todos os utilizadores que se ligaram ao canal, incluindo você próprio. Passe o cursor do rato sobre um &nickname; para mostrar informações adicionais sobre o utilizador. Poderá alterar a forma como os ícones são apresentados ao lado de cada &nickname;, alterando o tema de ícones do &nickname;. Veja em Configurar os temas do &nickname; para mais informações. O tema Pontos Grandes, como é mostrado no ecrã acima, usa os seguintes ícones: + + + utilizador normal + + + + utilizador com voz. O utilizador poderá falar num canal moderado. + + + + semi-operador de canal + + + + operador de canal + + + + dono do canal + + + + administrador do canal + + + + + +Para além disso, se um utilizador estiver ausente, é desenhada uma pequena cruz vermelha por cima do seu ícone. + +Carregue com o &RMB; em qualquer &nickname; para mostrar um menu de contexto das operações que pode efectuar com este &nickname;. Por exemplo, poderá enviar um ficheiro para o &nickname;. Este é também o local em que poderá associar um &nickname; a uma lista de contactos no seu livro de endereços. + +Para esconder o Painel de Alcunhas, escolha a opção Janela Esconder a Lista de Alcunhas no menu principal. + + + +Estes são chamados de Botões Rápidos. Por omissão, não são apresentados. Para os mostrar, veja a secção Configurar os Botões Rápidos. Poderá personalizar as suas definições para os comandos que desejar. + + + + +Nota Você pode controlar a forma como as mensagens são mostradas na área de mensagens do canal, bem como nas páginas de pesquisas. Por exemplo, poderá alterar a cor das mensagens, tocar um som quando for recebida uma mensagem que contenha determinado texto ou responder automaticamente às mensagens. Veja o Realce de mensagens para mais informações. + +Nota: Os nomes dos canais algumas vezes começam por &, + ou !. O primeiro carácter de um canal determina o seu tipo (RFC 2811) da seguinte forma: # - Canais normais. ! - Canais normais. & - Local. Canais que só poderão se ligados a partir do servidor que contém o canal. Todos os outros canais poderão ser ligados a partir de qualquer servidor da rede. + - Canais que não suportam modos do canal. Isto significa que todos os modos estão desactivados, com excepção da opção do canal 't', que está activa. Os nomes dos canais podem ter até 200 caracteres e poderão conter quaisquer caracteres, excepto o espaço, a vírgula e o Ctrl-G. + + + + + + +Ligação Rápida + +Algumas vezes poderá querer ligar-se a um servidor sem ter o problema de criar um servidor novo na Lista de Servidores. + +Escolha a opção Ficheiro Ligação Rápida no menu principal. O ecrã das Ligação Rápida irá aparecer. + + + +O ecrã de Ligação Rápida. + + + + + + O ecrã de Ligação Rápida + + + + + +Indique o endereço do servidor no campo URL do Servidor, o seu &nickname; desejado no campo Alcunha e carregue no botão Ligar. Quando o &konversation; se tiver ligado ao servidor, indique o comando /join #nome_canal para se ligar a um canal. + + + + + + +Comandos de &irc; usados frequentemente + +Segue-se uma pequena lista de comandos usados com frequência no &irc;. Veja o RFC 2812 para lista completa de todos os comandos ou vá a irchelp.org. Para uma lista dos comandos processados pelo &konversation;, veja os comandos do &konversation;. + + + + + +/help +Lista os comandos disponíveis no servidor actual. Não é suportado por todos os servidores. + + + +/help comando +Fornece alguma ajuda sobre o comando. Não é suportado por todos os servidores. + + + +/join #canal +Liga-se ao canal #canal. Se o canal não existir já, será criado e você será o operador do mesmo. + + + +/part +Abandona o canal actual e fecha a página do canal. + + + +/part #canal +Abandona o canal #canal e fecha a página correspondente ao mesmo. É um sinónimo do /leave + + + +/me mensagem +Envia a mensagem para o canal, antecedida do seu &nickname;. Por exemplo, se o seu &nickname; for ZéManel, ao escrever O /me está a fazer um café. irá mostrar a mensagem O ZéManel está a fazer um café. A menos que tenham filtrado estes tipos de mensagens, todos os utilizadores as vêem. Este tipo de mensagens é usado tipicamente para enviar mensagens não-verbais, como o seu estado emocional actual ou o que você está a fazer fisicamente. Se tiver abandonado o seu computador, use o comando /away em alternativa. + + + +/away mensagem +Se alguém lhe tentar enviar uma mensagem privada ou o convidar para um canal, eles serão avisados de que você está ausente do seu posto de trabalho com a with mensagem. + + + +/away +Cancela um comando /away mensagem. + + + +/query alcunha +Cria uma página nova com a alcunha do utilizador para uma conversa privada, conhecida normalmente normalmente no IRC como uma Pesquisa ou 'Query'. Tudo o que for escrito aqui só é visível para si e para o seu companheiro da conversa. + + + +/msg alcunha mensagem +Envia a mensagem para o utilizador com o &nickname; alcunha. Só o utilizador correspondente à alcunha é que vê a mensagem. Use o /query para conversas mais longas. + + + +/invite alcunha +Convida o utilizador com o &nickname; alcunha para se ligar a um canal. Este comando é especialmente útil se o canal for só por convite. + + + + + + + + + + +Conversas privadas (pesquisas ou 'queries') + +Uma conversa privada é uma que só você e outra pessoa poderão ver. As conversas privadas são chamadas de "pesquisas" no &konversation;. Para iniciar uma conversa privada, escreva /query alcunha em qualquer linha de entrada, onde a alcunha é o &nickname; da pessoa com quem deseja falar. Poderá também carregar com o &RMB; no &nickname; da pessoa no Painel de Alcunhas e escolha Abrir uma Pesquisa Será então criada uma página nova. Anuncie-se a si próprio, enviando uma mensagem. + +As pesquisas são iguais aos canais, excepto que só você e a outra pessoa poderão participar no canal. + +Para sair da pesquisa, basta fechar a página. Repare contudo que, se a outra pessoa lhe enviar outra mensagem na pesquisa, a página irá abrir de novo. + +Para sair de todas as pesquisas, escolha a opção Janela Fechar Todas as Pesquisas Abertas no menu principal, ou carregue em F11. + +Quando outra pessoa iniciar uma conversa privada consigo, o &konversation; cria uma página nova com o &nickname; dela. Se não quiser falar com a pessoa, feche a página. + + + + + + +Activar as notificações + +As Notificações são acções que o &konversation; irá efectuar sempre que ocorrer um evento. Suponha que tem o &konversation; a correr, mas está minimizado ou escondido por detrás de outras janelas de aplicações no seu ecrã. Se alguém quiser comunicar consigo, ou se o seu amigo se ligar a um canal, gostaria de ser alertado desse facto. As notificações poderão tratar desse assunto. + +Para configurar as notificações, escolha a opção Configuração Configurar as Notificações do menu principal. Irá aparecer o ecrã de Configuração das Notificações. + +Carregue imediatamente no botão Mais Opções. + + + +O ecrã de Configuração das Notificações. + + + + + + + + + + + + + O ecrã de Configuração das Notificações + + + + + + + + +Carregue aqui para seleccionar um evento. + +Assinale os tipos de notificações que deseja que aconteçam quando o evento ocorrer. (O Marcar o item da barra de tarefas faz com que o item na barra de tarefas pisque quando ocorrer o evento.) + + + + +Repita, seleccionando outro evento e escolhendo as notificações desejadas. Quando tiver configurado todas as notificações desejadas, carregue no botão Aplicar. + + + + +Logo que tenha configurado as suas notificações, poderá activar ou desactivar todas as acções de notificação aqui. Por exemplo, poderá optar por tocar um som sempre que o seu &nickname; for mencionado numa mensagem. Quando estiver na sua estação de trabalho, poderá desligar os sons, mas quando estiver longe dela, poderá activá-los para lhe chamar a atenção. + + + + +Poderá também alertar-se a si próprio, sempre que alguém menciona a sua alcunha numa mensagem, usando a funcionalidade do &konversation; para o realce. + + + + + + +Monitorizar quem está ligado + +O &konversation; mantê-lo-á informado quando os seus amigos se ligarem à rede de &irc; ou não. + +Poderá associar os &nickname;s ligados com os itens de contactos do seu livro de endereços. Quando o fizer, o &nickname; e a rede de &irc; onde o &nickname; está ligado serão introduzidos no contacto do livro de endereços. A rede de &irc; é guardada porque os &nickname;s são únicos para uma dada rede de &irc;. Os &nickname; de duas redes de &irc; diferentes não é necessariamente a mesma pessoa, mas o mesmo &nickname; em dois servidores diferentes, dentro da mesma rede de &irc; é geralmente a mesma pessoa. + +É por isso que é importante usar a mesma Rede para todos os servidores na mesma rede de &irc;, ao definir as redes, servidores e canais de ligação automática. + +Poderá também definir &nickname;s que deseje vigiar e que não estejam também no seu livro de endereços. Também neste caso, cada um dos &nickname;s tem uma rede de &irc; associada. Veja em baixo. + +Para activar a funcionalidade de vigia de &nickname;s, escolha a opção Janelas Alcunhas Vigiadas Ligadas no menu principal. O ecrã das Alcunhas Vigiadas Ligadas irá aparecer. + + + + Alcunhas Vigiadas Ligadas. + + + + + + + + + + + + + + + + Alcunhas Vigiadas Ligadas + + + + + + + +Os &nickname;s na sua lista de vigia e também os &nickname;s associados com os itens do seu livro de endereços são listados aqui. Eles são enumerados sob a sua rede de &irc; associada. Se não estiverem listados quaisquer &nickname;s, ou não indicou nenhuns &nickname;s para vigiar, ou então terá de activar a funcionalidade de vigia de &nickname; (veja em baixo). Expanda cada &nickname; ligado para ver uma lista dos canais a que o &nickname; se ligou. Os ícones ao lado de cada canal são os mesmos que aparecem no Painel de Alcunhas nos ecrãs dos canais. +A informação conhecida acerca do &nickname; é apresentada aqui. Quando o ecrã de Alcunhas Vigiadas Ligadas é apresentado da primeira vez, esta informação encontra-se de forma esparsa. A cada 8 segundos, é enviado um comando WHOIS para o servidor, a pedir informações para os &nickname;s que não têm quaisquer informações. Isto continua até que existam informações para todos os &nickname;. +As alcunhas que não estejam ligadas a nenhuma das redes de &irc; a que está ligado, são indicados na parte Desligado da listagem. +As alcunhas que estejam associadas a um item de contacto no seu livro de endereços têm este ícone () ao lado da informação deles. +Use estes botões para associar um &nickname; com um contacto no seu livro de endereços, remover uma associação ou abrir o livro de endereços para editar a informação do contacto. Veja o Manual do &kaddressbook; para mais instruções sobre como usar o livro de endereços do KDE. + + + +Para adicionar novos &nickname;s à vigia, carregue no botão Editar a Lista de Vigia. O ecrã com as Alcunhas Vigiadas irá aparecer. + + + +Alcunhas Vigiadas + + + + + + + + + + + + + + + Alcunhas Vigiadas + + + + + + + + +Assinale esta opção para activar a funcionalidade para vigiar alcunhas. + +Se quiser que o ecrã de Alcunhas Vigiadas Ligadas apareça automaticamente quando você abre o &konversation;, assinale esta opção. + +Os &nickname;s dos utilizadores que deseja vigiar estão aqui indicados. Cada &nickname; tem uma rede de &irc; associada. + +Carregue nestes botões para adicionar ou remover &nickname;s da lista. + +A funcionalidade de Alcunhas Vigiadas Ligadas funciona através de uma pesquisa periódica no servidor. Este campo indica com que frequência esta ocorre. Evite números inferiores a 20 segundos, dado que isto coloca uma carga excessiva no servidor. + +No ecrã de Alcunhas Vigiadas Ligadas acima, poderá fazer duplo-click em qualquer &nickname; para que este comando seja enviado para o servidor. O %u será substituído pelo &nickname;. O %n é necessário no fim do comando. + + + + +Carregue no botão OK quando tiver terminado de adicionar ou remover &nickname;s. + +Nota: Sempre que mostrar o ecrã de Alcunhas Vigiadas Ligadas, poderá levar algum tempo antes que apareçam alguns &nickname;s até o &konversation; pesquisar o servidor. Normalmente, você poderá deixar o ecrã de Alcunhas Vigiadas Ligadas a correr. + +O &konversation; mostra também uma mensagem em todos os canais sempre que um utilizador da sua lista de Alcunhas Vigiadas se ligar ao desligar do servidor. A mensagem é semelhante a esta: + +[17:52] [Notificação] O psn está ligado (irc.kde.org). + + + + + + +Realce de mensagens + +Você pode controlar a forma como as mensagens são apresentadas nos ecrãs dos canais e das pesquisas. + +Para activar a funcionalidade de realce;, escolha a opção Configuração Configurar o &konversation; no menu principal. O ecrã para Editar as Preferências irá aparecer. + + + +O ecrã de realce. + + + + + + + + + + + + + + + + + + + O ecrã de Realce + + + + + + + + +Carregue aqui para seleccionar o ecrã de Realce. +Carregue aqui para adicionar um novo item à Lista de realce. Quando for seleccionado um item na lista, podê-lo-á editar no painel abaixo. +Indique aqui um padrão de texto. Todas as mensagens recebidas que correspondam a este padrão, em qualquer ponto da mensagem, irão activar o realce da mensagem. Se você tiver o utilitário do Editor de Expressões Regulares do &kde; no seu sistema, o botão à direita do padrão ficará activo. Carregue para mostrar o editor, o que o irá ajudar a preparar os padrões mais complexos. (O Editor de Expressões Regulares do KDE faz parte do pacote kdeutils.) +Se o padrão for encontrado numa mensagem, a mensagem inteira será apresentada com a cor que seleccionar aqui. +Se o desejar, o &konversation; irá tocar um som, sempre que o padrão corresponder. Carregue no botão para escolher o ficheiro de áudio que será reproduzido. Carregue no botão de teste para ouvir o som. +Se desejar que o &konversation; envie automaticamente uma mensagem de resposta quando o padrão corresponder, escreva aqui a mensagem. Use esta funcionalidade com cuidado, dado que poderá incomodar os utilizadores de &irc; com demasiada conversa, se não tiver cuidado. Poderá também introduzir comandos de &irc; ou do &konversation; aqui. +Se tiver configurado os sons para alguma das suas selecções, podê-los-á desactivar a todos nesta opção. +Se assinalar esta opção, sempre que alguém mencionar a sua &nickname; numa mensagem, esta será apresentada na cor que escolher à direita. +Normalmente o realce não se aplica às mensagens que você escrever. Se quiser realçar as suas mensagens também, assinale esta opção e escolha uma cor à direita. + + + + + + + + + +Configurar a Visualização no Ecrã (&osd;) + +A Visualização no Ecrã (&osd;) é uma funcionalidade única do &konversation;. Com o &osd; ligado, as mensagens do canal irão aparecer no seu ecrã, mesmo que o &konversation; esteja minimizado. Aqui está um exemplo do &osd; em acção. A mensagem no canto superior esquerdo do ecrã é do &konversation;, o qual está a correr minimizado na bandeja do sistema. + + + +Exemplo da Visualização no Ecrã + + + + + + Exemplo da Visualização no Ecrã + + + + + +Para activar a &osd;, escolha a opção Configuração Configurar o &konversation; no menu principal. O ecrã para Editar as Preferências irá aparecer. + + + +O ecrã de Visualização no Ecrã. + + + + + + + + + + + + + + + O ecrã de Visualização no Ecrã. + + + + + + + + +Carregue aqui para expandir o item de Notificação. + +Carregue aqui para seleccionar o ecrã de Visualização no Ecrã. + +Assinale esta opção para activar o &osd;. + +Carregue neste botão para escolher um tipo de letra para o &osd;. (Nota: Nem todos os tipos de letra funcionam. O Luxi Sans 22 e o Impact 22 sabe-se que funcionam.) + +Assinale aqui as opções para seleccionar os tipos de mensagens que deseja que apareçam no ecrã e carregue então no botão Aplicar. + + + + + + + + + +Enviar mensagens coloridas + +Você poderá adicionar cores às mensagens que enviar para qualquer canal. Na Linha de Entrada de qualquer canal, comece a escrever a sua mensagem. Carregue no Botão para Inserir uma Cor do IRC botão para Inserir uma Cor do IRC ou escolher a opção Inserir Cor de IRC no menu principal. O ecrã do Selector de Cores do IRC irá aparecer. + + + +O ecrã de Escola de Cores do &irc;. + + + + + + O ecrã de Escola de Cores do &irc; + + + + + +Escolha uma cor e carregue em OK. Continue a escrever a sua mensagem na Linha de Entrada. Para alterar a cor de novo, carregue no botão Inserir uma Cor do &irc;. Escolha uma cor diferente e carregue em OK. + + + + + + +Configurar os temas do &nickname; + +Poderá alterar os ícones que são apresentados ao lado dos &nickname;s no Painel de Alcunhas das páginas dos canais. Para mudar o tema do &nickname;, escolha a opção Configuração Configurar o Konversation no menu principal. O ecrã para Editar as Preferências irá aparecer. Carregue em Aparência para o expandir, pelo que deverá carregar depois em Temas para mostrar o ecrã de Temas. + + + +O ecrã de temas. + + + + + + + + + + + + + + O ecrã de temas + + + + + + + + +Carregue para seleccionar o ecrã de Temas da alcunha. +Seleccione um tema. +Os ícones de exemplo são mostrados aqui, para o caso do tema escolhido. +Se tiver obtido um tema algures, carregue aqui para o instalar. + + + + + + + + + +Configurar os Botões Rápidos + +Poderá activar uma funcionalidade para mostrar os Botões Rápidos no ecrã Principal, em que ao fazê-lo aparecerão então oito Botões Rápidos. Os botões poderão ser personalizados de acordo com a sua vontade para executar os comandos de &irc; mais usados. Para personalizar os Botões Rápidos, escolha a opção Configuração Configurar o Konversation do menu principal. O ecrã para Editar as Preferências irá aparecer. Carregue na Aparência para o expandir e carregue depois nos Mostrar os botões rápidos, seguido do botão OK. + +Os botões poderão ser personalizados de acordo com a sua vontade para executar os comandos de &irc; mais usados. Para personalizar os Botões Rápidos, escolha a opção Configuração Configurar o Konversation do menu principal. O ecrã para Editar as Preferências irá aparecer. Carregue no Comportamento para o expandir e carregue depois nos Botões Rápidos para mostrar o ecrã de Botões Rápidos. + + + +O ecrã dos Botões Rápidos + + + + + + O ecrã dos Botões Rápidos + + + + + +Existem 8 Botões Rápidoss. Carregue num item para o alterar. A coluna do Nome do botão é o nome que irá aparecer no botão no ecrã Principal. Mantenha os nomes curtos. A coluna da Acção do Botão é a acção que será executada quando carregar no Botão Rápido. As dicas para criar as acções são dadas no ecrã. + +Carreguem em OK para terminar as alterações. + +Exemplo: + + + + + Nomed do Botão: Mensagem + + Acção do Botão: Mensagem %u (existe um espaço a seguir ao %u) + + + + + +Para usar este botão no ecrã Principal, carregue num &nickname; do Painel de Alcunhas, carregando então depois no botão. O /MSG irá aparecer na Linha de Entrada segundo do &nickname; escolhido. Escreva a mensagem que deseja enviar para essa pessoa e carregue em &Enter;. A mensagem será enviada para o utilizador. Só esse utilizador irá ver a mensagem. + +Nota: Não poderá adicionar ou remover Botões Rápidos. + + + + + + +Enviar e receber ficheiros + +Você poderá enviar ficheiros através do &irc; para outros utilizadores ligados, assim como eles lhe poderão enviar ficheiros para si. + + +ATENÇÃO: Nunca abra um ficheiro que alguém lhe envie a não ser que seja de uma fonte segura. Poderá ser um vírus. + + +Para enviar um ficheiro para alguém num canal, carregue com o &RMB; no &nickname; da pessoa no Painel de Alcunhas do ecrã Principal. Escolha a opção Enviar um Ficheiro Irá aparecer uma janela onde poderá escolher um ficheiro para ser enviado. A seguir, aparecerá uma nova página com o Estado do DCC. + + + +A página de Estado do DCC + + + + + + + + + + + + + A página de Estado do DCC + + + + + + + + +O &nickname; do destinatário e o nome do ficheiro aparecem aqui. + + +A coluna do Estado indica o estado do envio ou da recepção do ficheiro da seguinte forma: + + + + + + A oferecer + + + Você está a tentar enviar um ficheiro para o destinatário. O &konversation; está à espera que o destinatário aceite o ficheiro. + + + + + A ligar + + + O &konversation; está a tentar estabelecer uma ligação com o outro extremo. + + + + + A Enviar + + + O &konversation; está a enviar o ficheiro para o outro extremo. + + + + + A Receber + + + O &konversation; está a receber o ficheiro do outro lado. + + + + + Concluído + + + O ficheiro foi transferido com sucesso. + + + + + Parado + + + A transferência já começou mas não está a progredir nada de momento. + + + + + Interrompido + + + Ou carregou no botão para Cancelar ou a outra pessoa interrompeu a transferência. + + + + + Falhou + + + Ocorreu um erro e a transferência não foi bem sucedida. + + + + + Em Espera + + + A transferência foi aceite a irá começar quando o programa no destinatário a confirmar. + + + + + Procurar + + + O &konversation; está a tentar obter o endereço IP do remetente. + + + + + Continuar + + + Quando começa um transferência mas o ficheiro já existir no sistema do utilizador, este será avisado de que O ficheiro já existe. Continuar a transferência? Este estado indica que o utilizador prosseguiu com a transferência. + + + + + + + + +Quando alguém lhe quiser enviar um ficheiro, a página do Estado do DCC será criada (se não estiver já criada). Carregue na página do Estado do DCC para a mostrar. Carregue no ficheiro para o seleccionar e depois carregue neste botão para aceitar o ficheiro e para a transferência começar. Nota: Poderá configurar o &konversation; para aceitar automaticamente os envios das outras pessoas ao escolher a opção Configuração Configurar o Konversation Configuração do DCC no menu principal. + + + + + +Se tiver problemas a enviar ou a receber ficheiros, a sua 'firewall' ou 'router' poderão esta a bloquear os portos do DCC. Veja as Perguntas e Respostas. + + + + + + +Integração com o &kaddressbook; + +Você poderá associar qualquer &nickname; com um contacto no KAddressBook. Logo que tenha feito isto, o &konversation; irá mostrar o nome verdadeiro do contacto a seguir ao &nickname; no Painel de Alcunhas. + +Para associar um &nickname; com um contacto no KAddressBook, carregue com o &RMB; no &nickname; da pessoa no Painel das Alcunhas do ecrã Principal. Escolha o Quem é para mostrar a informação que o ajuda a determinar o nome verdadeiro do utilizador. De seguida, carregue com o &RMB; no &nickname; da pessoa de novo e escolha as Associações ao livro de endereços . Irá aparecer um submenu. Se o &nickname; não estiver já associado a um contacto, escolha a opção Criar um novo contacto . O ecrã para Editar o Contacto irá aparecer. + + + +O ecrã para Editar o Contacto. + + + + + + + + + + + + + O ecrã para Editar o Contacto. + + + + + + + + +O &nickname; é preenchido aqui automaticamente. Se souber o nome verdadeiro da pessoa, substitua o &nickname; pelo nome verdadeiro. + + +Repare que o &nickname; não aparece aqui. Em alternativa, .... + + + +Carregue aqui. Aparece então a janela dos Endereços de IM. + + + + + + + A Janela dos Endereços de IM. + + + + + + A Janela dos Endereços de IM. + + + + + +Repare que o &konversation; preenche o &nickname; por si com o protocolo IRC. + +Veja o Manual do &kaddressbook; para mais instruções sobre como usar o livro de endereços do &kde;. + +Preencha quaisquer informações adicionais sobre o &nickname; que conhece e carregue em OK. O nome verdadeiro da pessoa irá aparecer entre parêntesis ao lado do &nickname; no Painel de Alcunhas do &konversation;. O nome verdadeiro também aparecerá quando o rato passar por cima do &nickname;. + +Logo que um &nickname; tenha sido associado com um contacto do &kaddressbook;, você poderá carregar com o &RMB; no &nickname; da pessoa no Painel de Alcunhas e editar o contacto associado, associar o &nickname; com um contacto diferente ou remover a associação. + +Se tiver associado um &nickname; com um contacto e o utilizador alterar o seu &nickname; enquanto você estiver a correr o &konversation;, ele irá associar automaticamente o novo &nickname; com o contacto, mantendo também a associação original. + +Se você associar um &nickname; do &irc; com um contacto do &kopete;, a associação irá também aparecer no &konversation; e vice-versa. + +Nota: É possível seleccionar mais do que um &nickname; no Painel de Alcunhas, carregar com o &RMB; e efectuar várias associações. + + + + + + +Capturar os &URL;s das mensagens + +Em qualquer canal, os utilizadores publicam às vezes os &URL;s de 'sites' interessantes ou de outros recursos na Web. Poderá carregar num destes &URL;s para que o &konversation; invoque a aplicação associada com o &URL;. A aplicação invocada depende do tipo &MIME; do &URL;. Por exemplo, um &URL; que comece por http: irá activar o seu navegador Web por omissão do &kde; para mostrar a página Web. (Poderá também definir o navegador Web a usar.) Se o &URL; sair da visibilidade do ecrã, poderá ter problemas a encontrá-lo de novo. O &konversation; poderá manter uma lista conveniente de todos os &URL;s para si. Para activar esta funcionalidade, escolha a opção Janelas Extractor de &url; no menu principal. Irá aparecer uma nova página chamada Extractor de &url;. + + + +A página do Extractor de &url;. + + + + + + + + + + + + + + + + A página do Extractor de &url;. + + + + + + + + +Esta é a lista de &URL;s desde que você iniciou o &konversation;. A coluna da Alcunha é o &nickname; da pessoa que publicou o &URL;. Se o &nickname; estiver em branco, o &url; apareceu numa página de Mensagens do Servidor. (Os &URL;s que aparecem nas mensagens do início e fim de uma ligação não são listados). Carregue num &URL; para o seleccionar. + +Carregue aqui para activar a aplicação associada com o &URL; seleccionado. A aplicação lançada depende do tipo &MIME; do &URL;. Por exemplo, um &URL; que comece por um http: irá activar o seu navegador Web por omissão e mostrar a página Web. Para as páginas Web, poderá também indicar o navegador Web a usar. + +Carregue aqui para copiar o &URL; seleccionado para a área de transferência do &kde;. + +Carregue aqui para remover o &URL; seleccionado da lista. + +Carregue aqui para gravar a lista de &URL;s num ficheiro. + +Carregue aqui para limpar a lista. + + + + + + + + + +Configurar o seu navegador Web preferido + +Quando carregar num &URL; seleccionado no &konversation;, ele irá lançar a aplicação do &kde; por omissão que estiver associada ao tipo &MIME; do &URL;. Por exemplo, ao carregar num &URL; que comece por http, o &konqueror; é lançado para mostrar a página Web. Poderá indicar uma aplicação diferente da predefinida pelo &kde;. Por exemplo, poderá usar o Mozilla em alternativa. + +Para escolher um navegador Web diferente, escolha a opção Configuração Configurar o &konversation; do menu principal. O ecrã para Editar as Preferências irá aparecer. + + + +O ecrã do Navegador Web + + + + + + + + + + + + + O ecrã do Navegador Web + + + + + + + + +Carregue aqui para mostrar o ecrã do Navegador Web. + +Carregue aqui para indicar que deseja usar um navegador Web personalizado. + +Indique o comando para lançar o seu navegador Web desejado. Quando carregar num &URL;, o %u será substituído pelo &URL;. + + + + +Sugestão: (apenas para os sistemas &UNIX;) O comando por omissão é o mozilla '%u', o qual irá iniciar uma instância nova do Mozilla de cada vez que carregar num &URL;. Se preferir que o Mozilla mostre a página Web numa página nova de uma instância já existente, crie um ficheiro que contenha o seguinte: + + +#!/bin/sh +mozilla -remote "openURL($@, new-tab)" || exec mozilla "$@"; + + + +Dê o nome moz ao ficheiro, coloque-o na PATH, e torne-o executável (chmod a+x moz). Depois, indique moz '%u' para o comando do navegador Web do ecrã acima. + +Nota: A configuração do Navegador Web não se aplica aos &URL;s mailto:. Os &URL;s mailto: invocam sempre o cliente de e-mail por omissão do &kde;. + +Carregue em Aplicar para gravar as suas alterações. Precisa de se ligar de novo a cada servidor e canal para que as alterações façam efeito. A forma mais simples de fazer isto é sair e voltar a arrancar o &konversation;. + + + + + + +Marcar o Canal e os Registos das Pesquisas + +Poderá inserir um marcador nos ecrãs dos canais e das pesquisas para o ajudar a localizar rapidamente as informações. Para o fazer, escolha a opção Inserir Linha de Recordação no menu principal. ou carregar em &Ctrl;R. Irá aparecer uma linha no fundo do texto do ecrã. A linha deslocar-se-á com o resto do texto do ecrã. + +Para que a Linha de Recordação seja inserida em todos os canais e pesquisas ao mesmo tempo, escolha a opção Configuração Configurar o Konversation do menu principal, expanda o Comportamento, carregue na Janela de Conversação e assinale a opção Mostrar a linha de recordação em todos os canais/pesquisas. + +Para que o &konversation; introduza automaticamente uma Linha de Chamada de Atenção sempre que você enviar um comando /away mensagem, veja como Configurar a sua identidade. + + + + + + +Registo + +Se o registo estiver activo, o &konversation; manterá um registo de cada sessão do Servidor, Canal e Conversa privada (pesquisa). Cada sessão é guardada num ficheiro de registo no disco. Quando abrir a mesma sessão de novo, o &konversation; irá adicionar dados ao registo, Este irá crescer até um determinado limite que pode ser definido por si (veja em baixo). Quando se atinge o limite, as mensagens mais antigas são eliminadas. + +Sempre que abrir uma sessão de novo, são lidos aproximadamente os últimos 1024 caracteres da sessão anterior, a partir do fim do registo, sendo mostrados de seguida no ecrã. + +À medida que a sua sessão prossegue, as mensagens vão se deslocando e deixando de ficar visíveis. Poderá deslocar-se para trás para ver essas mensagens. Eventualmente, para conservar alguma memória, as mensagens mais antigas são descartadas. Isto é chamado de Limite de posicionamento. As mensagens que desapareçam da visibilidade devido ao Limite de posicionamento estão à mesma disponíveis no ficheiro de registo, se este estiver activo. + +Para ver o registo de uma sessão, carregue na página da sessão para a tornar a actual e escolha a opção Janela Abrir o Ficheiro de Registo do menu principal. Irá aparecer uma página nova com o ficheiro do registo. + + + +Ficheiro de Registo + + + + + + + + + + + + + + + Ficheiro de Registo + + + + + + + +As mensagens no ficheiro de registo são mostradas aqui. As mensagens mais antigas encontram-se no topo e as mais recentes em baixo. +Carregue neste botão para gravar o ficheiro de registo noutro ficheiro. +Carregue para actualizar a visualização do ficheiro de registo. Enquanto você estiver a ver um ficheiro de registo, as mensagens mais recentes da sessão correspondente não são adicionadas automaticamente à área do ficheiro de registo. Use este botão para ver as mensagens mais recentes. +Carregue para limpar o visualizador do ficheiro de registo e o conteúdo do mesmo no disco. +Use esta opção para definir o tamanho máximo do ficheiro de registo. Esta opção não faz efeito até que você reinicie o &konversation;. Cada ficheiro de registo poderá ter uma opção separada. + + + +O Limite de posicionamento poderá ser alterado se escolher a opção Configuração Configurar o &konversation; do menu principal, expandindo depois o Comportamento e carregando na Janela de Conversação. O campo de Limite do posicionamento aparecerá no ecrã. Se o configurar como Ilimitado, as mensagens não são eliminadas na área de visualização. + +Para activar ou desactivar o registo e definir outras opções de registo, escolha a opção Configuração Configurar o &konversation; do menu principal, expanda o Comportamento e carregue no Registo. + + + + + + +Comandos do &konversation; + +Os seguintes comandos são interpretados pelo &konversation; e podem ser diferentes dos comandos normais do &irc;. Os itens entre parêntesis rectos são opcionais. Os itens separados por uma barra (|) são formas alternativas do comando. Os comandos não listados aqui são enviados para o servidor tal-e-qual. + + + + + +/me mensagem +Envia a mensagem para o canal, antecedida do seu &nickname;. Por exemplo, se o seu &nickname; for ZéManel, ao escrever O /me está a fazer um café. irá mostrar a mensagem O ZéManel está a fazer um café. A menos que tenham filtrado estes tipos de mensagens, todos os utilizadores as vêem. Este tipo de mensagens é usado tipicamente para enviar mensagens não-verbais, como o seu estado emocional actual ou o que você está a fazer fisicamente. Se tiver abandonado o seu computador, use o comando /away em alternativa. + + + +/ame mensagem +Como o comando /me acima, excepto que a mensagem é enviada para todos os canais e pesquisas que tiver abertos em todos os servidores a que está ligado no &konversation;. + + + +/join canal [senha] +Liga-se ao canal. Se o servidor o permitir e se o canal não existir já, este é criado e você será o operador do canal. Se o canal necessitar de uma senha para se ligar, indique-a em senha. A maioria dos nomes dos canais começa por um # + + + +/j canal [senha] +O mesmo que o comando /join acima. + + + +/part [canal] [razão] +Sai do canal com a razão indicada e fecha a página correspondente do canal. Dentro de uma página de um canal ou uma pesquisa do &konversation;, poderá apenas escrever /part, o que irá fechar esse canal ou pesquisa com a razão predefinida que é indicada na Configuração da Identidade. + + +/leave [canal] [razão] +O mesmo que o comando /part indicado acima. + + +/quit +Quando for indicado em qualquer página de um canal, pesquisa ou DCC, desliga-se do servidor correspondente e fecha todas as páginas de canais, pesquisas ou DCCs desse servidor. + + +/notice alcunha|canal mensagem +Envia a mensagem para o utilizador com o &nickname; alcunha ou para todos os que estiverem ligados ao canal. Segue-se um exemplo do que aparece para si na página do canal + +[17:14] [Aviso] A enviar o aviso "Penso que percebi" para o #konversation + +E isto é o que os destinatários recebem + +[17:15] [Notice] -Portugal- Penso que percebi + + + + +/query alcunha +Cria uma página nova com a alcunha do utilizador para uma conversa privada, a qual é conhecida normalmente no IRC como uma Pesquisa. Tudo o que for escrito aqui só é visível para si e para o seu amigo. Poderá indicar mais do que um &nickname; separado por espaços, para que seja aberta uma página por cada &nickname;. Cada uma destas páginas será privada entre si e o respectivo utilizador. + + + +/msg alcunha|canal mensagem +Envia uma mensagem privada para o utilizador com o &nickname; alcunha ou para todos os utilizadores no canal. Ao contrário do /query, este não abre uma página nova. Se a mensagem começar por um /me , a mensagem é formatada da mesma maneira que um comando /me. + +Exemplos + +/msg Pedro preciso de ajuda com o comando msg + +/msg #konversation Nova versão do Konvi disponível! + +/msg Pedro /me está a compilar o Manual agora. + + + + + +/smsg alcunha|canal mensagem +O mesmo que o /msg excepto que a mensagem não é mostrada no seu ecrã. Isto é útil para evitar que as senhas e outras informações importantes sejam expostas no seu ecrã ou fiquem registadas. + + + +/amsg alcunha|canal mensagem +Como o comando /msg acima, excepto que a mensagem é enviada para todos os canais e pesquisas que tenha aberto para todos os servidores a que esteja ligado no &konversation;. + + + +/op alcunha +Quando for indicado na página de um canal, tenta atribuir ao utilizador alcunha privilégios de operador do canal. Poderá não funcionar se você tiver privilégios insuficientes no canal (você próprio precisa de ser um operador do canal). Poderá indicar mais do que um &nickname; separado por espaços. + + + +/deop alcunha +Quando for introduzido na página de um canal, retira os privilégios de operador do canal do utilizador correspondente a alcunha. Poderá indicar mais do que um &nickname;, separado por espaços. + + + +/oper [alcunha] +Concede ao utilizador com o &nickname; alcunha privilégios de Op-&irc; (Administrador). Isto só funciona se o &nickname; estiver na linha O: do servidor. Os Ops-&irc; têm o privilégio para executar o /kill dos &nickname;s, de efectuarem um /connect dos servidores à rede do &irc;, entre outras coisas. Se a alcunha não tiver sido indicado, tenta atribuir a si próprio os privilégios de Op-&irc;. Ser-lhe-á pedido o seu nome de utilizador e a senha do Op-&irc; em qualquer dos casos. + + + +/voice alcunha +Em certos canais (com a opção +m), os utilizadores não poderão enviar mensagens a não ser que tenham 'voz' (permissão para tal) no canal. Este comando tenta atribuir ao utilizador alcunha privilégios de 'voz'. Precisa de ter privilégios de operador do canal para executar este comand. Ele é mais utilizado quando você é um operador de um canal moderado. + + + +/unvoice alcunha +Retira os privilégios de 'voz' (permissão de envio de mensagens) do utilizador alcunha no canal. + + + +/topic [canal] [mensagem] +Tenta definir o tópico do canal como sendo a mensagem. Quando for introduzido na página de um canal, o canal poderá ser omitido e irá corresponder ao canal activo nesta página. Se a mensagem for omitida, mostra o tópico actual do canal. A alteração do tópico de um canal poderá ser mal-sucedida se não tiver privilégios suficientes. + + + +/away razão +Se alguém lhe tentar enviar uma mensagem privada ou o convidar para um canal, serão notificados de que você está ausente do seu local de trabalho devido à razão. Para voltar a colocar o seu estado no normal, escreva /away sem nenhuma razão. + + + +/aaway razão +Como o comando /away descrito acima, excepto que o comando é enviado para todos os servidores a que se ligou no &konversation;. + + + +/invite alcunha [canal] +Convida o utilizador com o &nickname; alcunha para se ligar ao canal. Este comando é especialmente útil se você só se puder ligar ao canal por convite. Quando for introduzido na página de um canal, o canal poderá ser omitido. + + + +/exec programa [parâmetros] +Executa o programa compatível com o &konversation; chamado programa, passando para ele os parâmetros. Veja a Programação para mais informações sobre como usar e criar estes programas. +Exemplos: + +/exec kdeversion + +Envia os números de versão do &kde; e do &Qt; do seu sistema para o canal. + +/exec cmd uname -a + +Envia o texto da sua versão de &Linux; para o canal. + + + + + +/notify [alcunha] +Adiciona ou remove o utilizador correspondente a alcunha da sua lista de Alcunhas Vigiadas Ligadas. Se o &nickname; já estiver na lista, é removido. Se não estiver, será adicionado. Se a alcunha for omitida, mostra a lista actual de &nickname;s vigiados. + + + + +/prefs [list|group] [list|option] [valor] +Mostra ou altera as opções do &konversation; sem usar o ecrã de Configuração. Se um parâmetro contiver espaços, coloque-o entre aspas. + +Exemplos: + +/prefs list + +lista os grupos de opções disponíveis. + +/prefs "General Options" list + +lista as opções disponíveis no grupo General Options (Opções Gerais) com os seus valores actuais + +/prefs "General Options" ShowTrayIcon + +Mostra o valor actual da opção para mostrar o ícone do &konversation; na bandeja do sistema. + +/prefs "General Options" ShowTrayIcon false + +Desliga o ícone do &konversation; na bandeja do sistema. + + + + +/kick alcunha razão +Quando for introduzido na página de um canal, tenta expulsar o utilizador com o &nickname; alcunha do canal com a explicação na razão. Se a razão não for indicada, é usada a razão definida na Configuração da Identidade. Este comando só poderá ser usado na página de um canal. + + + +/ban [-host|-domain| -userhost|-userdomain] [canal] utilizador|máscara +Tenta banir o utilizador ou os utilizadores correspondentes à máscara do canal. Quando for introduzido na página de um canal, o canal poderá ser omitido. Para mais informações sobre as máquinas, domínios e máscaras, leia por favor os documentos em irchelp.org. Para obter a lista de utilizadores banidos de um canal, introduza o comando /mode canal b. + + + +/unban [canal] padrão +Anula uma expulsão de um ou mais utilizadores de um canal. Quando o comando for introduzido na página de um canal, o canal poderá ser omitido. + + + +/ignore [-all] utilizador +Adiciona o utilizador alcunha à sua lista de utilizadores ignorados. Poderá indicar mais do que um &nickname; separado por espaços. As mensagens do canal dos utilizadores na sua lista para Ignorar não aparecem de todo. Para além disso, se indicar -all, todos os tipos de mensagens (pesquisas, avisos, &CTCP;, DCC e Excepções) do utilizador serão ignoradas, assim como as mensagens do canal. + + + +/quote comando +Envia o comando para o utilizador. + + + +/say mensagem +Quando for introduzido na página de um canal, envia a mensagem para o canal. Isto é o mesmo que introduzir a mensagem na Linha de Entrada do canal. É útil para enviar comandos de &irc; quando não desejar executar o comando. Dois caracteres de comando (//) numa linha fazem o mesmo que o /say. Também é usado pelos programas para enviar mensagens. + + + +/raw [open|close] +Coloca o servidor no modo em bruto (open) ou retira-o deste modo (close). Se nem o open nem o close forem passados, é usado por omissão o open. No modo em bruto, o registo mostra todas as mensagens recebidas do servidor no formato nativo do &irc;. + + + +/konsole +Abre uma nova página com um &konsole; do &kde;. + + + +/server [url] [senha] +Liga-se ao servidor no endereço url. Se o url for omitido, liga-se ao servidor associado com a página onde introduziu o comando. Isto é útil para se voltar a ligar a um servidor quando se tiver desligado. Se o servidor precisar de uma senha para se ligar a ele, indique-a com o parâmetro senha. Se o servidor necessitar de um número de porto que não o predefinido (6667), indique o url da seguinte forma: irc.kde.org:6665. + + + +/dcc SEND utilizador [ficheiro] +Envia o ficheiro para o utilizador com o &nickname; alcunha. Se o ficheiro for omitido, aparece-lhe uma janela para você seleccionar um ficheiro. + + + +/dcc +Abre uma página de Estado DCC. + + + +/ctcp alcunha|canal ping +Envia uma mensagem de PING para a alcunha ou para o canal. Isto é útil para determinar se alguém com quem você está a falar está com uma carga elevada na rede, ou (quando for enviado para um canal) se o seu próprio sistema está com uma carga elevada. + + + +/ctcp alcunha|canal mensagem +Envia uma mensagem para o utilizador alcunha ou para todos os utilizadores do canal. Isto é semelhante ao comando /msg, excepto que a mensagem é enviada através do protocolo &CTCP;. A resposta do outro lado depende do programa cliente de &irc; que o utilizador estiver a executar. Por exemplo, ao conversar com outro utilizador do &konversation;, o /ctcp Portugal TIME irá devolver a hora do sistema no computador do Portugal. O /ctcp Portugal VERSION irá devolver o número de versão do &konversation; no computador do Portugal. + + + + + + + + + + +Programação + +O &konversation; vem com alguns programas úteis que poderá executar na aplicação. Para executar um programa, escreva um comando numa página de um canal, pesquisa, DCC ou do servidor com o seguinte formato + +/exec programa [parâmetros] + +o qual executa a aplicação chamada programa, fornecendo-lhe os parâmetros (opcionalmente). + +Por exemplo, escreva o seguinte comando numa página de um canal + +/exec kdeversion + +para enviar as versões do &kde; e do &Qt; para o canal. + +/exec cmd uname -a + +executa o programa comando, passando a ele o uname -a. Isto devolve o texto da versão do seu sistema &Linux; para o canal. + +Para obter uma lista com todos os programas disponíveis, indique o comando seguinte num ecrã do &konsole;. + +ls $KDEDIR/share/apps/konversation/scripts + +Você poderá criar os seus próprios programas. Estes são programas simples da consola e poderão ser feitos em qualquer linguagem de linha de comandos, como a 'bash', o 'perl' ou o 'python'. Quando o &konversation; executa um programa, os três primeiros parâmetros passados a ele são: + + + +O número de porto do servidor de &irc; onde o comando /exec foi executado. + + +O endereço do servidor. + +O nome do canal. + + + +Aqui está um programa de exemplo de linha de comandos (comando). + + +#!/bin/sh + +# Executa um comando e envia o resultado para o Konversation. + +PORTO=$1; +SERVIDOR=$2; +DESTINO=$3; +shift;shift;shift; + +$@ | while read linha; do dcop $PORT Konversation say $SERVIDOR "$DESTINO" "$@: $linha"; done + + + +Repare que o programa usa o &DCOP; para comunicar com o &konversation;. O comando say faz com que o resultado seja enviado para o canal como uma mensagem normal. Para mostrar algo na página sem o enviar para os outros utilizadores, use o info em alternativa. Veja os programa existentes para aprender mais exemplos de programação. + +Para ser capaz de executar um programa que tenha criado, precisa de o instalar, copiando-o para tal para $KDEDIR/share/apps/konversation/scripts ou para $HOME/.kde/share/apps/konversation/scripts. Precisa também de ceder permissões de execução ao ficheiro, por exemplo com um chmod a+x programa. + + + + + + + + +Referência de Comandos + + + + + + +A janela principal do &konversation; + + +O Menu Ficheiro + + + + F2 Ficheiro Lista de Servidores + Mostra a lista dos servidores e dos canais. + + + F7 Ficheiro Ligação Rápida + Mostra o ecrã de Ligação Rápida para se ligar a um servidor. + + + File Ligar de Novo + Liga-se de novo a todos os servidores que se desligaram devido a um erro na rede ou a outro problema qualquer. + + + &Ctrl;J Ficheiro Juntar ao Canal + Mostra uma janela onde o utilizador poderá introduzir o nome de um canal onde se ligar. Faz o mesmo que se introduzir o comando /join #nome_canal na página de um canal ou de um servidor. + + + &Alt; &Ctrl;Q Ficheiro Pôr como Ausente Globalmente + Muda o estado da sua &nickname;, para ausente em todos os canais. + + + &Ctrl;Q Ficheiro Sair + Sai do &konversation; + + + + + + +O Menu <guimenu +>Editar</guimenu +> + + + + &Ctrl;F Editar Procurar + + Procura por uma determinada sequência de texto no ecrã actual. + + + + F3 Editar Procurar Seguinte + + Procura de novo por uma determinada sequência de texto no ecrã actual, usando o texto da pesquisa anterior. + + + + &Ctrl;L Editar Limpar a Janela + + Limpa o ecrã actual. + + + + &Ctrl; &Shift;L Editar Limpar Todas as Janelas + + Limpa todos os ecrãs. + + + + + + + +O Menu <guimenu +>Inserir</guimenu +> + + + + &Ctrl;K Inserir Cor do &irc; + + Veja a secção para Enviar mensagens coloridas. + + + + &Ctrl;R Inserir Linha de Recordação + + Veja a Marcação dos Canais e dos Registos das Pesquisas. + + + + &Alt; &Shift;C Inserir Carácter Especial + + É usado para introduzir caracteres especiais, como os caracteres estrangeiros. + + + + + + + +O Menu <guimenu +>Favoritos</guimenu +> + + + + &Ctrl;B Favoritos Adicionar aos Favoritos + + Coloca a rede & canal actuais num Favorito + + + + Favoritos Editar os Favoritos + + Abre o editor de favoritos + + + + Favoritos Nova Pasta de Favoritos + + Cria uma nova pasta de favoritos + + + + + + + +O Menu <guimenu +>Configuração</guimenu +> + + + + &Ctrl;M Configuração Esconder o Menu + + Esconde o menu principal. Carregue em &Ctrl;M para o mostrar de novo. + + + + Configuração Esconder a Barra de Ferramentas + + Esconde a barra de ferramentas. + + + + Configuração Esconder a Barra de Estado + + Esconde a barra de estado no fundo do ecrã principal. + + + + Configuração Identidades + Mostra o ecrã de Identidades para configurar a sua informação de identificação. + + + Configuração Configurar os Atalhos + + Permite-lhe alterar os atalhos de teclado do &konversation;. + + + + Configuração Configurar as Barras de Ferramentas + + Permite-lhe adicionar ou remover os botões da barra de ferramentas do &konversation;. + + + + Configuração Configurar as Notificações + + Mostra o ecrã de Configuração das Notificações. + + + + Configuração Configurar o &konversation; + + Mostra o ecrã para Editar as Preferências. + + + + + + + +O Menu <guimenu +>Janela</guimenu +> + + + + &Ctrl;. Janela Página Anterior + + Mostra o ecrã correspondente à página anterior. + + + + &Ctrl;, Janela Página Seguinte + + Mostra o ecrã correspondente à página seguinte. + + + + &Ctrl;W Janela Fechar a Página + + Fecha o ecrã actual. Se fechar um canal, irá sair dele. Se fechar uma página de Mensagens do Servidor, irá fechar todos os canais abertos nesse servidor e desligar-se-á dele. + + + + F11 Janela Fechar Todas as Pesquisas Abertas + + Fecha todas as conversas privadas (pesquisas). + + + + &Ctrl;H Janela Esconder a Lista de Alcunhas + + Esconde (ou mostra) o painel de &nickname;s nas páginas dos canais. + + + + F4 Janela Alcunhas Vigiadas Ligadas + + Mostra o ecrã das Alcunhas Vigiadas Ligadas. Veja a secção para Monitorizar quem está ligado. + + + + F5 Janela Lista de Canais + + Mostra uma lista dos canais que estão disponíveis no servidor. + + + + F6 Janela Extractor de &url; + + Mostra o ecrã com o Extractor de &url;. + + + + Janela Nova Konsole + + Mostra um ecrã de terminal. Poderá abrir tantas páginas do Konsole quantas desejar. + + + + &Ctrl;O Janela Abrir o Registo + + Abre um ecrã com o registo das mensagens da página actual. Só funciona para as páginas de Canais e Mensagens do Servidor. O registo precisa de estar activo na página de Configuração Configurar o Konversation Comportamento do menu principal. + + + + + + + +O Menu <guimenu +>Ajuda</guimenu +> +&help.menu.documentation; + + + + + + + +Perguntas e Respostas +&reporting.bugs; &updating.documentation; + + + +Quando inicio o &konversation;, gostaria de me ligar a um servidor sem me juntar a nenhum canal. Como é que eu faço isso? + + +No ecrã para Editar o Servidor, deixe a área de Canais em branco. + + + + + +O &konversation; não se liga a nenhuns servidores. O que se passa de errado ? + + +Existem várias coisas que poderão correr mal. + + +Certifique-se que introduziu o Nome do servidor e Porto correctos no ecrã para Adicionar um Servidor. + + +Verifique o resultado no ecrã das Mensagens do Servidor à procura de mensagens de erro. Será que o servidor rejeitou a ligação devido a uma senha errada? Será que o servidor rejeitou a ligação porque necessita do IDENTD e o seu computador não respondeu ao pedido de IDENT? Será que assinalou a opção do protocolo SSL mas o servidor não o suporta? + + +Se estiver por detrás de uma 'firewall', garanta que os seguintes portos estão activos. O &konversation; precisa de ter activos os seguintes portos: + + + +Saída para o 6667 em TCP (ou o porto do servidor a que está a ligar) +Entrada para o 113 em TCP (se o servidor necessitar do IDENTD) + + + + +Para mais informações sobre os problemas de ligações de IRC, veja em irchelp.org. + + + + + + + + + +Quando vou ao item Janela Lista de Canais , não o consigo seleccionar. Porquê? + + +O item de menu Janelas Lista de Canais fica inactivo se estiver actualmente a ver uma página não de canal, por exemplo a de Alcunhas Vigiadas Ligadas. Para o voltar a tornar seleccionável, volte para uma página de canal ou de servidor. + + + + + + + + + + +Créditos e Licença + +&konversation; +Programa copyright 2002-2005 pela equipa do &konversation;. +&konviwebsite; + +Contribuições: +Dario Abatianni eisfuchs@tigress.com +Peter Simonsson psn@linux.se +Christian Muehlhaeuser chris@chris.de +John Tapsel john@geola.geo.uk +Ismail Donmez ismail.donmez@boun.edu.tr +Shintaro Matsuoka shin@shoegazed.org +Gary Cramblitt garycramblitt@comcast.net +Matthias Gierlings gismore@users.sourceforge.net +&Alex.Zepeda; garbanzo@hooked.net +Stanislav Karchebny berkus@users.sourceforge.net +Mickael Marchand marchand@kde.org + + + +Agradecimentos a: +Michael Goettsche michael.goettsche@kdemail.net +Benjamin Meyer ben+konversation@kdemail.net +Jacub Stachowski qbast@go2.pl +Sabastian Sariego segfault@kde.cl +Olivier Bedard www.konversation.org hosting +Frauke Oster frauke@frsv.de +Lucijan Busch lucijan@kde.org +Sascha Cunz mail@sacu.de +Steve Wollkind steve@njord.org +Thomas Nagy thomas.nagy@eleve.emn.fr +Tobias Olry tobias.olry@web.de +Ruud Nabben r.nabben@gawab.com + + + +Documentação Copyright © 2003-2005 Gary R. Cramblitt garycramblitt@comcast.net + +Tradução de José Nuno Pires jncp@netcabo.pt +&underFDL; &underGPL; + + +Instalação + + + + +Como obter o &konversation; +&install.intro.documentation; As últimas versões do &konversation;, incluindo o código-fonte e as instruções de compilação, poderão ser obtidas na página Web em &konviwebsite;. + + + + + + +Requisitos + + + +Para poder usar com sucesso o &konversation;, necessita do &kde; 3.2 ou posterior e uma ligação de rede. Nas versões anteriores do &kde; poderão faltar algumas funcionalidades. Se estiver a executar o &konversation; por detrás de uma 'firewall', veja as Perguntas e Respostas. Se desejar utilizar o protocolo SSL pode necessitar do OpenSSL. + + + + +&documentation.index; +
+ + diff --git a/doc/ru/Makefile.am b/doc/ru/Makefile.am new file mode 100644 index 0000000..91a7703 --- /dev/null +++ b/doc/ru/Makefile.am @@ -0,0 +1,2 @@ +KDE_LANG = ru +KDE_DOCS = konversation diff --git a/doc/ru/index.docbook b/doc/ru/index.docbook new file mode 100644 index 0000000..caa0cf5 --- /dev/null +++ b/doc/ru/index.docbook @@ -0,0 +1,5961 @@ + + + Konversation"> + + + IRC"> + CTCP"> + nickname"> + Nickname"> + LED"> + OSD"> + URL"> + MIME"> + + + + + + +]> + + + + + + + + + + + + +Руководство по &kmyapplication; + + + Gary R. Cramblitt garycramblitt@comcast.net +ВладимирРычков
vvgtr2@mail.ru
Перевод на русский
СергейНовгородов
ximen@tsu.tmb.ru
Перевод на русский
АлексейОпарин
opaleksej@yandex.ru
Перевод на русский
+
+ + + + +2003-2005 +Gary R. Cramblitt + + + + +&FDLNotice; + + + +2005-05-23 +0.18 + + + + +&kmyapplication; - это &irc;-клиент для KDE с дружественныминтерфейсом. + + + + + +KDE +kdeextragear-2 +Konversation +irc +internet relay chat +chat +communications + + +
+ + + + + + +Введение + + + +&kmyapplication; - это &irc;-клиент для KDE 3.2 и выше. Он предоставляет следующие возможности: + + + +Поддержка SSL. +Дружественный интерфейс. +Настраиваемые Быстрые кнопки для часто используемых команд +Автоматическое возобновление подключения и вход в чат. +Отправка и приём DCC. +Наблюдение за статусом пользователей. +Визуальные и звуковые уведомления для широкого спектра событий, таких как упоминание вашего ника в сообщениях, вход/выход пользователя, входящего в ваш список наблюдения. +Настраиваемая подсветка ников и других регулярных выражений в сообщениях. +Автодополнение ников. +Захват и сохранение всех &URL;, появляющихся в сообщениях. +Вывод сообщений на экран даже при свёрнутом окне. +Список игнорируемых ников. +Автоматическое ведение журнала и управление им. +Пометка строк в журналах. +Поддержка сценариев. +Интеграция с &kaddressbook;. + + + +Веб-сайт &kmyapplication; расположен по адресу: &konviwebsite;. Вопросы и ответы по &kmyapplication; можно просмотреть в рассылке для пользователей &kmyapplication;. Пожалуйста, подпишитесь на неё, чтобы узнать о новых возможностях, обнаруженных ошибках и т.д. Чтобы узнавать о новых версиях, вы можете подписаться на рассылку &kmyapplication;-Анонс. Эта рассылка используется только для объявлений о новых версиях и исправлениях. + +С разработчиками &kmyapplication; можно связаться через &irc; на канале irc.kde.org #konversation. + + + + +Использование &kmyapplication; + + + + +Если вы новичок в &irc;... + +Попросту говоря, &irc; - это протокол для онлайн-общения, определяемый официальными стандартами, способный отнять много часов вашей жизни. Чтобы воспользоваться &irc;, вы должны сначала подключиться к серверу, после чего зайти на канал (аналог комнаты в чате) или просто вступить в двусторонние переговоры. + +Чтобы подключиться к серверу и каналу, откройте &kmyapplication;. Появится окно Список серверов. + + + +Список серверов + + + + + + + + + + + + + Список серверов + + + + + + + +Здесь показан список настроенных &irc; Сетей. Сеть &irc; - это множество совместно работающих серверов, и чтобы подключиться к ней - достаточно войти на один сервер. Однажды подключившись, &kmyapplication; будет автоматически входить на отображаемые Каналы. При первом запуске в &kmyapplication; для вас уже настроены сеть Freenode и канал #kde. Чтобы выделить сеть, щёлкните на ней мышью. +Нажмите здесь, чтобы определить новую Сеть, включая сервер и Каналы для автоматического входа при подключении. Подробнее об этом написано в разделе Определение новых сетей, серверов и каналов для автоматического входа. +Нажмите сюда, чтобы подключиться к выбранной &irc;-сети и каналу. + + + + +Когда вы нажмете кнопку Подключиться при первом запуске &kmyapplication;, возможна выдача сообщения о том, что ваш Профиль по умолчанию неправильно настроен. + + + + Проверка профилей + + + + + + Проверка профилей + + + + + +При первом запуске &kmyapplication; получает информацию о текущем пользователе от операционной системы и заполняет поля профиля автоматически. Если информация в системе неполна (например, не введено Полное имя), вы увидите вышеупомянутое сообщение. Для решения этой проблемы нажмите OK и посмотрите раздел Настройка вашего профиля. + + +Появится Главное окно, отображающее сообщения, отправляемые сервером клиенту (если &kmyapplication; не подключается к серверу, смотрите Вопросы и ответы). Когда сообщения сервера перестанут появляться, &kmyapplication; подключится к выбранному каналу или каналам. + + + +Канал. + + + + + + + + + + + + + Канал + + + + + + + + +Это называется Строка ввода. Чтобы послать сообщение на канале, наберите его в этой строке и нажмите &Enter;. Ваше сообщение, как и сообщения всех остальных, появляются в окне канала. Каждому сообщению предшествует время и ник пользователя. + +Вы можете войти на дополнительные серверы и каналы. Каждый сервер, канал, список каналов и другие окна получают здесь по отдельной вкладке. Чтобы просмотреть список доступных каналов, смотрите Список доступных каналов. Чтобы зайти на канал, наберите /join #имя_канала в Строке ввода (# вводить обязательно.) Также можно использовать /j как сокращение от /join. Чтобы покинуть канал, наберите /part. Чтобы перейти к другому серверу или каналу, щёлкните на соответствующей вкладке. + +Это называется Панель пользователей. Здесь отображаются ники всех пользователи, вошедших на канал, включая ваш. + + + + +Это основные понятия. Более подробные сведения приведены в... + + + + + + +Настройка вашего профиля + +Перед тем, как начать регулярно использовать &kmyapplication; - выберите себе сетевое имя. + +Выберите НастройкаПрофили в главном меню. Появится окно Профили. Открыть это окно можно также нажатием кнопки Изменить в диалоге Добавить сеть. + + + +Профили (основная вкладка) + + + + + + + + + + + + + + + + + Профили (основная вкладка) + + + + + + + +Щёлкните здесь, чтобы выбрать Профиль для редактирования. +Используйте эти кнопки, чтобы добавить, дублировать, переименовать или удалить Профиль. +Введите здесь ваше подлинное имя. &irc; не сможет скрыть вас от друзей и врагов. Имейте это в виду, если решите кому-нибудь навредить. Конечно, фальшивое "подлинное имя" может замаскировать ваш пол, но используемый вами компьютер всё равно можно отследить, поэтому вам не удастся быть истинно анонимным. +Используйте эти кнопки чтобы Добавить, Изменить или Удалить ник. +Это ваш список ников. Ник - это имя, по которому вас будут узнавать другие пользователи. Вы можете использовать любое имя, какое вам понравится, но первым символом должна быть буква. Остальными символами могут быть буквы, цифры или специальные символы: -[]\`_^{}|. + +Так как ник должен быть уникальным во всей &irc; сети, имя, которое вы выбрали, может быть отвергнуто сервером из-за того, что кто-то уже использует его. Для этого и нужны альтернативные имена. Если первый выбранный вами ник отвергнут сервером, &kmyapplication; будет пытаться использовать другие имена из списка по порядку. + +В соответствии с RFC 2812, максимальная длина имени - 9 символов, но на самом деле она определяется сервером. Чтобы определить максимальную длину, поддерживаемую сервером, подключитесь к нему. На вкладке Server Messages найдите сообщение [Support]. Например + + +[18:51] *Eisfuchs* [21:45] [Support] Eisfuchs MODES=4 MAXCHANNELS=20 NICKLEN=16 USERLEN=10 HOSTLEN=63 TOPICLEN=450 KICKLEN=450 CHANNELLEN=30 KEYLEN=23 CHANTYPES=# PREFIX=@+ CASEMAPPING=ascii CAPAB IRCD=dancer + + +Параметр NICKLEN определяет максимальную длину имени. + + +Используйте эти кнопки для смены порядка (а значит, и приоритета) имён. Первым пробуется верхнее, затем следующее и т.д. +Если вы зарегистрировали ваше имя в сети &irc;, введите сервис и пароль, чтобы удостоверить его подлинность. Когда &kmyapplication; подключается к серверу, она автоматически будет посылать /msg сервис IDENTIFY пароль. Если вы не знаете, что это такое, оставьте эти поля пустыми. + + + + + +Щёлкните на вкладке Отсутствие. + + + + Профили (вкладка Отсутствие) + + + + + + + + + + + + + Профили (вкладка Отсутствие) + + + + + + + +Введите имя, которое будет показывать, что вы отсутствуете. При выполнении команды /awayсообщение на любом канале, &kmyapplication;, используя этот Профиль, будет автоматически менять ваш ник на ник, веденный в поле Ник во время отсутствия. Это позволяет сообщить другим пользователям, что вы отошли от компьютера. Если вы выполните команду /away на любом канале, где вы уже отсутствуете, &kmyapplication; автоматически заменит ваш ник на оригинальный. Если вы не хотите автоматически менять ник, когда уходите - оставьте поле пустым. +Если вы снимете этот флажок, каждый раз при выполнении команды /away на канале будет появляться горизонтальная линия, отмечая место, с которого вы отсутствуете. Другие пользователи &irc; эту линию не видят. +Если вы установите этот флажок, &kmyapplication; будет автоматически посылать Сообщение об отсутствии на все каналы, к которым вы подключены под этим Профилем. %s заменяется текстом сообщения. Если вы выполните команду /away, Сообщение о возвращении появится на всех каналах, к которым вы подключены под этим Профилем. + +Многие считают сообщения об отсутствии надоедливыми. Используйте этот параметр осторожно, с учётом мнения других пользователей &irc;. + + + + + + +Перейдите на вкладку Дополнительно. + + + + Профили (вкладка Дополнительно) + + + + + + + + + + + + + + + + Профили (вкладка Дополнительно) + + + + + + + +Здесь вы можете ввести команду, которая будет выполняться перед подключением к серверу. Если этот профиль используется для нескольких серверов, то команда будет выполнена для каждого их них. +Этот параметр определяет кодировку и отображение отправляемых на сервер сообщений. При первом запуске &kmyapplication; автоматически получает эти настройки от операционной системы. Если у вас проблемы с отображением сообщений других пользователей, попробуйте изменить этот параметр. +Когда вы подключаетесь, множество серверов запрашивают ваш компьютер для получения ответа IDENT. Если на вашем компьютере не запущен IDENT-сервер, этот ответ посылает &kmyapplication;. Пробелы не разрешены. Рекомендуется использовать ваше имя. +Это сообщение отправляется на канал, когда вы его покидаете. +Это сообщение отправляется на канал, если вас с него выгнали (обычно это делает оператор &irc;). +Нажмите, чтобы применить изменения. Чтобы все изменения вступили в силу, вам нужно отключиться от сервера и подключиться заново. Простейший способ сделать это - перезапустить &kmyapplication;. + + + + + + + + + + +Настройка новых сетей, серверов и каналов для автоматического входа + +Окно Список серверов появляется при запуске &kmyapplication; или при выборе ФайлСписок серверов в главном меню. Окно Список серверов отображает существующие настроенные вами &irc; Сети. Сеть &irc; - это группа совместно работающих серверов. Подключившись к любому серверу какой-либо сети, вы получаете доступ ко всем её каналам. Примеры &irc; сетей - Freenode и Undernet. + + + + Список серверов + + + + + + + + + + + + + + Список серверов + + + + + + + +Здесь показаны существующие настроенные вами Сети вместе с Профилями, используемыми для подключения к сети, и Каналами, на которые осуществляется автоматический вход при подключении. Организованные вами группы сетей будут выделяться отступами. Выделить сеть можно мышью. +Используйте эти кнопки, чтобы Добавить новую сеть, Изменить или Удалить выделенную. +Нажмите эту кнопку, чтобы подключиться к выбранной Сети и закрыть окно Список серверов. Вы можете выделить сразу несколько сетей, к которым будет производиться подключение. +Нажатие этой кнопки не отменяет сделанных изменений, просто в данный момент вы не хотите подключаться ни к одной из сетей. + + + + + +При нажатии кнопки Добавить появится окно Добавить сеть. + + + + Добавить сеть + + + + + + + + + + + + + + + + + + + Добавить сеть + + + + + + + +Введите имя сети. Вы можете создать столько записей в Списке серверов для одной и той же Сети, сколько пожелаете. +Дополнительно. Если вы введёте здесь что-нибудь, все Сети одной Группы будут показаны вместе в окне Список серверов. +Выберите существующий Профиль или нажмите кнопку Изменить, чтобы добавить новый профиль или отредактировать существующий. Профиль отождествляется с вами и будет определять ваш ник в то время, когда вы подключены к сети. +Дополнительно. Эта команда будет передана на сервер после подключения. Например: /msg NickServ IDENTIFY konvirocks. Это пример для сети freenode, которая требует от пользователей регистрации их ников и паролей. konvirocks - это пароль для имени, указанного в Профиле. Вы можете ввести несколько команд, разделяя их точкой с запятой. +Установите этот флажок, если хотите, чтобы &kmyapplication; автоматически подключался к этой сети при каждом запуске. +Это список &irc;-серверов. Для подключения к сети &kmyapplication; будет последовательно, сверху вниз, перебирать серверы из списка (в списке должен быть указан как минимум один). Выделить сервер можно мышью. +Используйте эти кнопки, чтобы Добавить cервер, Изменить или Удалить выделенный сервер. Можно изменить порядок серверов в списке и, следовательно, порядок попыток подключения. +Дополнительно. Это список каналов, на которые &kmyapplication; будет автоматически входить при подключении к серверу. Можете оставить незаполненным, если вам это не нужно. +Используйте эти кнопки, чтобы Добавить канал, Изменить или Удалить выбранный канал. Можно изменить порядок подключения каналов. + + + +Старайтесь не смешивать серверы из различных &irc;-сетей в одной Сети. Избегайте указания одних и тех же серверов в различных Сетях, иначе в &kmyapplication; не будут работать интеграция с адресной книгой и наблюдение за никами в сети. + + + + +При нажатии кнопки Добавить в рамке Серверы, появляется окно добавления сервера. + + + + Добавить сервер + + + + + + + + + + + + + + Добавить сервер + + + + + + + +Имя или IP адрес сервера. На irchelp.org можно найти список серверов. +Введите номер порта для подключения к серверу. Для большинства серверов - 6667. +Если сервер требует пароля для подключения - введите его здесь, иначе - оставьте незаполненным. +Отметьте, если вы хотите использовать протокол SSL для общения с сервером. Это сохранит конфиденциальность сообщений между вашим компьютером и &irc;-сервером, но для этого сервер должен поддерживать протокол SSL. В большинстве случаев, если сервер не поддерживает SSL, соединения не произойдёт. + + + + + +При нажатии кнопки Добавить в рамке Каналы для автоматического подключения появляется окно Добавить канал. + + + + Добавить канал + + + + + + Добавить канал + + + + + +Введите имя канала. Не забудьте поставить # перед именем. Если канал требует пароль для подключения - введите его здесь, иначе - оставьте незаполненным. + + + + + + +Список доступных каналов + +Чтобы просмотреть список доступных каналов, выберите Окна Список каналов в главном меню. После вывода предупреждения будет создана новая вкладка под названием Список каналов. + + + +Вкладка Список каналов. + + + + + + + + + + + + + + + + Вкладка Список каналов. + + + + + + + + +Введите здесь строку фильтра. + +Вы можете фильтровать список каналов по количеству пользователей на них. Установка значения 0 отключает критерий. + +Щёлкните здесь, чтобы получить список каналов с сервера и применить фильтр. + +Здесь отображается отфильтрованный список каналов. Заметьте, если вы не использовали регулярные выражения, &kmyapplication; покажет все каналы, содержащие в названиях строку фильтра, а не только те, названия которых начинаются с этой строки. + +Выберите канал, на который вы хотите зайти, щелчком по нему. Щелчок правой кнопкой на канале выдаёт список всех веб-адресов, упомянутых в теме канала. + +Щёлкните здесь, чтобы войти на канал. Для него будет создана новая вкладка. + + + + +Следует избегать нажатия кнопки Обновитьсписок. Большинство серверов работают с тысячами каналов, обновления сильно загружают их и могут занимать до нескольких минут, в зависимости от пропускной способности сети. Если ваш клиент слишком медленный, сервер может даже отключить вас. + +Иногда на серверах бывают "секретные" каналы. Они не отображаются в Списке каналов, но, если знать названия, входить на них можно. В любой Строке ввода введите /join #имя_канала (# обязательно). Для канала будет выделена новая вкладка. Если вы вошли на канал, а в Панели пользователей красуется только ваш ник - это значит, что канал до этого не существовал. В таком случае вы, должно быть, захотите закрыть канал, набрав /part. + + + + + + +Тур по главному экрану + +Давайте подробнее рассмотрим Главноеокно. Вот так оно выглядит при выделенной вкладке каналов. + + + +Главное окно. + + + + + + + + + + + + + + + + + + + Главное окно + + + + + + + + +Это называется Строка ввода. Она становится доступной, если выделена вкладка канала. Отправить сообщение всем пользователям этого канала можно, набрав сообщение здесь и нажав &Enter;. Ваше сообщение, как и все остальные, появится в окне канала. В начале каждого сообщения указано время отправки и &nickname; отправителя. + + Можно вставлять и текст из буфера обмена. Если вставляемый текст будет содержит более одной строки -- открывается диалог. Отредактируйте текст и нажмите кнопку ОК. + + Если вставленный из буфера обмена текст окажется длиннее 256 символов (или содержит более одной строки), то появится предупреждение. Слишком большие сообщения могут повлечь за собой сброс соединения.Вы можете продолжать ввод, но это не очень хорошая идея, так как флуд (захламление канала большим числом сообщений) может помешать общению других пользователей, и вы будете отключены от сервера. Поэтому лучше отправлять сообщения небольшими частями. + + + + На большинстве каналов существует соглашение о том, что сообщение, адресованое одному конкретному пользователю, должно начинаться с его &nickname;. &kmyapplication; имеет очень удобную функцию автозавершения &nickname; пользователя. Начните набирать &nickname; и нажмите клавишу Tab. &kmyapplication; допишет за вас оставшуюся часть &nickname;. Настроить автозавершение можно в меню. Выберите НастройкаНастроить Konversation, разверните Поведение. НажмитеОбщие и установите флажок Режим автозавершения. + + В строке ввода вы можете набирать и команды &irc;, для этого набирайте: +/ &irc;-команда +Наиболее часто используемые команды &irc;. Некоторые серверы поддерживают команду /help, выводящую список доступных команд, или даже /help команда -- для описания конкретной команды. + + + +Вы можете войти на дополнительные серверы и каналы. Каждый сервер и канал получает отдельную вкладку. Для просмотра списка доступных каналов см. Список доступных каналов. Чтобы зайти на канал, наберите /join #имя_канала в Строке ввода (# вводить обязательно). Также можно использовать /j как сокращение от /join. Для выхода с канала, наберите /part. Кроме того, отдельные вкладки открываются для списка каналов, участия вдвусторонних переговорах, Охотника за &URL; и терминальных сеансов. Для перехода по вкладкам можно использовать как кнопки, так и колёсико мыши. + +Для задания других параметров вкладок, выберите Настройка Настроить Konversation в главном меню. Перейдите в Поведение, затем Общие. + + + +Этот индикатор мигает, когда на вкладке есть что-то новое. Если это сообщения вроде join, part,quit или изменение ников, то индикатор мигает медленно. Мигание учащается при появлении новых обычных сообщений. Цвета могут быть такие: + + Канал + + + Сообщения сервера,Список каналов или Охотник за &URL; + + + Консоль или статус DCC. + + + Частное сообщение (на очереди). + + + + +Нажмите здесь, чтобы закрыть текущую вкладку. Закрыв вкладку Канал, вы автоматически покинете канал. Закрыв Сообщения сервера, вы: +-- покинете все каналы к которым присоединились; +-- закроете все запросы; +-- отключитесь от сервера. + +Эта кнопка позволяет изменить ваш &nickname;. Доступна, только если текущая вкладка является вкладкой канала. Чтобы спрятать эту кнопку, выберите в главном меню НастройкаНастроить Konversation. Разверните вкладку Внешний вид, нажмите Окно чата и снимите флажокПоказывать кнопку изменения псевдонима. + +Здесь отображается тема канала. Подведя к названию темы курсор мыши, вы увидите полный текст темы. Нажимая кнопку слева от названия темы, вы можете редактировать название. Скрыть тему канала можно, выбрав в главном меню Настройки Настроить Konversation . Развернуть Внешний вид, Окно чата и снять флажок Отображать тему канала. + +Эти кнопки отображают текущее состояние режимов канала. Если кнопка нажата--значит, режим включен. Имея достаточно привилегий, вы сможете изменять режимы канала, нажимая эти кнопки или кнопки слева от темы канала. Скрыть кнопки режимов канала можно, выбрав в главном менюНастройки Настроить Konversation. Развернуть Внешний вид и щелкнуть на Окно чата. Снять флажок Показывать кнопки режима канала. + + +Это называется Панель пользователей. Она отображается на вкладках каналов и содержит ники всех пользователей канала, включая и ваш. Наведите курсор на интересующий вас &nickname; и вы получите дополнительную информацию об этом пользователе. Вы можете изменить значок рядом с каждым из &nickname;. Читайте Настройка &nickname; тем для получения более подробной информации. Тема Big Bullets, как видно на экране выше, использует следующие значки: + + + обычный пользователь + + + + пользователь с правом голоса. Может отправлять сообщения в модерируемый канал. + + + + halfop канала, привилегированный пользователь + + + + оператор канала + + + + владелец канала + + + + администратор канала + + + + + +Если пользователь недоступен, то в углу значка появляется маленький красный крест. + +Щёлкните правой кнопкой мыши на имени пользователя для отображения контекстного меню этого &nickname;. Например, можно послать файл этому пользователю. Кроме того, можно связать &nickname; с контактом в адресной книге. + +Скрыть Панель пользователей можно в меню ОкноСпратать список имен. + + + +Это называется Быстрые кнопки. По умолчанию они не видны. Для их отображения существует Настройка быстрых кнопок. Вы можете назначать им любые команды по вашему усмотрению. + + + + +Замечание: вы можете контролировать то, как сообщения выглядят на экране канала и вкладках двусторонних переговоров (приватов). Например, можно изменять цвет сообщений, проигрывать звук при получении сообщения с определенной строкой или автоматически отвечать на сообщения. Подробности смотрите в разделе подсветка сообщений. + +Замечание:названия каналов иногда начинаются с &, + или !. Согласно RFC 2811, первый символ имени определяет тип канала: # - Постоянные каналы. ! - Постоянные каналы. & - Локальные (каналы, к которым можно присоединиться только с того сервера, где работает канал). Все остальные каналы доступны для подключения из сети. + -Каналы, которые не поддерживают режимы канала. Это означает, что все режимы на канале отключены за исключением флага t.. Имена каналов могут достигать длины в 50 символов и содержать любые символы, исключая пробел, запятую и Ctrl-G. + + + + + + +Быстрое подключение + +Иногда хочется подключиться к серверу как можно быстрее, не проходя всю процедуру добавления нового сервера в Список серверов. + +В главном меню выберите ФайлБыстрое подключение. Появится окно Быстрое подключение. + + + +Окно быстрого подключения. + + + + + + Окно быстрого подключения + + + + + +Введите адрес сервера в поле Сервер, ваш &nickname; в поле Псевдоним, нажмите кнопку Подключиться. А когда &kmyapplication; подключится к серверу, введите команду /join #имя_канала -- и вы войдете на канал. + + + + + + +Часто используемые команды &irc; + +Ниже привёден краткий список наиболее часто используемых &irc;-команд. Полный список смотрите на RFC2812 или посетите irchelp.org. Команды, адаптированные специально для &kmyapplication;, смотрите в Команды Konversation + + + + + +/help +Отображает все доступные на сервере команды. Поддерживается не всеми серверами. + + + +/helpкоманда +Выводит помощь для команды. Поддерживается не всеми серверами. + + + +/join#канал +Подключает к #каналу. Если канала с таким именем нет -- он будет создан, и вы станете его оператором. + + + +/part +Отключает вас от текущего канала, соответствующая вкладка закрывается. + + + +/part#канал +Отключает вас от текущего #канала, соответствующая вкладка закрывается. Синоним /leave + + + +/meсообщение +Отправляет на канал сообщение, в начале которого стоит ваш &nickname;. Например если ваш &nickname; Pingvin и сообщение выглядело /me пьёт ароматный чай., то на канале сообщение будет выглядеть так: Pingvin пьёт ароматный чай.. Все пользователи увидят это сообщение (если, конечно, такой тип сообщений не фильтруется). Эти сообщения дают вам возможность передать невербальную информацию, например ваше настроение или то, чем вы сейчас заняты. Но, если вам нужно ненадолго отойти от вашего компьютера, воспользуйтесь лучше командой /away. + + + +/away сообщение +Если кто-нибудь захочет послать вам личное сообщение или пригласить на канал - он увидит, что в данный момент вы отошли от компьютера и оставили ваше сообщение. + + + +/away +Отменяет действие предыдущей команды /awayсообщение. + + + +/queryпсевдоним. +Откроет новую вкладку с псевдонимом пользователя для двустороннего общения, в IRC более известного как Приват. Все, что вводится в этой вкладке, видите только вы и ваш собеседник. + + + +/msg псевдоним сообщение +Отправляет одиночное сообщение пользователю под ником псевдоним. Только пользователь с этим псевдонимом увидит это сообщение. Для более продолжительных переговоров удобно пользоваться командой /query. + + + +/invite псевдоним +Приглашает пользователя с указанным псевдонимом присоединиться к каналу. Команда особенно полезна для тех каналов, на которые можно войти только по приглашению (invite-only). + + + + + + + + + + +Двусторонние разговоры (queries) + +Двусторонние переговоры -- участвуете только вы и ваш собеседник. Такие разговоры в &kmyapplication; называются "queries". Начать приватную беседу можно, набрав команду /query псевдоним в любой строке ввода, где псевдоним -- &nickname; пользователя, с которым вы хотите пообщаться. Также можно нажать правую кнопку мыши на &nickname; пользователя в Панели пользователей и выбрать Начать приват Откроется новая вкладка. Представьтесь, послав сообщение. + +Двусторонние переговоры - те же каналы, с тем отличием, что в них общаетесь только вы с вашим собеседником. + +Чтобы закончить двусторонние переговоры, просто закройте эту вкладку. Однако учтите, что если собеседник снова пошлёт вам сообщение -- вкладка опять откроется. + +Чтобы завершить все двусторонние переговоры, в главном меню выберите ОкноЗакрыть все открытые приваты или просто нажмите клавишу F11. + +Если какой-то пользователь начнет с вами частный разговор - &kmyapplication; создаст новую вкладку с его &nickname;. Но если вы не хотите говорить с этим пользователем -- просто закройте вкладку. + + + + + + +Настройка уведомлений + +Уведомления -- это действия, которые &kmyapplication; будет осуществлять при наступлении при какого-либо события. Допустим, &kmyapplication; работает, но окно свернуто или оказалось спрятано за другими окнами. Если же кто-то захочет срочно связаться с вами или ваш приятель подключится к каналу, вам наверняка захочется узнать об этом. Тут-то и пригодятся уведомления. + +Настройка уведомлений в главном меню: НастройкаНастроить оповещения. Появится окно Настройка уведомлений. + +Сразу же нажмите кнопку Дополнительные параметры. + + + +Окно настройки уведомлещений. + + + + + + + + + + + + + Окно настройки уведомлещений + + + + + + + + +Щёлкните здесь для выбора события. + +Отметьте типы уведомлений при наступлении выбранных событий. (Выделять запись на панели задач -- заставляет запись на панели задач мигать при наступлении события.) + + + + +Отметьте таким образом все интересующие вас события и задайте методы уведомления о них. После этого нажмите кнопку Применить. + + + + +Однажды настроив все увеолмления, вы можете включать и выключать их здесь. Например, при появлении вашего &nickname; в каком-либо сообщении может проигрываться определенный звуковой файл. Когда вы сидите за компьютером, такое звуковое сообщение может не понадобиться, но находясь в той же комнате и не глядя на монитор, вы по звуку сможете узнать о событии. + + + + +Можно настроить &kmyapplication; на выделение вашего псевдонима в чьих-либо сообщениях, используя подсветку. + + + + + + +Наблюдение за подключением пользователей + +&kmyapplication; будет держать вас в курсе того, кто из ваших приятелей подключен к сети &irc;. + +Вы можете установить связи между сетевыми псевдонимами и соответствующими строками вашей адресной книги. После этого &nickname; и &irc;-сеть, к которой подключен &nickname;, будут записаны в вашей адресной книге. &irc;-сеть записыватеся потому, что псевдонимы уникальны только в пределах одной &irc;-сети. Одинаковые псевдонимы в двух разных &irc;-сетях совсем необязательно принадлежат одному и тому же человеку. Но на разных серверах одной и той же &irc;-сети один человек, как правило, имеет одинаковые псевдонимы. + +Именно по этой причине важно использовать одну и ту же Сеть для всех серверов в &irc;-сети, в определении сетей, серверов и автоподключений к каналам. + +Можно указать пользователей, за статусом которых нужно следить, но не находящихся в вашей адресной книге. В этом случае &nickname; тоже будет связан с &irc;-сетью. Смотрите ниже. + +Включение функции наблюдения за &nickname; в главном меню: Окна Подключенные наблюдаемые пользователи. Появится окно Подключенные наблюдаемые пользователи. + + + + Подключенные наблюдаемые пользователи + + + + + + + + + + + + + + + + Подключенные наблюдаемые пользователи + + + + + + + +Список содержит все псевдонимы вашего списка наблюдения и все псевдонимы, связанные с элементами вашей адресной книги. Все псевдонимы связаны с их &irc;-сетями. Если список пуст, то вы не внесли ни одного псевдонима в список или не включили функцию слежения за пользователями (смотрите ниже). Просмотреть все каналы, к которым подключен пользователь можно, развернув &nickname;. Значки рядом с каждым из каналов совпадают с теми, которые появляются в Списке пользователей окна Каналы. +Здесь отображается вся известная информация о &nickname;. Каждые 8 секунд на сервер отправляется команда WHOIS для получения информации обо всех пользователях, находящихся на линии. Это продолжается до тех пор, пока не будут получены сведения обо всех пользователях. +Ники пользователей, не подключенных к &irc;-сети, в которой вы работаете, отображаются в списке Не подключены +Ники, связанные с элементами вашей адресной книги, отмечаются значком (). +Используйте эти кнопки для связывания ника пользователя с элементами вашей адресной книги. Подробнее об этом написано в Справочнике KAddressBook. + + + +Добавить &nickname; в список слежения можно, нажав кнопку Редактировать список наблюдения. Появится диалог Наблюдение за псевдонимами. + + + +Наблюдаемые пользователи + + + + + + + + + + + + + + + Наблюдаемые пользователи + + + + + + + + +Установите этот флажок для активации функции наблюдение за пользователями. + +Чтобы список Подключенные пользователи открывался при запуске &kmyapplication;, установите этот флажок. + +Здесь приведён список пользователей, за статусом которых вы хотите наблюдать. Каждый псевдоним связан с соответствующей &irc;-сетью. + +Нажмите эту кнопку, чтобы добавить пользователя или удалить его из списка. + +Список Подключенные пользователи обновляется путем периодического опроса сервера. Это поле определяет частоту таких запросов. Не вводите значения менее 20 секунд, так как это может привести к перегрузке сервера. + +Дважды щёлкнув на &nickname; пользователя в Списке подключенных пользователей, вы отправите на сервер команду вида %u, где %u будет заменено на &nickname;. Завершать команду необходимо символом %n. + + + + +Закончив редактировать список пользователей, нажмите кнопку ОК. + +Замечание: когда вы откроете Список подключенных пользователей, пройдет ещё некоторое время до появления ников подключенных пользователей, ведь на опрос сервера необходимо некоторое время. Обычно Список подключенных пользователей остается постоянно открытым. + +Во всех каналах &kmyapplication; отображает сообщение о статусе пользователя из вашего Списка наюлюдения. Сообщение выглядит примерно так: + +[17:52] [Notify] psn is online (irc.kde.org). + + + + + + +Подсветка сообщений + +Вы можете управлять отображением сообщений в окнах каналов и приватов. + +Активировать подсветку сообщений можно в главном меню: Настройка Настроить &kmyapplication;. Появится окно Изменить предпочтения. + + + +Экран подстветки + + + + + + + + + + + + + + + + + + + Экран подстветки + + + + + + + + +Щёлкните здесь для выбора экрана Подсветка. +Щёлкните здесь для добавления нового элемента в Список подсветки. Когда элемент в списке выбран -- можно редактировать свойства в панели ниже него. +Введите здесь шаблое строки. Присутствие этого шаблона в любом месте сообщения вызовет его подсветку. Если в вашей системе установлен редактор регулярных выражений KDE, то кнопка справа будет активна. Нажмите на неё, чтобы открыть редактор, он поможет вам создать более сложный шаблон. (Редактор регулярных выражений в KDE -- это часть пакета kdeutils.) +Всё сообщение, содержащее указанный шаблон, будет выделено указанным цветом. +Если вы хотите, &kmyapplication; может проигрывать мелодии при появлении заданного шаблона в каком-либо сообщении. Для выбора файла и проверки звучания нажмите соответствующие кнопки. +Если вы хотите, чтобы при соответствии сообщения заданному шаблону &kmyapplication; автоматически отправляла ответ, введите его здесь. Используйте этот инструмент осторожно, так как вы можете раздражать пользователей &irc; излишними сообщениями. Кроме того, здесь вы можете вводить команды &irc; или &kmyapplication;. +Сбросом этого флажка вы отключите все настроенные звуки. +Установив этот флажок, вы включите автоматическое выделение цветом всех сообщений, содержащих ваш &nickname;. Цвет можете выбрать справа. +По умолчанию подсветка не распространяется на сообщения, написанные вами. Но если вы хотите выделять и их -- установите этот флажок и выберите цвет справа. + + + + + + + + + +Настройка экранного дисплея (&osd;) + +On Screen Display(экранный дисплей)&osd; -- это уникальная функция &kmyapplication;. Со включенным &osd; сообщения из канала будут появляться на вашем рабочем столе, даже если &kmyapplication; свернуто. Здесь вы видите пример работы &osd;. Сообщение в левой верхней части экрана -- это &kmyapplication;, работающее, но в данный момент свернутое до значка в системном лотке. + + + +Пример экранного дисплея + + + + + + Пример экранного дисплея + + + + + +Активировать &osd; можно в главном меню: Настройка Настроить &kmyapplication; . Появится окно Изменить настройки. + + + +Экранный дисплей + + + + + + + + + + + + + + + Экранный дисплей + + + + + + + + +Щёлкните здесь, чтобы развернуть пункт Уведомление + +Щёлкните здесь, чтобы выбрать Экранный дисплей. + +Для активации &osd; установите этот флажок. + +Нажмите эту кнопку, чтобы выбрать шрифт &osd;. (Замечание: работают не все шрифты, но Luxi Sans 22 и Impact 22 проверены). + +Установите соответствующие флажки для выбора типов сообщений, которые хотите видеть на экране, и нажмите кнопку Применить. + + + + + + + + + +Отправка сообщений с окрашенным шрифтом + +Вы можете использовать цвет для отправки сообщения в любой канал. В Строке ввода любого канала начните набирать сообщение. Нажмите Добавить IRC-кнопку цвета, чтобы добавить цвет, или выберите в главном меню ВставитьЦвета IRC. Появится Диалог выбора цвета IRC. + + + +Диалог выбора цвета + + + + + + Диалог выбора цвета + + + + + +Выберите нужный цвет и нажмите ОК. Продолжайте набирать ваше сообщение в Строке ввода. Еще раз сменить цвет можно, нажав кнопку Вставить IRC-цвет. Выберите другой цвет и нажмите ОК. + + + + + + +Настройка тем псевдонимов + +Вы можете изменять значки, отображаемые рядом с &nickname; в Списке пользователей. Для изменения темы отображения &nickname; -- выберите НастройкаНастроить Konversation в главном меню.Появится окно Изменить настройки. Щёлкните Внешний вид, чтобы развернуть его, потом щёлкните Темы -- появится окно Темы. + + + +Окно настройки тем + + + + + + + + + + + + + + Окно настройки тем + + + + + + + + +Щёлкните, чтобы открыть окно Темы псевдонима. +Выберите тему. +Пример значка отображается здесь с учётом выбранной темы. +Если вы откуда-либо загрузили тему отображения псевдонимов, нажмите здесь для её установки. + + + + + + + + + +Настройка быстрых кнопок + +Вы можете включить функцию отображения Быстрых кнопок, и в Главном окне появятся восемь Быстрых кнопок. Включить быстрые кнопки можно, выбрав в главном меню Настройки НастроитьKonversation . Появится окно Изменение настроек. Щёлкните Внешний вид, чтобы развернуть его, затем щёлкните Окно чата. Установите флажокПоказывать быстрые кнопки и нажмите ОК. + +Кнопки можно настроить на исполнение наиболее часто используемых вами команд &irc;. Настроить Быстрые кнопки можно, открыв в главном меню Настройка Настроить Konversation . Появится окно Изменить настройки.. Нажмите Поведение, чтобы развернуть его, затем нажмите Быстрые кнопки для отображения окна Быстрых кнопок. + + + +Окно быстрых кнопок + + + + + + Окно быстрых кнопок + + + + + +Существуют восемь Быстрых кнопок. Выберите пункт в списке для редактирования кнопки. Столбец Название кнопки - это название, которое будет отображаться в Главном окне. Постарайтесь давать кнопкам короткие имена. Колонка Действие кнопки - это действие, происходящее при нажатии Быстрой кнопки. На экране отображаются советы по назначению кнопкам различных действий. + +Нажмите ОК для завершения изменений. + +Пример: + + + + + Название кнопки: Сбщ + + Действие кнопки:Сообщение %u (после %u стоит пробел) + + + + + +Чтобы использовать эту кнопку в Главном окне, щёлкните на &nickname; в Панели имен, затем нажмите кнопку. В Строке ввода появится /MSG , а после него -- выбранный &nickname;. Наберите сообщение, которое вы хотите послать этому пользователю, и нажмите &Enter;. Сообщение будет отправлено, и получит его только тот, кому оно предназначено. + +Замечание: Вы не можете добавлять или удалять Быстрые кнопки. + + + + + + +Отправка и получение файлов + +По &irc; вы можете обмениваться файлами с подключенными пользователями. + + +ВНИМАНИЕ!!! Никогда не открывайте файлы, полученные из незнакомого источника!!! + + +Чтобы отправить кому-либо в канале файл, щёлкните правой кнопкой на его &nickname; в Списке имен Главного окна. Выберите Послать файл Появится диалог выбора файла для отправки. Затем появится вкладка DCC статуса. + + + +Вкладка статуса DCC + + + + + + + + + + + + + Вкладка статуса DCC + + + + + + + + +Здесь отображаются &nickname; получателя и имя файла. + + +Колонка Статус отображает состояние отправки или получения файла: + + + + + + Предложение + + + Вы хотите отправить кому-то файл, а &kmyapplication; ждёт согласия пользователя на прием. + + + + + Соединение + + + &kmyapplication; пытается установить соединение с другой стороной. + + + + + Отправка + + + &kmyapplication; отправляет файл. + + + + + Получение + + + &kmyapplication; получает файл. + + + + + Завершено + + + Файл бы успешно отправлен + + + + + Остановлено + + + Передача начата, но приостановлена. + + + + + Отменено + + + Вы или другой пользователь нажали кнопку Отмена. + + + + + Сбой + + + Передача была прервана из-за ошибки. + + + + + Поставлено в очередь + + + Передача принята к исполнению и будет начата при получении согласия программы на стороне получателя. + + + + + Поиск + + + &kmyapplication; пытается получить IP отправителя. + + + + + Продолжение + + + Если во время передачи было обнаружено, что на принимающей стороне такой файл уже существует, пользователю будет выдан запрос Такой файл уже существует. Продолжить передачу?. Такое состояние отображается, если пользователь продолжит передачу. + + + + + + + + +Если кто-то хочет отправить вам файл, то появится вкладка DCC статус (если она не была открыта ранее). Щёлкните на вкладке DCC статус, чтобы открыть её. Выберите файл и нажмите кнопку для приема. Замечание: Можно настроить &kmyapplication; на автоматический прием файлов, отправленных другими пользователями, в главном меню: Настройка Настроить KonversationНастройка DCC. + + + + + +Если вы испытываете затруднения при отправке/получении файлов - возможно, ваш сетевой экран блокирует DCC-порты. Смотрите Часто задаваемые вопросы. + + + + + + +Интеграция с KAddressBook (Адресной книгой). + +Можно связать любой ник с контактом в Адресной книге. Если это будет сделано, то в Панели имен &kmyapplication; рядом с ником пользователя будет отображаться его реальное имя. + +Чтобы связать &nickname; с контактом в KAddressBook, в контекстном меню &nickname; пользователя в Панели имен Главного окна. Выберите Кто это? для отображения сведений о реальном имени этого человека. Затем, снова в контекстном меню выберите Связывание с Адресной книгой . Появится подменю. Если &nickname; еще не связан с контактом, щёлкните Создать контакт... . Появится окно Изменить контакт... . + + + +Окно редактирования контакта + + + + + + + + + + + + + Окно редактирования контакта + + + + + + + + +&nickname; здесь вводится автоматически. Если вы знаете реальное имя - замените им &nickname;. + + +Учтите, что &nickname; не появляется здесь. Вместо этого, .. + + + +Щёлкните здесь. Появится окно IM-адреса. + + + + + + + Окно IM-адреса + + + + + + Окно IM-адреса + + + + + +Заметьте, что &kmyapplication; вводит &nickname; за вас при помощи протокола IRC. + +Дополнительные сведения об использовании адресной книги KDE содержатся в Руководстве KAddressBook. + +Введите дополнительные сведения, которыми вы располагаете о данном человеке, и нажмите ОК. Реальное имя этого человека будет теперь отображаться рядом с его &nickname; в Панели имен &kmyapplication;. Это же имя будет появляться при наведении указателя мыши на &nickname;. + +Если &nickname; связан с контактом в Адресной книге, вы можете щёлкнуть правой кнопкой мыши на нем в Панели имен и отредактировать контакт, связать &nickname; с другим контактом, или удалить эту связь. + +Если &nickname; связан с контактом, а пользователь сменил свой ник во время работы &kmyapplication;, новый ник будет автоматически связан с контактом, при этом старая связь тоже сохранится. + +Если &nickname; IRC связан с контактом в Kopete, то эта связь будет передана &kmyapplication;, и наоборот. + +Заметьте: в Панели имён можно выделить несколько ников одновременно, щелчком правой кнопкой мыши можно создать одновременно несколько связей. + + + + + + +Перехват &URL; из сообщений. + +Во время общения в каналах пользователи часто посылают друг другу &URL; интересных веб-сайтов и других Интернет-ресурсов. При двойном щелчке на подобном &URL;, &kmyapplication; автоматически запустит приложение, связанное с этим &URL;. Запускаемое приложение зависит от &MIME;-типа &URL;. Например, если &URL; начинается с http:, то штатный браузер KDE запускается и отображает веб-страницу. (Можете также указать, какой браузер запустить.) Если во время перемотки текста &URL; ушел с экрана, трудно отыскать его снова. &kmyapplication; может вести для вас удобный журнал &URL;. Чтобы включить эту функцию, выберите Окна Охотник за URL в главном меню. Создаётся новая вкладка под названием Охотник за URL. + + + +Вкладка Охотника за URL + + + + + + + + + + + + + + + + Вкладка охотника за URL + + + + + + + + +Это - список всех &URL;, захваченных со времени запуска &kmyapplication;. В колонке Пользователь отображается &nickname; отправителя &URL;. Если эта колонка пуста, то URL появляется на вкладке Сообщения сервера. (&URL; из мгновенных сообщений не отображаются.) Для того чтобы выделить &URL;, щёлкните на нём. + +Щёлкните здесь для запуска приложения, связанного с выделенным &URL;. Запускаемое приложение зависит от &MIME;-типа &URL;. Например, для обработки &URL;, начинающегося с http:, штатный браузер запустится и отобразит запрашиваемую страницу. Для web-страниц вы можете также указать, какой браузер следует запускать. + +Щёлкните здесь для копирования выбранного &URL; в буфер обмена &kde;. + +Нажмите здесь для удаления выбранного &URL; из списка. + +Щёлкните здесь, чтобы сохранить список &URL; в файле. + +Нажмите здесь, чтобы очистить список. + + + + + + + + + +Выбор предпочитаемого браузера. + +При щелчке на &URL; в любом месте &kmyapplication; запустится приложение KDE, связанное с &MIME;-типом этого &URL;. Например, щелчок на адресе, начинающемся с http, вызовет запуск &konqueror; и загрузку в него соответствующей страницы. В качестве штатного можно указать другой браузер, например Mozilla. + +Для смены штатного браузера, выберите Настройка Настроить &kmyapplication; в главном меню. Появится окно Изменить предпочтения . + + + +Окно Браузера + + + + + + + + + + + + + Окно Браузера + + + + + + + + +Щёлкните здесь для отображения окна Браузера. + +Щёлкните здесь, чтобы указать свой браузер. + +Введите команду для запуска вашего любимого браузера. Когда вы щёлкнете на &URL;, вместо %u будет подставлен реальный адрес. + + + + +Совет: (Только для &UNIX;-систем). Команда по умолчанию - mozilla '%u', которая при каждом щелчке на &URL; запускает новый экземпляр Mozilla. Если вы хотите, чтобы Mozilla открывал новую страницу в уже запущенном экземпляре программы, создайте следующий файл: + + +#!/bin/sh +mozilla -remote "openURL($@, new-tab)" || exec mozilla "$@"; + + + +Назовите файл moz, поместите ссылку на него в PATH и сделайте его исполняемым (chmod a+x moz). Затем в командной строке окна, описанного выше, введите moz '%u' + +Заметка: Настройка Браузера не влияет на почтовые &URL;, они всегда обрабатываются штатной почтовой программой. + +Для сохранения сделанных изменений намите Применить. Чтобы изменения вступили в силу, нужно подключиться к каждому серверу и каналу. Простейший способ добиться этого - перезапуск &kmyapplication;. + + + + + + +Пометки в журналах каналов и приватов. + +Для облегчения и ускорения поиска нужной информации, вы можете делать пометки в экранах каналов и приватов. Для этого выберите в главном меню Вставка Пометить строку или нажмите &Ctrl;R. Строка появится внизу окна и станет частью общего текста. + +Чтобы одновременно ввести Помеченную строку во все каналы и приваты, выберите в главном меню Настройка Настроить Konversation , разверните пункт Поведение, нажмите кнопку Очистить окно и установите флажок Отображать помеченную строку во всех каналах/приватах. + +О том, как добиться того, чтобы &kmyapplication; автоматически подставляла Помеченную строку при вводе команды /away msg, смотрите в разделеНастройка идентификации. + + + + + + +Журналирование + +Если ведениепротоколов включено, то &kmyapplication; в течение сеанса сохраняет данные о каждом Сервере, Каналеи Привате. Данные каждого сеанса сохраняются в виде файла на диске. Если вы откроете тот же сеанс снова, то запись журнала будет продолжена. Объем журнала увеличивается до тех пор, пока не будет достигнут предел, установленный вами, при достижении предела старейшие сообщения будут удалены. + +Когда вы открываете сессию заново, приблизительно 1024 символа читаются из журнала и отображаются на экране. + +Во время сеанса сообщения передвигаются кверху. Для просмотра сообщений можно промотать их назад. Время от времени, для экономи памяти, старейшие сообщения удаляются. Это называется Предел отката:. Если журналирование включено, то сообщения, которые были удалены с экрана по достижении Предела отката, можно просмотреть в журнале. + +Для просмотра журнала сеанса, перейдите на его вкладку и выберите в главном меню Окно Открыть журнал . Появится новая вкладка, отображающая журнал. + + + +Файл журнала + + + + + + + + + + + + + + + Файл журнала + + + + + + + +Здесь отображены сообщения журнала. Старейшие из них находятся сверху, а новейшие - снизу. +Нажмите здесь, чтобы сохранить журнал в другом файле. +Щёлкните здесь для обновления журнала. В то время, когда вы просматриваете журнал, новые сообщения не добавляются к журналу автоматически. Для просмотра последних сообщений пользуйтесь этой кнопкой. +Нажмите, чтобы удалить файл журнала с диска. +Use this box to set the maximum size of the log file. This setting does not take effect until you restart &kmyapplication;. Each log file may have a separate setting. + + + +Предел отката можно изменить. Для этого нужно выбрать в главном меню Настройка Настроить &kmyapplication; , затем развернуть Поведение и выбрать Окно чата. На экране появится поле Предел отката:. Если вы зададите параметр Без ограничений, то старые сообщения удаляться не будут. + +Можно включить/выключить журналирование и установить его параметры. Для этого нужно выбрать в главном меню Настройка Настроить &kmyapplication; , затем развернуть Поведение и выбрать Журналирование. + + + + + + +Команды &kmyapplication; + +Следующие команды обрабатываются &kmyapplication; и могут отличаться от обычных команд &irc;. Значения внутри квадратных скобок необязательны. Значения, разделенные вертикальной чертой (|), являются альтернативными вариантами. Те команды, которые не описаны здесь, при вводе поступают на сервер. + + + + + +/me сообщение +Отправляет на канал сообщение, в начале которого стоит ваш &nickname;. Например если ваш &nickname; Pingvin и сообщение выглядело /me пьёт ароматный чай., то на канале сообщение будет выглядеть так: Pingvin пьёт ароматный чай.. Все пользователи увидят это сообщение (если, конечно, такой тип сообщений не фильтруется). Эти сообщения дают вам возможность передать невербальную информацию, например ваше настроение или то, чем вы сейчас заняты. Но, если вам нужно ненадолго отойти от вашего компьютера, воспользуйтесь лучше командой /away. + + + +/ame сообщение +Похожа на команду /me, приведенную выше, только сообщение рассылается на все каналы и всем приватам на всех серверах, к которым вы подключены в &kmyapplication;. + + + +/join канал [пароль] +Подключает к указанному каналу. Если сервер даст согласие, и если канал еще не существует, то вы станете его оператором. Если канал для подключения требует пароль, введите его в разделе пароль. Большинство названий каналов начинается с # + + + +/j канал [пароль] +То же самое, что /join. + + + +/part [канал] [причина] +Приводит к выходу с канала с указанием причины и закрывает вкладку соответствующего канала. Во вкладке канала или привата &kmyapplication;, чтобы закрыть канал или приват, можно просто ввести команду /part с причиной по умолчанию, указанной в Настройке. + + +/leave [канал] [причина] +То же самое, что /part. + + +/quit +После ввода на любом канале, в привате или DCC-вкладке, отключает соответствующий сервер и закрывает все каналы, приваты и DCC-вкладки, открытые на этом сервере. + + +/notice ник|канал сообщение +Посылает сообщение пользователю под псевдонимом ник или всем на канале. Ниже приведен прмер того, что вы можете увидеть во вкладке канала + +[17:14] [Notice] Sending notice "Понял вас" to #konversation + +А вот что увидят получатели + +[17:15] [Notice] -Eisfuchs- Понял вас + + + + +/queryпсевдоним. +Создаётся новая вкладка для пользователя под указанным ником для частного разговора, известного в IRC под названием Приват. Все, что написано здесь, будете видеть только вы и ваш приватный партнер. Можно ввести несколько ников, разделенных пробелами, и для каждого из них будет открыта новая вкладка. Все они будут частными для вас и ваших партнеров. + + + +/msg ник|канал сообщение +Посылает частное сообщение пользователю с указанным ником или пользователям указанного канала. В отличие от команды /query, не приводит к открытию новой вкладки. Если сообщение начинается с команды /me , то текст форматируется так же, как в команде /me. + +Примеры + +/msg Eisfuchs Мне нужна помощь по команде msg + +/msg #konversation Появилась новая версия Konvi! + +/msg Eisfuchs /me компилирую Учебник. + + + + + +/smsg ник|канал сообщение +То же самое, что /msg, с той разницей, что сообщение не отображается на экране. Может пригодиться, если вы опасаетесь выдать пароль или другую секретную информацию. + + + +/amsg ник|канал сообщение +Похожа на /msg, только сообщение будет разослано во все каналы и приваты, которые открыты на всех серверах, к которым вы подключены в &kmyapplication;. + + + +/op ник +Вводом этой команды во вкладке канала делается попытка дать пользователю под ником права оператора канала. Может не сработать, если у вас недостаточно привилегий на этом канале (вы сами должны быть оператором). Можно ввести несколько ников, разделив их пробелами. + + + +/deop ник +Ввод этой команды во вкладке канала снимает привилегии оператора с пользователя под указанным ником. Можно ввести несколько ников, разделив их пробелами. + + + +/oper [ник] +Наделяет пользователя &nickname; ник привилегиями IRC-Op (Администратора). Команда будет иметь эффект только в том случае, если &nickname; указан в строке O: сервера. IRC-Op может издавать команду /kill в отношении пользователей, подключать серверы к сети &irc; и совершать другие ответственные действия. Если ник не указан, то делается попытка присвоить привилегии IRC-Op себе. В этом случае вам будет предложено ввести имя и пароль администратора. + + + +/voice ник +На некоторых каналах (с флагом +m), пользователи не могут отправлять сообщения, если у них нет права голоса. Эта команда - попытка дать такое право. Для выполнения этой команды у вас должны быть права оператора. В основном используется операторами модерируемых каналов. + + + +/unvoice ник +Лишает права голоса пользователя под указанным ником. + + + +/topic [канал] [сообщение] +Попытка задать на канале тему для сообщения. Когда команда вводится во вкладке канала, часть канал может быть опущена, и тогда действуют параметры канала по умолчанию. Если опущена часть сообщение, то отображается текущая тема канала. Если у вас недостаточно прав, то смены темы канала вы можете и не добиться. + + + +/away причина +Если кто-либо захочет послать вам сообщение или пригласить на частный разговор, им может быть отправлено сообщение о вашем отсутствии за компьютером по указанной причине. Для возвращения в нормальное состояние наберите /away без указания причины. + + + +/aaway причина +То же, что команда /away, только рассылается на все серверы, к которым подключена &kmyapplication;. + + + +/invite ник [канал] +Приглашение пользователя под указанным ником подключиться к каналу. Особенно полезна эта команда для тех каналов, доступ на которые возможен только по приглашению. Если команда вводится во вкладке канала, то часть канал можно опустить. + + + +/exec имя_файла [параметры] +Исполняет сценарий оболочки под названием имя_файла, передавая ему указанные параметры. Более подробно эта тема освещена в разделе Поддержка сценариев. +Примеры: + +/exec kdeversion + +Посылает на канал номера версий ваших KDE и Qt. + +/exec cmd uname -a + +Посылает на канал строку с версией вашей Linux. + + + + + +/notify [ник] +Добавляет ник к списку ваших Наблюдаемых подключенных пользователей или удаляет его из списка. Если ник уже есть в списке, то он удаляется, а если его нет - добавляется. Если конкретный nick не указан, то отображается весь список наблюдаемых ников. + + + + +/prefs [list|группа] [list|параметр] [значение] +Отображает или устанавливает настройки &kmyapplication; без обращения к окну "Настройка". Если параметр содержит пробелы, заключите его в скобки. + +Примеры: + +/prefs list + +отображает доступные группы параметров. + +/prefs "General Options" list + +отображает параметры, доступные в группе Общие параметры вместе с их текущими значениями. + +/prefs "General Options" ShowTrayIcon + +Отображает текущую настройку отображения значка &kmyapplication; в системном лотке. + +/prefs "General Options" ShowTrayIcon false + +Убирает значок &kmyapplication; из системного лотка. + + + + +/kick ник причина +Если ввести команду во вкладке канала, то будет сделана попытка выгнать с канала пользователя с указанным ником по указанной причине. Если причина не указана, то действует Настройка по умолчанию. Эта команда используется только во вкладке канала. + + + +/ban [-host|-domain| -userhost|-userdomain] [канал] пользователь|маска +Попытка удалить пользователяили маску с канала. Если комада вводится во вкладке канала, то канал можно опустить. Более подробно о хостах, доменах и масках можно узнать на irchelp.org. Чтобы просмотреть текущий список удалённых с канала пользователей, введите команду /mode канал b. + + + +/unban [канал] шаблон +Отменяет прежнее удаление с канала. Если команда введена во вкладке канала, то часть канал можно опустить. + + + +/ignore [-all] ник +Добавляет ник к списку игнорируемых вами. Можно указать несколько ников, разделив их пробелами. Сообщения пользователей из этого списка на канале не отображаются. Кроме того, если введена команда -all, то не отображаются не только сообщения на канал, но и все остальные типы сообщений (приватные, уведомления, CTCP, DCC и Исключения). + + + +/quote команда +Посылает команду на сервер. + + + +/say сообщение +Введенная во вкладке канала, отсылает на канал сообщение. То же самое, что команда сообщение, введенная в Строке ввода канала. Удобно для ввода &irc;-команд, если вы не хотите их исполнения. Два управляющих символа (//) в строке дают тот же результат, что команда /say. Используется также в сценариях для отправки сообщений. + + + +/raw [open|close] +Переводит журнал сервера в цифровой режим (open) или отменяет цифровой режим (close). Если ни open, ни close не введены, то по умолчанию действует режим open. В цифровом режиме все сообщения в журнале отображаются в собственном &irc;-формате. + + + +/konsole +Открывает новую вкладку с запущенной консолью KDE. + + + +/server [адрес] [пароль] +Подключает к серверу по указанному адресу. Если адрес не указан, то подключение происходит к серверу, связанному с вкладкой, в которой вводится команда. Удобно для подключения к серверу при разрыве связи. Если для входа на сервер требуется пароль, то введите его в части pwd. Если для подключения к серверу используется не обычный (6667) порт, то адрес нужно набирать таким образом: irc.kde.org:6665. + + + +/dcc SEND ник [имя_файла] +Посылает файл с названием имя_файла пользователю под ником ник. Если имя файла не указано, то появится диалоговое окно выбора файла. + + + +/dcc +Открывает вкладку состояния DCC. + + + +/ctcp ник|канал ping +Посылает PING-сообщение пользователю ник или на канал. Полезно для определения, насколько высок сетевой уровень вашего собеседника или (если команда направляется на канал) насколько высок сетевой уровень вашей системы. + + + +/ctcp ник|канал сообщение +Посылает сообщение пользователю под указанным ником или пользователям в указанном канале. Похоже на команду /msg, только сообщение отправляется с использованием протокола CTCP. Ответ противоположной стороны зависит от того, какой клиент &irc; там запущен. Например, если вы переговариваетесь с другим пользователем &kmyapplication;, то команда /ctcp Eisfuchs TIME вернёт системное время компьютера Eisfuchs. /ctcp Eisfuchs VERSION вернёт номер версии &kmyapplication; компьютера Eisfuchs. + + + + + + + + + + +Поддержка сценариев + +&kmyapplication; может работать с удобными сценариями, которые можно запускать из программы. Для запуска сценария на канале, в привате, DCC или во вкладке сервера нужно набрать команду вида + +/exec имя_файла [параметры] + +которая исполнит сценарий под названием имя_файла, передав ему (необязательные) параметры. + +Например, ввод следующей команды во вкладке канала + +/exec kdeversion + +передаст на канал номера версий KDE и Qt, установленных в системе. + +/exec cmd uname -a + +исполняет сценарий cmd, передав ему параметр uname -a. На канал будет передана строка с версией вашей Линукс. + +Чтобы посмотреть список доступных сценариев, наберите в консоли следующую команду. + +ls $KDEDIR/share/apps/konversation/scripts + +Вы можете писать собственные сценарии на любом языке оболочки (bash, perl или python). Во время исполнения сценария в &kmyapplication;, первыми тремя параметрами должны быть: + + + +Номер порта &irc;-сервера, во вкладке которого вводится команда /exec. + + +Адрес сервера. + +Название канала. + + + +Пример сценария (cmd). + + +#!/bin/sh + +# Исполняет команду и отображает выход в Konversation. + +PORT=$1; +SERVER=$2; +TARGET=$3; +shift;shift;shift; + +$@ | while read line; do dcop $PORT Konversation say $SERVER "$TARGET" "$@: $line"; done + + + +Заметьте, что для сообщения с &kmyapplication; сценарий использует DCOP. Команда say вызовет отправку вывода на канал, как обычного сообщения. Для отображения во вкладке того, что вы не хотите отправлять другим пользователям, используйте команду info. Взглянув на существующие файлы сценариев, вы получите более полное представление о них. + +Чтобы получить возможность запустить собственный сценарий, вы должны скопировать его в $KDEDIR/share/apps/konversation/scripts или в $HOME/.kde/share/apps/konversation/scripts. Необходимо также дать ему права на исполнение, например таким образом: chmod a+x имя_файла. + + + + + + + + +Описание команд + + + + + + +Главное окно &kmyapplication; + + +Меню Файл + + + + F2 Файл Список серверов + Отображает список серверов и каналов. + + + F7 Файл Быстрое подключение + Открывает окно Быстрое подключение для подключения к серверу. + + + Файл Переподключиться + Возобновляет подключение ко всем серверам в случае неожиданного разрыва связи. + + + &Ctrl;J Файл Зайти на канал + Открывает диалог ввода названия канала для подключения. То же, что ввод /join #channelname во вкладке канала или сервера. + + + &Alt; &Ctrl;Q Файл Установить статус Отсутствую во всех разговорах + Состояние вашего ника указывает всем на ваше отсутствие за компьютером. + + + &Ctrl;Q Файл Выход + Закрывает &kmyapplication; + + + + + + +Меню <guimenu +>Правка</guimenu +> + + + + &Ctrl;F Правка Найти + + Поиск текстовой строки в текущем окне. + + + + F3 Правка Продолжить поиск + + Повторяет поиск текстовой строки в текущем окне с использованием результатов предыдущего поиска. + + + + &Ctrl;L Правка Очистить окно + + Очищает текущее окно. + + + + &Ctrl; &Shift;L Правка Очистить все окна + + Очищает все окна. + + + + + + + +Меню <guimenu +>Вставка</guimenu +> + + + + &Ctrl;K Вставка Цвет IRC + + Смотрите Отправка окрашенных сообщений. + + + + &Ctrl;R Вставка Пометить строку + + Смотрите Пометки в журналах каналов и приватов. + + + + &Alt; &Shift;C Вставка Вставить символ... + + Используется для вставки особых символов (например, иностранных букв). + + + + + + + +Меню <guimenu +>Закладки</guimenu +> + + + + &Ctrl;B Закладки Добавить закладку + + Добавляет закладку на текущие сеть и канал + + + + Закладки Изменить закладки + + Открывает редактор закладок + + + + Закладки Создать папку закладок + + Создает новую папку для закладок + + + + + + + +Меню <guimenu +>Настройка</guimenu +> + + + + &Ctrl;M Настройка Скрыть меню + + Скрывает главное меню. Чтобы отобразить его снова, нажмите &Ctrl;M. + + + + Настройка Скрыть панель инструментов + + Скрывает Панель инструментов. + + + + Настройка Скрыть строку состояния + + Скрывает строку состояния внизу главного окна. + + + + Настройка Профили + Открывает Профили для настройки ваших персональных данных. + + + Настройка Настроить комбинации клавиш + + Настройка горячих клавиш для &kmyapplication;. + + + + Настройка Настроить панели инструментов + + Позволяет добавлять и удалять кнопки Панели инструментов &kmyapplication;. + + + + Настройка Настроить уведомления... + + Открывает окно Настройка уведомлений. + + + + Настройка Настроить &kmyapplication; + + Открывает окно Изменить предпочтения. + + + + + + + +Меню <guimenu +>Окно</guimenu +> + + + + &Ctrl;. Окно Предыдущая вкладка + + Открывает окно, связанное с предыдущей вкладкой. + + + + &Ctrl;, Окно Следующая вкладка + + Открывает окно, связанное со следующей вкладкой. + + + + &Ctrl;W Окно Закрыть вкладку + + Закрывает текущее окно. Если закрывается вкладка канала, то происходит отключение от него. Если закрывается вкладка сервера, то происходит отключение от всех каналов этого сервера, и сам сервер тоже отключается. + + + + F11 Окно Закрыть все приваты + + Закрывает все приваты (queries). + + + + &Ctrl;H Окно Скрыть список пользователей + + Скрывает/открывает панель имен во вкладке канала. + + + + F4 Окно Наблюдаемые подключенные пользователи + + Открывает окно Наблюдаемые подключенные пользователи. Смотрите Наблюдение за пользователями в сети. + + + + F5 Окно Список каналов + + Открывает список каналов, доступных на сервере. + + + + F6 Окно Охотник за URL + + Открывает окно Охотника за URL. + + + + Окно Открыть консоль + + Открывает терминал. Можно открыть столько вкладок Консоль, сколько необходимо. + + + + &Ctrl;O Окно Открыть журнал + + Открывает окно с журналом сообщений текущей вкладки. Действует только для вкладок Канал, Сообщения сервера и Приват. Ведением журнала можно управлять через меню Настройка Настроить Konversation Поведение Журналирование . + + + + + + + +Меню <guimenu +>Справка</guimenu +> +&help.menu.documentation; + + + + + + + +Вопросы и ответы +&reporting.bugs; &updating.documentation; + + + +При запуске &kmyapplication; я хотел бы подключаться к серверу без входа на какой-либо канал. Как это сделать? + + +В окне Настройка сервера оставьте поле Каналы пустым. + + + + + +&kmyapplication; не подключается ни к одному серверу. В чем дело? + + +Дело может быть в нескольких вещах. + + +Убедитесь, что в окне Добавить сервер указаны верные Имя сервера и номер Порта. + + +Просмотрите вывод в окне Сообщения сервера на предмет сообщений об ошибках. Не отказал ли сервер в подключении из-за неверного пароля? Не было ли отказа в подключении из-за того, что сервер потребовал IDENTD (идентификации), а ваш компьютер не ответил на этот запрос? Может быть, вы пользуетесь протоколом SSL, а сервер его не поддерживает? + + +Если у вас установлен брандмауэр, то нужно убедиться в том, что доступны следующие порты: + + + +Исходящий TCP 6667 (или порт сервера, к которому вы подключаетесь) +Входящий TCP 113 (если сервер требует идентификации) + + + + +Подробнее о проблемах подключения IRC можно узнать на irchelp.org. + + + + + + + + + +При переходе в Окно Список каналов , я не могу выбрать канал. Почему? + + +Пункт меню Окно Список каналов может стать серым (неактивным) в том случае, если вкладка канала не является текущей (например, вы находитесь во вкладке Наблюдаемые подключенные пользователи). Чтобы вернуть возможность выбора пункта, нужно вернуться во вкладку канала или сервера. + + + + + + + + + + +Благодарности и лицензия + +&kmyapplication; +© 2002-2005 Разработчики Konversation. +&konviwebsite; + +Участники: +Дарио Абатианни (Dario Abatianni) eisfuchs@tigress.com +Питер Симонссон (Peter Simonsson) psn@linux.se +Кристиан Мюельгаузер (Christian Muehlhaeuser) chris@chris.de +Джон Тэпсел (John Tapsel) john@geola.geo.uk +Измаил Доменз (Ismail Donmez) ismail.donmez@boun.edu.tr +Шинтаро Матсуока (Shintaro Matsuoka) shin@shoegazed.org +Гари Крамблитт (Gary Cramblitt) garycramblitt@comcast.net +Маттиас Гирлингс (Matthias Gierlings) gismore@users.sourceforge.net +Алекс Зепеда (Alex Zepeda) garbanzo@hooked.net +Станислав Карчебный (Stanislav Karchebny) berkus@users.sourceforge.net +Майкл Мачанд (Mickael Marchand) marchand@kde.org + + + +Благодарности: +Майкл Гоеттше (Michael Goettsche) michael.goettsche@kdemail.net +Бенжамин Мейер (Benjamin Meyer) ben+konversation@kdemail.net +Якоб Стаховский (Jacub Stachowski) qbast@go2.pl +Себастьян Сарьяго (Sabastian Sariego) segfault@kde.cl +Оливер Вебард (Olivier Bedard)www.konversation.org hosting +Фраук Остер (Frauke Oster) frauke@frsv.de +Лучиян Муш (Lucijan Busch) lucijan@kde.org +Саша Кунз (Sascha Cunz) mail@sacu.de +Стив Уоллкайнд (Steve Wollkind) steve@njord.org +Томас Нэги (Thomas Nagy) thomas.nagy@eleve.emn.fr +Тобиас Олри (Tobias Olry) tobias.olry@web.de +Руд Наббен (Ruud Nabben) r.nabben@gawab.com + + + +Документация © 2003-2005 Гари Крамблитт (Gary R. Cramblitt) garycramblitt@comcast.net + +Перевод на русский язык: Владимир Рычков vvgtr2@mail.ru, Сергей Новгородов ximen@tsu.tmb.ru, Алексей Опарин opaleksej@yandex.ru +&underFDL; &underGPL; + + +Установка + + + + +Поолучение &kmyapplication; +&install.intro.documentation; Новейшую версию &kmyapplication;, со всеми исходными кодами и инструкциями по сборке, можно получить на сайте &konviwebsite;. + + + + + + +Требования + + + +Для успешной работы &kmyapplication; необходим &kde; 3.2 или выше, подключение к Интернет. На ранних версиях &kde; некоторые свойства могут быть недоступны. Если вы пользуетесь &kmyapplication; при включенном брандмауэре посмотрите Вопросы и ответы. Если вы хотите пользоваться протоколом SSL, то вам нужен OpenSSL. + + + + +&documentation.index; +
+ + diff --git a/doc/sv/Makefile.am b/doc/sv/Makefile.am new file mode 100644 index 0000000..3d9353e --- /dev/null +++ b/doc/sv/Makefile.am @@ -0,0 +1,2 @@ +KDE_LANG = sv +KDE_DOCS = konversation diff --git a/doc/sv/addchannel.png b/doc/sv/addchannel.png new file mode 100644 index 0000000..3bd4ed8 Binary files /dev/null and b/doc/sv/addchannel.png differ diff --git a/doc/sv/addnetwork_co.png b/doc/sv/addnetwork_co.png new file mode 100644 index 0000000..703e362 Binary files /dev/null and b/doc/sv/addnetwork_co.png differ diff --git a/doc/sv/addserver_co.png b/doc/sv/addserver_co.png new file mode 100644 index 0000000..4c864a3 Binary files /dev/null and b/doc/sv/addserver_co.png differ diff --git a/doc/sv/channel_screen_tour_co.png b/doc/sv/channel_screen_tour_co.png new file mode 100644 index 0000000..01a362e Binary files /dev/null and b/doc/sv/channel_screen_tour_co.png differ diff --git a/doc/sv/channellist_screen_co.png b/doc/sv/channellist_screen_co.png new file mode 100644 index 0000000..e94de82 Binary files /dev/null and b/doc/sv/channellist_screen_co.png differ diff --git a/doc/sv/checkidentities.png b/doc/sv/checkidentities.png new file mode 100644 index 0000000..0a21b80 Binary files /dev/null and b/doc/sv/checkidentities.png differ diff --git a/doc/sv/colorchooser_screen.png b/doc/sv/colorchooser_screen.png new file mode 100644 index 0000000..55feac5 Binary files /dev/null and b/doc/sv/colorchooser_screen.png differ diff --git a/doc/sv/dccstatus_screen_co.png b/doc/sv/dccstatus_screen_co.png new file mode 100644 index 0000000..8d4a7a2 Binary files /dev/null and b/doc/sv/dccstatus_screen_co.png differ diff --git a/doc/sv/first_channel_co.png b/doc/sv/first_channel_co.png new file mode 100644 index 0000000..cfe8cee Binary files /dev/null and b/doc/sv/first_channel_co.png differ diff --git a/doc/sv/first_serverlist_co.png b/doc/sv/first_serverlist_co.png new file mode 100644 index 0000000..1d0fc09 Binary files /dev/null and b/doc/sv/first_serverlist_co.png differ diff --git a/doc/sv/highlighting_screen_co.png b/doc/sv/highlighting_screen_co.png new file mode 100644 index 0000000..9689d41 Binary files /dev/null and b/doc/sv/highlighting_screen_co.png differ diff --git a/doc/sv/identities_adv_co.png b/doc/sv/identities_adv_co.png new file mode 100644 index 0000000..3f4624c Binary files /dev/null and b/doc/sv/identities_adv_co.png differ diff --git a/doc/sv/identities_away_co.png b/doc/sv/identities_away_co.png new file mode 100644 index 0000000..b600100 Binary files /dev/null and b/doc/sv/identities_away_co.png differ diff --git a/doc/sv/identities_gen_co.png b/doc/sv/identities_gen_co.png new file mode 100644 index 0000000..327f0cf Binary files /dev/null and b/doc/sv/identities_gen_co.png differ diff --git a/doc/sv/index.docbook b/doc/sv/index.docbook new file mode 100644 index 0000000..2d2c797 --- /dev/null +++ b/doc/sv/index.docbook @@ -0,0 +1,5965 @@ + + + + + IRC"> + CTCP"> + nickname"> + Nickname"> + LED"> + OSD"> + URL"> + MIME"> + + + + + + +]> + + + + + + + + + + + + +Handbok &konversation; + + + Gary R. Cramblitt garycramblitt@comcast.net +StefanAsserhäll
stefan.asserhall@comhem.se
Översättare
+
+ + + + +2003-2005 +Gary R. Cramblitt + + + + +&FDLNotice; + + + +2005-05-23 +0.18 + + + + +&konversation; är en användarvänlig &irc;-klient för K-skrivbordsmiljön. + + + + + +KDE +kdeextragear-2 +Konversation +irc +internet relay chat +chatt +kommunikationer + + +
+ + + + + + +Inledning + + + +&konversation; är en &irc;-klient för &kde; 3.2 eller senare. Den erbjuder följande funktioner: + + + +Stöd för SSL. +Användarvänligt gränssnitt med flikar. +Anpassningsbara snabbknappar för ofta använda kommandon. +Automatisk återuppkoppling och gå med igen. +Skicka och ta emot filer. +Bevakningslista för smeknamn. +Visuella och ljudbaserade underrättelser för en stor mängd händelser, som meddelanden som innehåller ditt smeknamn, eller uppkoppling och nerkoppling för smeknamn i din bevakningslista. +Anpassningsbar färgläggning av meddelanden enligt smeknamn eller mönster med reguljärt uttryck. +Komplettering av smeknamn. +Fånga och spara alla webbadresser som ingår i meddelanden. +Visning av meddelanden på skärmen, också om minimerad. +Lista över smeknamn att ignorera. +Automatisk loggning och logghantering. +Markering av rader i loggar. +Styrning via skript. +Integrering med adressboken. + + + +Webbplatsen för &konversation; är &konviwebsite;. Frågor och svar om &konversation; kan diskuteras via e-postlistan &konversation;-Users. Prenumerera gärna för att få reda på nya funktioner, felrapporter och liknande. För att bli informerad om nya utgåvor, kan du gå med i e-postlistan &konversation;-Announce. Det här är en e-postlista med litet antal brev, som bara används för att kungöra nya utgåvor eller programfixar. + +Utvecklare av &konversation; kan oftast kontaktas via &irc; på irc.kde.org, kanalen #konversation. + + + + +Att använda &konversation; + + + + +Om du inte har använt &irc; tidigare... + +Enkelt uttryckt är &irc; ett chattprotokoll, definierat av officiella Internetstandarder, med möjlighet att stjäla många timmar av ditt liv. För att använda &irc; måste du ansluta till en server, och därefter gå med i en kanal (som motsvarar ett chattrum) eller bara inleda en privat konversation. + +För att ansluta till en server och kanal, starta &konversation;. Skärmen Serverlista visas. + + + +Serverlista + + + + + + + + + + + + + Serverlista + + + + + + + +Listan med inställda &irc; Nätverk anges här. Ett &irc;-nätverk är en samling samarbetande servrar. Du behöver bara ansluta dig till en av servrarna i nätverket för att vara ansluten till hela &irc;-nätverket. När du väl är ansluten, kommer &konversation; automatiskt att gå med i de visade Kanalerna. När &konversation; startas för första gången, är nätverket Freenode och kanalen #kde redan inskrivna åt dig. Klicka på ett nätverk för att välja det. +Klicka här för att definiera ett nytt Nätverk, inklusive servern att ansluta till, och Kanalerna som automatiskt ska gås med i efter anslutning. Se Definiera nya nätverk, servrar och kanaler att automatiskt gå med i för mer information. +Klicka här för att ansluta till valt &irc;-nätverk och kanal. + + + + +När du klickar på knappen Anslut första gången du öppnar &konversation;, kanske du ser följande meddelande, som talar om för dig att din förvalda identitet inte är riktigt inställd. + + + + Kontrollera identiteter + + + + + + Kontrollera identiteter + + + + + +Första gången du öppnar &konversation; hämtas information om nuvarande användare från operativsystemet, och förvalda värden för identiteten fylls i. Om användarinformationen i operativsystemet inte är fullständig, till exempel om inget Fullständigt namn är definierat, kan du se meddelandet ovan. För att rätta problemet, klicka på Ok och titta i Ställa in din identitet för mer information. + + +Huvudskärmen öppnas och visar meddelanden som skickas av servern till klienten. (Om &konversation; inte ansluter till servern, se Vanliga frågor.) När servermeddelanden har slutat bläddra förbi, går &konversation; med i kanalen eller kanalerna som valts. + + + +Kanal. + + + + + + + + + + + + + Kanal + + + + + + + + +Det här kallas inmatningsraden. För att skicka ett meddelande till alla i kanalen, skriv in meddelandet här och tryck på Enter. Meddelandet samt alla andras meddelanden syns i kanalfönstret ovanför. Varje meddelande inleds med tiden och användarens smeknamn. + +Du kan gå med i ytterligare servrar och kanaler. Varje server, kanal, kanallista och annan skärm får en separat flik här. För att visa en lista med tillgängliga kanaler, se Lista över tillgängliga kanaler. För att gå med i en kanal, skriv: /join #kanalnamn på indataraden. (Tecknet # krävs.) Du kan också skriva /j som förkortning av /join. För att lämna en kanal, skriv bara /part. För att byta visning till en annan server eller kanal, klicka på motsvarande flik. + +Det här kallas smeknamnsrutan. Den listar smeknamnen för alla användare som har gått med i kanalen, inklusive dig själv. + + + + +Det här är grunderna, för mer detaljerad information, läs vidare... + + + + + + +Ställa in din identitet + +Innan du börjar använda &konversation; regelbundet bör du ställa in hur du vill bli identifierad på nätverket. + +Klicka på Inställningar Identiteter i huvudmenyn. Skärmen Identiteter visas. Du kan också visa skärmen Identiteter genom att klicka på knappen Redigera på skärmen Lägg till nätverk. + + + +Identiteter (fliken Allmänt) + + + + + + + + + + + + + + + + + Identiteter (fliken Allmänt) + + + + + + + +Klicka här för att välja en Identitet att redigera. +Använd de här knapparna för att lägga till, duplicera, byta namn på eller ta bort en Identitet. +Skriv in ditt riktiga namn här. &irc; är inte avsett att dölja dig för dina vänner eller fiender. Kom ihåg det om du är frestad att bete dig ondsint. Ett felaktigt "riktigt namn" kan vara ett bra sätt att dölja om du är man eller kvinna för alla töntar därute, men datorn som du använder kan alltid spåras, så du kan aldrig vara verkligt anonym. +Använd de här knapparna för åtgärderna Lägg till, Redigera eller Ta bort för ett smeknamn. +Det här är din lista med dina smeknamn. Ett smeknamn är namnet som övriga användare känner dig som. Du kan skriva in vilket namn du än önskar. Det första tecknet måste vara en bokstav, medan övriga tecken kan vara bokstäver, siffror eller specialtecken -[]\`_^{}|. + +Eftersom smeknamn måste vara unika i ett helt &irc;-nätverk, kanske ditt önskade namn inte tillåts av servern eftersom någon annan redan använder det. Skriv in alternativa smeknamn för dig själv. Om ditt första val inte tillåts av servern, försöker &konversation; med de alternativa smeknamnen. + +Enligt RFC 2812 är den maximala smeknamnslängden 9, men det avgörs i själva verket av servern. För att avgöra maximum för en server, anslut till servern. Leta efter meddelandet [Support] under fliken Servermeddelanden. Till exempel: + + +[18:51] *Eisfuchs* [21:45] [Support] Eisfuchs MODES=4 MAXCHANNELS=20 NICKLEN=16 USERLEN=10 HOSTLEN=63 TOPICLEN=450 KICKLEN=450 CHANNELLEN=30 KEYLEN=23 CHANTYPES=# PREFIX=@+ CASEMAPPING=ascii CAPAB IRCD=dancer + + +Parametern NICKLEN anger maximala längden på smeknamnet. + + +Använd de här knapparna för att ändra ordning på smeknamnen. Det översta smeknamnet provas först, därefter nästa, och så vidare. +Om du har registrerat ditt smeknamn med &irc;-nätverket, skriv in tjänsten och lösenordet för att behörighetskontrollera ditt smeknamn. När &konversation; ansluter, skickas automatiskt /msg tjänst IDENTIFY lösenord till servern. Om du inte vet vad det är, lämna rutorna tomma. + + + + + +Klicka på fliken Borta. + + + + Identiteter (fliken Borta) + + + + + + + + + + + + + Identiteter (fliken Borta) + + + + + + + +Skriv in ett smeknamn som anger att du är borta. Så fort du utför kommandot /away meddelande i någon kanal som du gått med i med denna Identitet, ändrar &konversation; automatiskt ditt smeknamn till Borta smeknamn. Andra användare märker att du är borta från datorn. Så fort du utför kommandot /away i någon kanal där du är borta, ändrar &konversation; automatiskt tillbaka ditt smeknamn till det normala. Om du inte automatiskt vill ändra ditt smeknamn när du är borta, lämna det tomt. +Om du markerar den här rutan, så ritas en horisontell linje i kanalen så fort du utför kommandot /away, som markerar stället där du gick ifrån. Andra &irc;-användare ser inte den här horisontella linjen. +Om du markerar den här rutan skickar &konversation; automatiskt Frånvaromeddelande: till alla kanaler som du gått med i med denna Identitet:. %s ersätts med meddelande. Så fort du utför kommandot /away, visas Återkomstmeddelande i alla kanaler du gått med i med denna Identitet. + +Frånvaromeddelanden anses ofta irriterande av andra användare. Använd alternativet med försiktighet, och tag hänsyn till andra &irc;-användare. + + + + + + +Klicka på fliken Avancerat. + + + + Identiteter (fliken Avancerat) + + + + + + + + + + + + + + + + Identiteter (fliken Avancerat) + + + + + + + +Du kan skriva in ett kommando här som körs innan anslutning till servern. Om identiteten används för mer än en server, körs kommandot för varje server. +Den här inställningen påverkar hur tecken du skriver kodas när de ska skickas till servern. Den påverkar också hur meddelanden visas. När du först öppnar &konversation;, hämtas den här inställningen automatiskt från operativsystemet. Om du verkar ha problem med att se andra användares meddelanden riktigt, försök då ändra inställningen. +När du ansluter, frågar många servrar din dator efter ett IDENT-svar. Om du dator inte kör en IDENT-server, skickas svaret av &konversation;. Inga mellanslag tillåts. Ett förslag är att använda ditt förnamn. +Så fort du lämnar en kanal, skickas det här meddelandet till kanalen. +Så fort du sparkas ut från en kanal (oftast av en &irc;-operatör), skickas det här meddelandet till kanalen. +Klicka för att verkställa dina ändringar. För att alla ändringar ska få effekt, måste du koppla ner från servern och koppla upp igen. Det enklaste sättet att göra det är att avsluta &konversation; och starta om. + + + + + + + + + + +Definiera nya nätverk, servrar och kanaler att automatiskt gå med i + +Skärmen Serverlista visas när du startar programmet &konversation;. Den visas också när du väljer Arkiv Serverlista i huvudmenyn. Skärmen Serverlista anger de befintliga definierade &irc;-nätverken, enligt grupp. Ett &irc;-nätverk är en samling samarbetande servrar. När du ansluter till någon server i ett nätverk, kan du komma åt alla kanaler i nätverket. Exempel på &irc;-nätverk är Freenode och Undernet. + + + + Serverlista + + + + + + + + + + + + + + Serverlista + + + + + + + +Dina befintliga definierade nätverk listas här tillsammans med den identitet som används för att ansluta till nätverket, och de kanaler som du automatiskt går med i när du är ansluten. Om du har angivit en grupp för dina nätverk, listas nätverken indragna under gruppen. Klicka på ett nätverk för att markera det. +Använd de här knapparna för att lägga till ett nytt nätverk, redigera ett markerat nätverk eller ta bort ett markerat nätverk. +Klicka på den här knappen för att ansluta till ett markerat nätverk och stänga skärmen Serverlista. Du kan markera mer än ett nätverk om du önskar, vilket ansluter till alla markerade nätverk. +Att klicka på den här knappen kastar inte ändringarna du har gjort. Den betyder bara att du inte vill ansluta till något nätverk för närvarande. + + + + + +När du klickar på knappen Lägg till visas skärmen Lägg till nätverk. + + + + Lägg till nätverk + + + + + + + + + + + + + + + + + + + Lägg till nätverk + + + + + + + +Skriv in namnet på ett nätverk här. Du kan skapa så många poster på skärmen Serverlista med samma nätverk som du vill. +Valfritt. Om du skriver in något här, listas alla nätverk med samma grupp tillsammans på skärmen Serverlista. +Välj en befintlig identitet eller klicka på knappen Redigera för att lägga till en ny identitet eller redigera en befintlig. En identitet kommer att identifiera dig och avgöra ditt smeknamn när du ansluter till nätverket. +Valfritt. Kommandot skickas till servern efter anslutning. Exempel: /msg NickServ IDENTIFY konvirocks. Exemplet gäller för nätverket freenode, som kräver att användare registrerar sina smeknamn med ett lösenord och inloggningsnamn vid anslutning. konvirocks är lösenordet för smeknamnet som anges under Förvald identitet. Du kan skriva in mer än ett kommando genom att skilja dem åt med semikolon. +Markera det här om du vill att &konversation; automatiskt ska ansluta till nätverket så fort du öppnar &konversation;. +Det här är en lista med &irc;-servrar i nätverket. Vid anslutning till nätverket, försöker &konversation; ansluta till den översta servern först. Om det misslyckas, försöker den med den andra servern. Om det misslyckas, försöker den med den tredje, och så vidare. Åtminstone en server måste anges. Klicka på en server för att markera den. +Använd de här knapparna för att lägga till en server, redigera en markerad server eller ta bort en markerad server. Du kan också justera servrarnas ordning, och på så sätt ordningen på anslutningsförsöken. +Valfritt. Det här är en lista över kanalerna du automatiskt går med i så fort &konversation; har anslutit till en server. Du kan lämna den tom om du inte vill gå med i några kanaler automatiskt. +Använd de här knapparna för att lägga till en kanal, redigera en markerad kanal eller ta bort en markerad kanal. Du kan också ändra ordningen som du går med i kanalerna. + + + +Undvik att blanda servrar på olika &irc;-nätverk under samma nätverk. Undvik att skriva in samma server under två olika nätverk. Annars fungerar inte &konversation;s integration med adressboken och bevakning av uppkopplade smeknamn riktigt. + + + + +När du klickar på knappen Lägg till i rutan Servrar, visas skärmen Lägg till server. + + + + Lägg till server + + + + + + + + + + + + + + Lägg till server + + + + + + + +Namnet eller IP-adressen till servern. En lista med servrar finns på irchelp.org. +Skriv in portnumret som krävs för att ansluta till servern. För de flesta servrar ska det vara 6667. +Om servern kräver ett lösenord för att ansluta, skriv in det här. Lämna det annars tomt. +Markera om du vill använda SSL-protokollet (Secure Socket Layer) för att kommunicera med servern. Det skyddar kommunikationen mellan din dator och &irc;-servern, och gör den privat. Servern måste stöda SSL-protokollet för att det ska fungera. I de flesta fall, om servern inte stöder SSL, misslyckas anslutningen. + + + + + +När du klickar på knappen Lägg till i rutan Gå med automatiskt i kanaler, visas skärmen Lägg till kanal. + + + + Lägg till kanal + + + + + + Lägg till kanal + + + + + +Skriv in ett kanalnamn. Glöm inte det inledande tecknet #. Om kanalen kräver ett lösenord för att gå med, skriv in det, lämna det annars tomt. + + + + + + +Lista över tillgängliga kanaler + +För att visa en lista med tillgängliga kanaler, välj Fönster Kanallista i huvudmenyn. Efter en varningsskärm skapas en ny flik som heter Kanallista. + + + +Fliken med kanallistan. + + + + + + + + + + + + + + + + Fliken med kanallistan. + + + + + + + + +Skriv in en filtersträng här. + +Här kan du begränsa kanallistan till de kanaler som har ett minimalt eller maximalt antal användare. Att välja 0 inaktiverar respektive kriterium. + +Klicka här för att hämta listan över kanaler från servern och tillämpa filtret. + +Den filtrerade listan med kanaler visas här. Observera att om du inte använder reguljära uttryck, listar &konversation; alla kanaler vars namn innehåller filtersträngen som du skrev in. Kanalnamnet behöver inte börja med strängen du skrev in. + +Välj en kanal som du vill gå med i genom att klicka på den. Högerklicka på kanalen för att få en lista med alla webbadresser som nämns i kanalens ämne. + +Klicka här för att gå med i en kanal. En ny flik skapas för kanalen. + + + + +Du ska undvika att klicka på knappen Uppdatera lista. De flesta servrar har tusentals kanaler, och att utföra det här ger hög last på servern. Dessutom kan det kräva flera minuter att utföra, beroende på din nätverksbandbredd. Om din klient är för långsam, kan servern till och med koppla ner dig. + +Ibland finns det "hemliga" kanaler på en server. Sådana kanaler listas inte i Kanallistan. Du kan fortfarande gå med i kanalerna om du känner till deras namn. Skriv i vilken inmatningsrad som helst, /join #kanalnamn. (Tecknet # krävs.) En ny flik skapas för kanalen. Om du går med i en kanal och smeknamnsrutan bara listar ditt smeknamn, betyder det att kanalen inte tidigare fanns. Servern skapade kanalen, och du är operatör. I detta fall vill du troligen stänga kanalen genom att skriva: /part. + + + + + + +En översikt över huvudskärmen + +Låt oss lära oss mer om huvudskärmen. Skärmen visas nedan med en kanalflik vald. + + + +Huvudskärmen. + + + + + + + + + + + + + + + + + + + Huvudskärmen + + + + + + + + +Det här kallas inmatningsraden. Den visas bara om aktuell flik är en kanal. För att skicka ett meddelande till alla i kanalen, skriv in meddelandet här och tryck på Enter. Meddelandet samt alla andras meddelanden syns i kanalfönstret ovanför. Varje meddelande inleds med tiden och användarens smeknamn. + + Du kan också klistra in text från klippbordet. Om den inklistrade texten har mer än en rad (nyrader), visas en dialogruta. Redigera texten enligt dina önskemål och klicka på Ok. + + Om den inklistrade texten är längre än 256 tecken, eller om den består av mer än en rad, visas ett varningsmeddelande som informerar dig om att långa inlägg kan orsaka återställningar av anslutningen och överfyllnad. Du kan fortfarande fortsätta med den inmatade texten, men det är inte en god idé att göra det, eftersom överfyllnad kan irritera övriga användare av kanalen, eller göra att du kopplas ner från servern. Det är bättre att skicka meddelandet i kortare delar. + + + + En konvention som används i många kanaler är att inleda meddelanden riktade till en användare med deras smeknamn. &konversation; tillhandahåller en bekväm funktion för att komplettera smeknamn. Börja skriva användarens smeknamn, tryck sedan på Tabulator. &konversation; kompletterar resten av användarens smeknamn, följt av ett kolon. För att anpassa kompletteringsfunktionen, välj Inställningar Anpassa Konversationi huvudmenyn, expandera Beteende, klicka på Allmänt och klicka på rutan Kompletteringsläge. + + Du kan också skriva in &irc;-kommandon här genom att först skriva / följt av ett giltigt &irc;-kommando. Se Ofta använda &irc;-kommandon. På vissa servrar kan du skriva /help för att få en lista med tillgängliga kommandon, eller skriva /help kommando för att få hjälp med ett angivet kommando. + + + +Du kan gå med i ytterligare servrar och kanaler. Varje server och kanal får en separat flik här. För att visa en lista med tillgängliga kanaler, se Lista över tillgängliga kanaler. För att gå med i en kanal, skriv: /join #kanalnamn på indataraden. (Tecknet # krävs.) För att lämna en kanal, skriv bara /part. Flikar visas också här om du öppnar en Kanallista, deltar i en privat konversation (fråga), öppnar en Webbadressinfångning eller öppnar en eller flera Terminaler. För att byta till en annan skärm, klicka på motsvarande flik, eller använd mushjulet för att gå igenom flikarna cykliskt. + +För att ställa in andra alternativ för flikar, välj Inställningar Anpassa Konversation i huvudmenyn, expandera Beteende och klicka på Allmänt. + + + +De här lamporna blinkar när det finns något du inte sett under fliken. En lampa blinkar långsammare när de enda meddelandena du inte sett är join, part, quit eller ändringar av smeknamn. De blinkar snabbare om det finns vanliga meddelanden du inte sett. Färgerna är följande: + + Kanal + + + Servermeddelanden, Kanallista eller Webbadressinfångning + + + Terminal eller DCC Status. + + + Privat meddelande (fråga). + + + + +Klicka här för att stänga aktuell flik. Stängs en kanalflik lämnas kanalen. Stängs en flik med servermeddelanden lämnas alla kanaler som du har gått med i, alla öppna frågekanaler på servern stängs och servern kopplas ner. + +Klicka på knappen för att ändra ditt eget smeknamn. Den visas bara när den aktuella fliken är en kanal. Välj Inställningar Anpassa Konversation i huvudmenyn, expandera Beteende, klicka på Chattfönster och avmarkera rutan Visa ruta för att ändra eget smeknamn för att dölja knappen. + +Kanalämnet visas här. Håll musen stilla på ämnet för att se det långa ämnet. Du kan ändra ämnet genom att klicka på knappen till vänster om ämnet. Välj Inställningar Anpassa Konversation i huvudmenyn, expandera Beteende, klicka på Chattfönster och avmarkera rutan Visa kanalämne för att dölja kanalämnen. + +Dessa knappar visar nuvarande status hos kanallägen. En knapp är nertryckt om läget är aktiverat. Om du har rätt privilegier kan du också ändra kanallägen genom att klicka på knapparna, eller genom att klicka på knappen till vänster om ämnet. Välj Inställningar Anpassa Konversation i huvudmenyn, expandera Beteende, klicka på Chattfönster och avmarkera rutan Visa kanallägesknappar för att dölja kanallägesknapparna. + + +Det här kallas smeknamnsrutan. Den visas så fort den aktuella fliken är en kanal. Den listar smeknamnen på alla användare som har gått med i kanalen, inklusive dig själv. Håll musen stilla över ett smeknamn för att visa ytterligare information om användaren. Du kan ändra hur ikoner visas intill varje smeknamn genom att ändra ikontemat för smeknamn. Se Anpassa smeknamnsteman för mer information. Temat Big Bullets, som visas på skärmen ovan, använder följande ikoner: + + + normal användare + + + + användare med röst. Användaren kan prata i en modererad kanal. + + + + deloperatör för kanalen + + + + operatör för kanalen + + + + kanalägare + + + + kanaladministratör + + + + + +Om en användare är borta, ritas dessutom ett litet rött kors i ikonens hörn. + +Klicka med högerknappen på vilket smeknamn som helst för att visa en sammanhangsberoende meny med åtgärder som du kan utföra med smeknamnet. Du kan till exempel skicka en fil till smeknamnet. Det här är också stället du kan koppla ihop ett smeknamn med en kontakt i adressboken. + +För att dölja smeknamnsrutan, välj Fönster Dölj smeknamnslista i huvudmenyn. + + + +De här kallas snabbknappar. Normalt visas de inte. För att visa dem, se Anpassa snabbknappar. Du kan ställa in deras definitioner till vilka kommandon du vill. + + + + +Observera: Du kan styra hur meddelanden visas för meddelanden som visas i kanal- och frågeflikar. Du kan till exempel ändra meddelandets färg, spela ett ljud när ett meddelande som innehåller en sträng tas emot, eller svara på meddelanden automatiskt. Se Färgläggning av meddelanden för mer information. + +Observera: Kanalnamn börjar ibland med &, +, eller !. Det första tecknet i ett kanalnamn avgör kanaltypen (RFC 2811) enligt följande: # - Vanliga kanaler. ! - Vanliga kanaler. & - Lokal. Kanaler som man bara kan gå med i från servern som är värd för kanalen. Alla andra kanaler kan man gå med i från vilken server som helst i nätverket. + - Kanaler som inte stöder kanallägen. Det betyder att inga lägen är aktiverade, med undantag av kanalflaggan 't' som är aktiverad. Kanalnamn kan vara upp till 50 tecken långa och innehålla alla tecken utom mellanslag, kommatecken och Ctrl+G. + + + + + + +Snabbanslutning + +Ibland vill du ansluta till en server utan besväret med att skapa en ny server i serverlistan. + +Välj Arkiv Snabbanslutning i huvudmenyn. Skärmen Snabbanslutning visas. + + + +Snabbanslutningsskärmen + + + + + + Snabbanslutningsskärmen + + + + + +Skriv in serveradressen i rutan Servervärddator, ditt önskade smeknamn i rutan Smeknamn och klicka på knappen Anslut. När &konversation; har anslutit till servern, skriv in kommandot /join #kanalnamn för att gå med i en kanal. + + + + + + +Ofta använda &irc;-kommandon + +Det följande är en kort lista med ofta använda &irc;-kommandon. Se RFC 2812 för en fullständig lista över alla kommandon, eller besök irchelp.org. För en lista med kommandon som hanteras speciellt av &konversation;, se &konversation;s kommandon. + + + + + +/help +Listar kommandon tillgängliga på aktuell server. Stöds inte av alla servrar. + + + +/help kommando +Tillhandahåller hjälp för kommando. Stöds inte av alla servrar. + + + +/join #kanal +Går med i #kanal. Om kanalen inte redan finns, skapas den och du blir kanaloperatör. + + + +/part +Lämnar aktuell kanal och stänger kanalfliken. + + + +/part #kanal +Lämnar #kanal och stänger motsvarande kanalflik. Synonym för /leave. + + + +/me meddelande +Skickar meddelande till kanalen föregått av ditt smeknamn. Om ditt smeknamn till exempel var Tux, skulle meddelandet Tux brygger en kopp te visas genom att skriva /me brygger en kopp te. Om de inte har filter för den här sortens meddelanden, ser alla användare dem. Den här sortens meddelanden används oftast för att uttrycka icke-verbal information, som ditt känslomässiga tillstånd just nu, eller vad du fysiskt sysslar med. Om du lämnar datorn en kort stund, använd kommandot /away istället. + + + +/away meddelande +Om någon försöker skicka dig ett privat meddelande eller inbjuda dig till en kanal, får de reda på att du är borta från din dator med meddelande. + + + +/away +Avbryter kommandot /away meddelande. + + + +/query smeknamn +Skapar en ny flik med användarens smeknamn för en privat konversation, vanligtvis känd på &irc; som en fråga. Allt som skrivs här syns bara hos dig och din partner. + + + +/msg smeknamn meddelande +Skickar meddelande till användaren med smeknamnet smeknamn. Bara smeknamn ser meddelandet. Använd /query för längre konversationer. + + + +/invite smeknamn +Inbjuder användaren med smeknamnet smeknamn att gå med i en kanal. Kommandot är särskilt användbart om kanalen enbart är öppen för inbjudna. + + + + + + + + + + +Privata konversationer (frågor) + +En privat konversation är en som bara du och en annan person kan se. Privata konversationer kallas "frågor" i &konversation;. För att starta en privat konversation, skriv /query smeknamn på vilken inmatningsrad som helst, där smeknamn är smeknamnet på personen som du vill prata med. Du kan också klicka med höger musknapp i smeknamnsrutan och välja Öppna frågekanal. En ny flik skapas.. Tillkännage dig genom att skicka ett meddelande. + +Frågekanaler är precis som andra kanaler, utom att bara du och den andra personen kan delta i kanalen. + +För att lämna frågekanalen, stäng bara fliken. Observera dock att om den andra personen skickar ett meddelande till i frågekanalen, öppnas fliken igen. + +För att lämna alla frågekanaler, välj Fönster Stäng alla öppna frågekanaler i huvudmenyn, eller tryck på F11. + +När någon annan öppnar en frågekanal till dig, skapar &konversation; en ny flik med deras smeknamn. Om du inte vill prata med personen, stäng fliken. + + + + + + +Ställa in meddelanden + +Meddelanden är åtgärder som &konversation; utför så fort en händelse inträffar. Antag att du låter &konversation; köra, men minimerad eller dold bakom andra programfönster på skrivbordet. Om någon vill kommunicera med dig, eller om en kompis går med i en kanal, vill du få reda på det. Meddelanden åstadkommer detta. + +För att anpassa meddelanden, välj Inställningar Anpassa meddelanden i huvudmenyn. Skärmen för meddelandeinställning visas. + +Klicka omedelbart på knappen Fler alternativ. + + + +Skärmen för meddelandeinställning. + + + + + + + + + + + + + Skärmen för meddelandeinställning + + + + + + + + +Klicka här för att välja en händelse. + +Markera de typer av meddelanden som du vill ska visas när händelsen inträffar. (Använd systembrickan för underrättelse om nytt meddelande gör att ikonen i systembrickan blinkar när händelsen inträffar.) + + + + +Upprepa genom att välja en annan händelse och markera önskat meddelande. När du har anpassat alla önskade meddelanden, klicka på knappen Verkställ. + + + + +När du väl har ställt in dina meddelanden, kan du aktivera eller inaktivera alla meddelandeåtgärder här. Du kan till exempel välja att spela ett ljud så fort ditt smeknamn nämns i ett meddelande. När du är vid datorn kan du inaktivera ljud, men medan du är borta från datorn men i närheten, kan du aktivera ljuden för att kunna bli uppmärksammad. + + + + +Du kan också själv bli underrättad när någon nämner ditt smeknamn i ett meddelande med &konversation;s färgläggningsfunktion. + + + + + + +Bevaka vem som är uppkopplad + +&konversation; håller dig informerad om när dina kompisar är anslutna till &irc;-nätverket. + +Du kan koppla ihop uppkopplade smeknamn med kontaktposter i adressboken. När du gör det, skrivs smeknamnet och &irc;-nätverket där smeknamnet är uppkopplat in i adressbokens kontakt. &irc;-nätverket lagras eftersom smeknamn är unika i ett enstaka &irc;-nätverk. Smeknamn i två olika &irc;-nätverk motsvarar inte nödvändigtvis samma person, men samma smeknamn på två olika servrar i samma &irc;-nätverk motsvarar samma person. + +Det här är orsaken till att det är viktigt att använda samma nätverk för alla servrar i samma &irc;-nätverk, när nätverk, servrar och kanaler att automatiskt gå med i definieras. + +Du kan också definiera smeknamn som du vill bevaka som inte finns i din adressbok. I det fallet har varje smeknamn också ett tillhörande &irc;-nätverk. Se nedan. + +För att aktivera funktionen för smeknamnsbevakning, välj Fönster Bevakade uppkopplade smeknamn i huvudmenyn. Skärmen Bevakade uppkopplade smeknamn visas. + + + + Bevakade uppkopplade smeknamn. + + + + + + + + + + + + + + + + Bevakade uppkopplade smeknamn + + + + + + + +Smeknamnen i bevakningslistan och även smeknamnen som hör ihop med poster i adressboken anges här. De anges under tillhörande &irc;-nätverk. Om inga smeknamn anges, har du antingen inte specificerat några smeknamn att bevaka, eller behöver du aktivera funktionen för smeknamnsbevakning (se nedan). Expandera varje uppkopplat smeknamn för att se en lista med kanaler som smeknamnet har gått med i. Ikonerna intill varje kanal är samma som ikonerna som visas i smeknamnsrutan på skärmarna med kanaler. +Informationen som är känd om smeknamnet visas här. När skärmen Bevakade uppkopplade smeknamn först visas, är informationen gles. Var åttonde sekund, skickas automatiskt kommandot WHOIS till servern för att begära information om smeknamn som inte har någon information. Det fortsätter till alla smeknamn har information. +Smeknamn som inte är anslutna till något av &irc;-nätverken du är ansluten till listas under Nerkopplade i listan. +Smeknamn som hör ihop med en kontaktpost i din adressbok har den här ikonen () intill informationen. +Använd knapparna för att koppla ihop ett smeknamn med en kontakt i din adressbok, ta bort en koppling, eller öppna adressboken för att redigera kontaktinformationen. Se Handbok Adressboken för ytterligare instruktioner om hur man använder &kde;:s adressbok. + + + +För att lägga till ytterligare smeknamn att bevaka, klicka på knappen Redigera bevakningslista. Då visas skärmen Bevakade smeknamn. + + + +Bevakade smeknamn + + + + + + + + + + + + + + + Bevakade smeknamn + + + + + + + + +Markera den här rutan för att aktivera funktionen smeknamnsbevakning. + +Om du vill att skärmen Bevakade uppkopplade smeknamn automatiskt ska visas när du startar &konversation;, markera den här rutan. + +Smeknamnen på användarna som du vill bevaka listas här. Varje smeknamn har ett tillhörande &irc;-nätverk. + +Klicka på de här knapparna för att lägga till eller ta bort smeknamn från listan. + +Funktionen Bevakade uppkopplade smeknamn fungerar genom att periodiskt fråga servern. Den här rutan anger hur ofta det sker. Undvik tal mindre än 20 sekunder, eftersom det orsakar onödigt stor last på servern. + +På skärmen Bevakade uppkopplade smeknamn ovan, kan du dubbelklicka på vilket smeknamn som helst, så skickas det här kommandot till servern. %u ersätts med smeknamnet. %n krävs i slutet av kommandot. + + + + +Klicka på knappen Ok när du är klar med att lägga till eller ta bort smeknamn. + +Observera: När du visar skärmen Bevakade uppkopplade smeknamn, kan det ta ett tag innan några smeknamn visas, innan &konversation; har frågat servern. Normalt lämnar du skärmen Bevakade uppkopplade smeknamn igång. + +&konversation; visar också meddelanden i alla kanaler så fort en användare i din Bevakningslista för smeknamn ansluter till eller kopplar ner från servern. Meddelandet ser ut så här: + +[17:52] [Underrättelse] psn är uppkopplad (irc.kde.org). + + + + + + +Färgläggning av meddelanden + +Du kan styra hur meddelanden visas på kanal- och frågeskärmar. + +För att aktivera färgläggningsfunktionen, välj Inställningar Anpassa &konversation; i huvudmenyn. Skärmen Redigera inställningar visas. + + + +Skärmen Färgläggning. + + + + + + + + + + + + + + + + + + + Skärmen Färgläggning + + + + + + + + +Klicka här för att välja skärmen Färgläggning. +Klicka här för att lägga till ett nytt objekt i Färgläggningslistan. När ett objekt i listan markeras, kan du redigera det i rutan nedanför. +Skriv in ett strängmönster här. Alla mottagna meddelanden som matchar mönstret, någonstans i meddelandet, aktiverar färgläggning av meddelandet. Om du har verktyget &kde;:s editor för reguljära uttryck installerad på systemet, är knappen till höger aktiverad. Klicka för att visa editorn, som hjälper dig att skapa mer komplicerade mönster. (&kde;:s editor för reguljära uttryck är en del av paketet kdeutils.) +Om mönstret hittas i ett meddelande, visas hela meddelandet med färgen du väljer här. +Om du vill kan &konversation; spela ett ljud när mönstret matchas. Klicka på knappen för att välja en ljudfil att spela. Klicka på testknappen för att höra ljudet. +Om du vill att &konversation; automatiskt ska skicka ett svarsmeddelande när mönstret matchas, skriv in meddelandet här. Använd funktionen med försiktighet eftersom du kan irritera &irc;-användare med för mycket prat om du inte är försiktig. Du kan också skriva in &irc;- eller &konversation;-kommandon här. +Om du har ställt in ljud för några av dina färgläggningar, kan du inaktivera alla genom att avmarkera rutan. +Om du markerar rutan, och någon nämner ditt smeknamn i ett meddelande, visas meddelandet med färgen som du väljer till höger. +Normalt gäller inte färgläggning för meddelanden du skriver in. Om du vill färglägga meddelanden du skriver in, markera rutan och välj en färg till höger. + + + + + + + + + +Anpassa meddelanden på skärmen (&osd;) + +Meddelanden på skärmen (OSD) är en unik funktion i &konversation;. När de är aktiverade, visas kanalmeddelanden på skrivbordets skärm, även om &konversation; är minimerad. Här är ett exempel på skärmmeddelanden i funktion. Meddelandet längst upp till vänster på skärmen är från &konversation;, som kör minimerad i systembrickan. + + + +Exempel på meddelanden på skärmen + + + + + + Exempel på meddelanden på skärmen + + + + + +För att aktivera meddelanden på skärmen, välj Inställningar Anpassa &konversation; i huvudmenyn. Skärmen Redigera inställningar visas. + + + +Meddelanden på skärmen. + + + + + + + + + + + + + + + Meddelanden på skärmen + + + + + + + + +Klicka här för att expandera objektet Underrättelse. + +Klicka här för att välja Meddelanden på skärmen. + +Markera den här rutan för att aktivera meddelanden på skärmen. + +Klicka på den här knappen för att välja teckensnitt för meddelanden på skärmen. (Observera: Alla teckensnitt fungerar inte. Det är känt att Luxi Sans 22 och Impact 22 fungerar.) + +Markera rutorna här för att välja typ av meddelanden som du vill ska visas på skärmen, och klicka därefter på knappen Verkställ. + + + + + + + + + +Skicka färglagda meddelanden + +Du kan lägga till färg till meddelanden du skickar i vilken kanal som helst. Börja skriva meddelandet på inmatningsraden för vilken kanal som helst. Klicka på knappen Infoga &irc;-färg knappen Infoga &irc;-färg eller välj Infoga &irc;-färg i huvudmenyn. Skärmen &irc;-färgväljare visas. + + + +Skärmen &irc;-färgväljare. + + + + + + Skärmen &irc;-färgväljare + + + + + +Välj en färg och klicka på Ok. Fortsätt att skriva in meddelandet på inmatningsraden. För att ändra färg igen, klicka på knappen Infoga &irc;-färg. Välj en annan färg och klicka på Ok. + + + + + + +Anpassa smeknamnsteman + +Du kan ändra ikonerna som visas intill smeknamn i smeknamnsrutan i kanalflikar. För att ändra smeknamnstema, välj Inställningar Anpassa Konversation i huvudmenyn. Skärmen Redigera inställningar visas. Klicka på Utseende för att expandera det, klicka därefter på Teman för att visa skärmen Teman. + + + +Skärmen Teman. + + + + + + + + + + + + + + Skärmen Teman + + + + + + + + +Klicka här för att välja skärmen Teman. +Välj ett tema. +Exempelikoner visas här med det valda temat. +Om du har laddat ner ett smeknamnstema någon annanstans ifrån, klicka för att installera det. + + + + + + + + + +Anpassa snabbknappar + +Du kan aktivera funktionen att visa snabbknapparhuvudskärmen. Då visas åtta snabbknappar. För att visa snabbknapparna, välj Inställningar Anpassa Konversation i huvudmenyn. Skärmen Redigera inställningar visas. Klicka på Utseende för att expandera det, och klicka på Chattfönster. Markera rutan Visa snabbknappar och kicka på Ok. + +Knapparna kan anpassas som du tycker för att utföra &irc;-kommandon som ofta används. För att anpassa snabbknapparna, välj Inställningar Anpassa Konversation i huvudmenyn. Skärmen Redigera inställningar visas. Klicka på Utseende för att expandera det, och klicka på Snabbknappar för att visa skärmen Snabbknappar. + + + +Skärmen Snabbknappar + + + + + + Skärmen Snabbknappar + + + + + +Det finns åtta snabbknappar. Klicka på en post för att ändra den. Kolumnen Knappnamn är namnet som visas på knappen på huvudskärmen. Håll namnen korta. Kolumnen Knapphändelse är åtgärden som utförs när du klickar på snabbknappen. Tips för att skapa åtgärder ges på skärmen. + +Klicka på Ok för att slutföra ändringarna. + +Exempel: + + + + + Knappnamn: Meddelande + + Knapphändelse: Msg %u (det är ett mellanslag efter %u) + + + + + +För att använda den här knappen på huvudskärmen, klicka på ett smeknamn i smeknamnsrutan, och klicka därefter på knappen. /MSG visas på inmatningsraden följt av det valda smeknamnet. Skriv in ett meddelande som du vill skicka till personen och tryck på Enter. Meddelandet skickas till användaren. Bara den användaren kommer att se meddelandet. + +Observera: Du kan inte lägga till eller ta bort snabbknappar. + + + + + + +Skicka och ta emot filer + +Du kan skicka filer via &irc; till andra uppkopplade användare, eller så kan de skicka filer till dig. + + +Varning: Öppna aldrig en fil någon skickar till dig om det inte är en pålitlig källa. Det kan vara ett virus. + + +För att skicka en fil till någon i en kanal, klicka med höger musknapp på personens smeknamn i smeknamnsrutanhuvudskärmen. Välj Skicka fil. En dialogruta visas så att du kan välja filen som ska skickas. Därefter visas en ny flik med DCC Status. + + + +Fliken DCC Status + + + + + + + + + + + + + Fliken DCC Status + + + + + + + + +Mottagarens smeknamn och filnamnet visas här. + + +Kolumnen Status anger status för sändningen eller mottagningen av filen enligt följande: + + + + + + Erbjuder + + + Du försöker skicka en fil till mottagaren. &konversation; väntar på att mottagaren ska acceptera filen. + + + + + Ansluter + + + &konversation; försöker upprätta en förbindelse med andra ändan. + + + + + Skickar + + + &konversation; skickar filen till andra ändan. + + + + + Tar emot + + + &konversation; tar emot filen från andra ändan. + + + + + Klar + + + Filen har överförts utan problem. + + + + + Avstannad + + + Överföringen har startats men går för närvarande inte vidare. + + + + + Avbruten + + + Antingen klickade du på knappen Avbryt, eller så avbröt den andra personen överföringen. + + + + + Misslyckad + + + Ett fel uppstod och överföringen lyckades inte. + + + + + Köad + + + Överföringen har accepterats och börjar när programvaran på mottagarsidan bekräftar. + + + + + Slår upp + + + &konversation; försöker hämta avsändarens IP-adress. + + + + + Fortsätter + + + När en överföring börjar men filen redan finns på användarens system, får användaren frågan Filen finns redan. Återuppta överföring? Denna status anger att användaren återupptog överföringen. + + + + + + + + +När någon vill skicka en fil till dig, skapas fliken DCC Status (om den inte redan skapats). Klicka på fliken DCC Status för att visa den. Klicka på filen för att markera den, och klicka därefter på den här knappen för att acceptera filen, så börjar överföringen. Observera: Du kan ställa in &konversation; att automatiskt acceptera sändningar från andra personer genom att välja Inställningar Anpassa Konversation DCC-inställningar i huvudmenyn. + + + + + +Om du har problem med att skicka eller ta emot filer, kanske din brandvägg blockerar DCC-portar. Se Vanliga frågor. + + + + + + +Integrering med adressboken. + +Du kan koppla ihop vilket smeknamn som helst med en kontakt i adressboken. När du väl har gjort det, visar &konversation; kontaktens riktiga namn inom parentes efter smeknamnet i smeknamnsrutan. + +För att koppla ihop ett smeknamn med en kontakt i adressboken, klicka med högerknappen på personens smeknamn i smeknamnsrutanhuvudskärmen. Välj Vem-är-det för att visa information som hjälper dig avgöra användarens riktiga namn. Klicka därefter med högerknappen på personens smeknamn och välj Adressbokskopplingar. En undermeny visas. Om smeknamnet inte redan är ihopkopplat med en kontakt, välj Skapa ny kontakt. Skärmen Redigera kontakt visas. + + + +Skärmen Redigera kontakt + + + + + + + + + + + + + Skärmen Redigera kontakt + + + + + + + + +Smeknamnet fylls automatiskt i här. Om du vet personens riktiga namn, ersätt smeknamnet med det riktiga namnet. + + +Observera att smeknamnet inte visas här. Istället, ... + + + +Klicka här. Fönstret Direktmeddelandeadresser visas. + + + + + + + Fönstret Direktmeddelandeadresser. + + + + + + Fönstret Direktmeddelandeadresser. + + + + + +Observera att &konversation; fyller i smeknamnet åt dig med protokollet IRC. + +Se Handbok Adressboken för ytterligare instruktioner om hur man använder &kde;:s adressbok. + +Fyll i eventuell ytterligare information om smeknamnet du känner till och klicka på Ok. Personens riktiga namn visas inom parenteser intill smeknamnet i smeknamnsrutan i &konversation;. Det riktiga namnet visas också när musen hålls stilla över smeknamnet. + +Så fort ett smeknamn har kopplats ihop med en kontakt i adressboken, kan du högerklicka på personens smeknamn i smeknamnsrutan och redigera tillhörande kontakt, koppla ihop smeknamnet med en annan kontakt, eller ta bort hopkopplingen. + +Om du har kopplat ihop ett smeknamn med en kontakt, och användaren ändrar sitt smeknamn medan du kör &konversation;, kopplas det nya smeknamnet automatiskt ihop med kontakten, och dessutom behålls den ursprungliga hopkopplingen. + +Om du kopplar ihop ett smeknamn i &irc; med en kontakt i &kopete;, visas också kopplingen i &konversation; och tvärtom. + +Observera: Det är möjligt att markera mer än ett smeknamn i smeknamnsrutan, klicka med musens högerknapp, och utföra flera hopkopplingar. + + + + + + +Fånga webbadresser i meddelanden + +Användare skickar ibland webbadresser till intressanta webbplatser eller andra resurser på webben, i vilken kanal som helst. Du kan dubbelklicka på alla sådana webbadresser så startar &konversation; programmet som hör ihop med webbadressen. Programmet som startas beror på &MIME;-typen som webbadressen har. Till exempel aktiveras din vanliga webbläsare i KDE för en webbadress som börjar med http:, och visar webbsidan. (Du kan också ange webbläsaren som ska användas.) Om webbadressen rullar förbi på skärmen, kan det vara svårt att hitta den igen. &konversation; kan spara en bekväm lista med alla webbadresser åt dig. För att aktivera funktionen, välj Fönster Webbadressinfångning i huvudmenyn. En ny flik som heter Webbadressinfångning skapas. + + + +Fliken Webbadressinfångning. + + + + + + + + + + + + + + + + Fliken Webbadressinfångning. + + + + + + + + +Det här är listan med webbadresser som synts sedan du startade &konversation;. Kolumnen Smeknamn är smeknamnet på personen som skickade webbadressen. Om smeknamnet är tomt, visades webbadressen under fliken Servermeddelanden. (Webbadresser som visas i meddelanden för att gå med eller lämna kanaler listas inte.) Klicka på en webbadress för att markera den. + +Klicka här för att aktivera programmet som hör ihop med den markerade webbadressen. Programmet som startas beror på &MIME;-typen som webbadressen har. Till exempel aktiveras din vanliga webbläsare för en webbadress som börjar med http:, och visar webbsidan. Du kan också ange webbläsaren som ska användas för webbsidor. + +Klicka här för att kopiera markerad webbadress till &kde;:s klippbord. + +Klicka här för att ta bort markerad webbadress från listan. + +Klicka här för att spara listan med webbadress i en fil. + +Klicka här för att rensa listan. + + + + + + + + + +Ställa in webbläsaren du föredrar + +När du klickar på en markerad webbadress någonstans i &konversation;, startas det förvalda &kde;-programmet som hör ihop med webbadressens MIME-typ. Om du till exempel klickar på en webbadress som börjar med http, startas &konqueror; för att visa webbsidan. Du kan ange ett program som skiljer sig från det förvalda &kde;-programmet. Du kan till exempel istället använda Mozilla. + +För att välja en annan webbläsare, använd Inställningar Anpassa &konversation; i huvudmenyn. Skärmen Redigera inställningar visas. + + + +Webbläsarskärmen + + + + + + + + + + + + + Webbläsarskärmen + + + + + + + + +Klicka här för att visa skärmen Webbläsare. + +Klicka här för att ange att du vill använda en egen webbläsare. + +Skriv in kommandot för att starta önskad webbläsare. När du klickar på en webbadress, ersätts %u med webbadressen. + + + + +Tips: (bara för &UNIX;-system) Förvalt kommando är mozilla '%u', som startar en ny instans av Mozilla varje gång du klickar på en webbadress. Om du föredrar att Mozilla visar webbsidan under en ny flik i en instans som redan kör, skapa en fil med följande innehåll: + + +#!/bin/sh +mozilla -remote "openURL($@, new-tab)" || exec mozilla "$@"; + + + +Namnge filen moz, lägg den någonstans i sökvägen från PATH, och gör den körbar (chmod a+x moz). Skriv därefter moz '%u' som webbläsarkommando på skärmen ovan. + +Observera: Inställningen Webbläsare gäller inte webbadresser med mailto:. Webbadresser med mailto: startar alltid &kde;:s förvalda e-postprogram. + +Klicka på Verkställ för att spara dina ändringar. Du måste återansluta till varje server och kanal för att ändringar ska få effekt. Det enklaste sättet att göra det är att avsluta &konversation; och starta om. + + + + + + +Markera kanal- och frågeloggar + +Du kan infoga en markering på skärmen för en kanal och en frågekanal för att hjälpa dig att snabbt lokalisera information. För att göra det, välj Infoga Komihåg-linje i huvudmenyn, eller tryck på &Ctrl;R. En linje visas längst ner i texten på skärmen. Linjen rullar med resten av texten på skärmen. + +För att få en komihåg-linje att infogas i alla kanaler och frågor samtidigt, välj Inställningar Anpassa Konversation i huvudmenyn, expandera Beteende, klicka på Chattfönster och markera rutan Visa en komihåg-linje för alla kanaler och frågor. + +För att få &konversation; att automatiskt infoga en komihåg-linje så fort du skickar kommandot /away meddelande, se Ställa in din identitet. + + + + + + +Loggning + +Om loggning är aktiverad, loggar &konversation; varje server, kanal och privat konversation (fråga). Varje session lagras i en loggfil på disk. När du öppnar samma session igen, lägger &konversation; till loggen. Loggen växer till en gräns som du kan ställa in (se nedan). När gränsen nås, kastas de äldsta meddelandena. + +Så fort du öppnar en session igen, läses ungefär de sista 1024 tecknen av föregående session från slutet av loggen och visas på skärmen. + +Medan sessionen pågår, rullar meddelanden bort längst upp på skärmen. Du kan rulla bakåt för att visa meddelandena. Slutligen, för att spara minne, tas de äldsta meddelandena bort från skärmen. Det kallas för historikgräns. Meddelanden som försvinner från skärmen på grund av denna historikgräns är fortfarande tillgängliga i loggfilen, om loggning är aktiverad. + +För att visa loggfilen för en session, klicka på sessionens flik för att göra den till aktuell session och välj Fönster Öppna loggfil i huvudmenyn. En ny flik öppnas som visar loggfilen. + + + +Loggfil + + + + + + + + + + + + + + + Loggfil + + + + + + + +Meddelanden från loggfilen visas här. De äldsta meddelandena är längst upp och de senaste längst ner. +Klicka på den här knappen för att spara loggfilen i en annan fil. +Klicka för att uppdatera visningen av loggfilen. Medan du tittar på en loggfil, läggs nya meddelanden i motsvarande session inte till automatiskt i visningen av loggfilen. Använd den här knappen för att titta på de senaste meddelandena. +Klicka för att rensa skärmen med loggfilen och ta bort loggfilen på disk. +Använd rutan för att ställa in maximal storlek på loggfilen. Inställningen får ingen effekt förrän du startar om &konversation;. Varje loggfil kan ha en separat inställning. + + + +Historikgränsen kan ändras genom att välja Inställningar Anpassa &konversation; i huvudmenyn, och därefter expandera Beteende och klicka på Chattfönster. Rutan Historikgräns visas på skärmen. Om du ställer in den till Obegränsad, tas inte meddelanden bort från skärmen. + +Du kan aktivera eller inaktivera loggning och ställa in andra loggningsalternativ genom att välja Inställningar Anpassa &konversation; i huvudmenyn, och därefter expandera Beteende och klicka på Loggning. + + + + + + +&konversation;s kommandon + +Följande kommandon tolkas av &konversation; och kan skilja sig från vanliga &irc;-kommandon. Väljare inom hakparenteser är valfria. Väljare åtskilda med ett vertikalt streck (|) är olika former av kommandot. Kommandon som inte listas här skickas till servern som de skrivs in. + + + + + +/me meddelande +Skickar meddelande till kanalen föregått av ditt smeknamn. Om ditt smeknamn till exempel var Tux, skulle meddelandet Tux brygger en kopp te visas genom att skriva /me brygger en kopp te. Om de inte har filter för den här sortens meddelanden, ser alla användare dem. Den här sortens meddelanden används oftast för att uttrycka icke-verbal information, som ditt känslomässiga tillstånd just nu, eller vad du fysiskt sysslar med. Om du lämnar datorn en kort stund, använd kommandot /away istället. + + + +/ame meddelande +Som /me kommandot ovan, utom att meddelandet skickas till alla kanaler och frågor som är öppna på alla servrar du har anslutit till i &konversation;. + + + +/join kanal [lösenord] +Går med i kanal. Om servern tillåter det, och om kanalen inte redan finns, skapas den och du blir kanaloperatör. Om kanalen kräver ett lösenord för att gå med, ange det som lösenord. De flesta kanalnamn börjar med #. + + + +/j kanal [lösenord] +Samma som /join ovan. + + + +/part [kanal] [orsak] +Lämnar kanal med orsak och stänger motsvarande kanalflik. Inne i en &konversation; kanal eller frågeflik, kan du bara skriva in /part vilket stänger kanalen eller frågan med din standardorsak som anges i Inställningar. + + +/leave [kanal] [orsak] +Samma som /part ovan. + + +/quit +När det skrivs in i någon kanalflik, frågeflik eller DCC-flik, kopplar ner från motsvarande server och stänger alla kanalflikar, frågeflikar eller DCC-flikar som är öppna för den servern. + + +/notice smeknamn|kanal meddelande +Skickar meddelande till användaren med smeknamnet smeknamn eller till alla i en kanal. Det följande är ett exempel på vad du ser i kanalfliken + +[17:14] [Notis] Skickar meddelande "Jag tror jag förstår" till #konversation + +Och det här är var mottagarna ser + +[17:15] [Notis] -Eisfuchs- Jag tror jag förstår + + + + +/query smeknamn +Skapar en ny flik med användarens smeknamn för en privat konversation, vanligtvis känd på IRC som en fråga. Allt som skrivs här syns bara hos dig och din frågepartner. Du kan skriva in mer än ett smeknamn, åtskilda med mellanslag, så öppnas en frågeflik för varje smeknamn. Varje sådan frågeflik är privat mellan dig och frågepartnern. + + + +/msg smeknamn|kanal meddelande +Skickar ett privat meddelande till användaren med smeknamnet smeknamn eller till alla användare i kanal. I motsats till /query öppnar det inte en ny flik. Om meddelande börjar med /me, formateras meddelandet på samma sätt som ett /me kommando. + +Exempel + +/msg Eisfuchs Jag behöver en del hjälp med kommandot msg + +/msg #konversation Ny version av Konvi är uppkopplad! + +/msg Eisfuchs /me kompilerar handboken just nu. + + + + + +/smsg smeknamn|kanal meddelande +Samma som /msg utom att meddelandet inte visas på din skärm. Det är användbart för att förhindra att lösenord och annan känslig information förblir synlig på din skärm eller loggas. + + + +/amsg smeknamn|kanal meddelande +Samma som /msg kommandot ovan, utom att meddelandet skickas till alla kanaler och frågor som du har öppnat på alla servrar du har anslutit till i &konversation;. + + + +/op smeknamn +När det skrivs in under en kanalflik, försöker ge smeknamn operatörsrättigheter för kanalen. Kanske inte fungerar om du saknar tillräckliga rättigheter i kanalen (du måste själv vara kanaloperatör). Du kan skriva in mer än ett smeknamn åtskilda med mellanslag. + + + +/deop smeknamn +När det skrivs in under en kanalflik, tar bort operatörsrättigheter från smeknamn. Du kan skriva in mer än ett smeknamn åtskilda med mellanslag. + + + +/oper [smeknamn] +Ger användaren med smeknamnet smeknamn &irc;-op rättigheter (administratör). Det fungerar bara om smeknamn listas på serverns O:-rad. En &irc;-op har rättigheter att utföra /kill för ett smeknamn, ansluta servrar till &irc;-nätverket med /connect med mera. Om smeknamn inte skrivs in, försöker ge dig själv &irc;-op rättigheter. Du blir tillfrågad om ditt &irc;-op användarnamn och lösenord i båda fallen. + + + +/voice smeknamn +I vissa kanaler (med +m flagga) kan inte användare skicka meddelanden om de inte har rösträttigheter. Det här kommandot försöker ge smeknamn rösträttigheter. Du måste ha kanaloperatörsrättigheter för att utföra kommandot. Kommandot används oftast när du är operatör på en modererad kanal. + + + +/unvoice smeknamn +Tar bort rösträttigheter från smeknamn i kanalen. + + + +/topic [kanal] [meddelande] +Försöker ändra ämnet i kanal till meddelande. När det skrivs in under en kanalflik, kan kanal utelämnas, och blir förvald till kanalen som är aktiv under fliken. Om meddelande utelämnas, visas kanalens nuvarande ämne. Ändra kanalens ämne kan misslyckas om du saknar tillräckliga rättigheter. + + + +/away orsak +Om någon försöker skicka dig ett privat meddelande eller inbjuda dig till en kanal, får de reda på att du är borta från din dator med orsak. För att ändra tillbaka ditt tillstånd till det normala, skriv in /away utan en orsak. + + + +/aaway orsak +Som kommandot /away ovan, utom att kommandot skickas till alla servrar du har anslutit till i &konversation;. + + + +/invite smeknamn [kanal] +Inbjuder användaren med smeknamnet smeknamn att gå med i kanal. Kommandot är särskilt användbart om kanalen enbart är öppen för inbjudna. När det skrivs in under en kanalflik kan kanal utelämnas. + + + +/exec skript [parametrar] +Kör ett skalskript som fungerar med &konversation; som heter skript, och skickar det parametrar. Se Styrning via skript för mer information om att använda och skriva skript. +Exempel: + +/exec kdeversion + +Skickar ditt systems &kde;- och &Qt;-versionsnummer till kanalen. + +/exec cmd uname -a + +Skickar din &Linux;-versionssträng till kanalen. + + + + + +/notify [smeknamn] +Lägger till eller tar bort smeknamn från listan Bevakade uppkopplade smeknamn. Om smeknamnet redan finns i listan, tas det bort. Om det inte finns i listan, läggs det till. Om smeknamn utelämnas, visas den nuvarande listan över bevakade smeknamn. + + + + +/prefs [list|grupp] [list|alternativ] [värde] +Visar eller ställer in inställningar i &konversation; utan att använda inställningsskärmen. Om en parameter innehåller mellanslag, omge den med citationstecken. + +Exempel: + +/prefs list + +listar tillgängliga alternativgrupper. + +/prefs "General Options" list + +listar alternativen tillgängliga i gruppenGeneral Options tillsammans med deras aktuella värden + +/prefs "General Options" ShowTrayIcon + +Visar nuvarande värde på inställningen som visar &konversation;s ikon i systembrickan. + +/prefs "General Options" ShowTrayIcon false + +Stänger av &konversation;s ikon i systembrickan. + + + + +/kick smeknamn orsak +När det skrivs in under en kanalflik, försöker sparka användaren med smeknamnet smeknamn från kanalen med orsak. Om orsak inte skrivs in, används standardorsaken från Inställningar. Kommandot får bara användas under en kanalflik. + + + +/ban [-host|-domain| -userhost|-userdomain] [kanal] användare|mask +Försöker bannlysa användare eller mask från kanal. När det skrivs in under en kanalflik, kan kanal utelämnas. För mer information om värddatorer, domäner och masker, se dokumenten på irchelp.org. För att hämta den nuvarande bannlysningslistan för en kanal, skriv in /mode kanal b. + + + +/unban [kanal] mönster +Återtar en tidigare bannlysning från en kanal. När det skrivs in under en kanalflik kan kanal utelämnas. + + + +/ignore [-all] smeknamn +Lägger till smeknamn i din ignorera-lista. Du kan ange mer än ett smeknamn åtskilda med mellanslag. Kanalmeddelanden från användare i din ignorera-lista visas inte. Dessutom om du skriver in -all, ignoreras alla typer av meddelanden från användaren (frågor, notiser, &CTCP;, DCC och undantag) förutom kanalmeddelanden. + + + +/quote kommando +Skickar kommando till servern. + + + +/say meddelande +När det skrivs in under en kanalflik, skickar meddelande till kanalen. Det här är samma sak som att skriva in meddelande på kanalens inmatningsrad. Användbart för att skicka &irc;-kommandon när du inte vill utföra kommandot. Två kommandotecken i rad (//) gör samma sak som /say. Används också av skript för att skicka meddelanden. + + + +/raw [open|close] +Ställer in serverloggen i obehandlat läge (open) eller avslutar obehandlat läge (close). Om varken open eller close skrivs in, är förvalt värde open. I obehandlat läge visar loggen alla meddelanden som tas emot från servern på riktigt &irc;-format. + + + +/konsole +Öppnar en ny flik som kör en &kde;-terminal. + + + +/server [webbadress] [lösenord] +Ansluter till servern på adress webbadress. Om webadress utelämnas, ansluter till servern som hör ihop med fliken där du skrev in kommandot. Det är användbart för att ansluta till en server igen om du blev nerkopplad. Om servern kräver ett lösenord för anslutning till den, skriv in det som lösenord. Om servern kräver ett annat portnummer än det förvalda (6667), skriv in webbadress så här: irc.kde.org:6665. + + + +/dcc SEND smeknamn [filnamn] +Skickar filnamn till användaren med smeknamnet smeknamn. Om filnamn utelämnas, visas en dialogruta så att du kan välja en fil. + + + +/dcc +Visar en DCC-statusflik + + + +/ctcp smeknamn|kanal ping +Skickar ett PING-meddelande till smeknamn eller kanal. Det är användbart för att avgöra om någon som du pratar med har en lång nätverksfördröjning eller (när det skickas till en kanal) om ditt system har en lång fördröjning. + + + +/ctcp smeknamn|kanal meddelande +Skickar ett meddelande till smeknamn eller alla använder i kanal. Det liknar kommandot /msg ovan, utom att meddelandet skickas med &CTCP;-protokollet. Svaret från andra sidan beror på &irc;-klientprogrammet användaren kör. Om du till exempel samtalar med en annan användare av &konversation;, returnerar /ctcp Eisfuchs TIME systemtiden på Eisfuchs dator. /ctcp Eisfuchs VERSION returnerar versionsnumret för &konversation; från Eisfuchs dator. + + + + + + + + + + +Styrning via skript + +&konversation; levereras med några praktiska skript som du kan köra från programmet. För att köra ett skript under en kanalflik, DCC-flik eller serverflik, skriv in ett kommando på formen + +/exec skript [parametrar] + +vilket kör ett skript som heter skript och skickar det (valfritt) parametrar. + +Skriv till exempel följande kommandon under en kanalflik + +/exec kdeversion + +för att skicka dina &kde;- och &Qt;-versionsnummer till kanalen. + +/exec cmd uname -a + +kör skriptet cmd, och skickar uname -a till det. Det skickar din &Linux;-versionssträng till kanalen. + +För att få en lista över alla tillgängliga skript, skriv in följande kommando i en terminal: + +ls $KDEDIR/share/apps/konversation/scripts + +Du kan skriva dina egna skript. Skript är skalskript och kan skrivas med vilket skalspråk som helst, som bash, perl eller python. När &konversation; kör ett skript, är de första tre parametrarna som skickas till skriptet: + + + +Portnumret för &irc;-servern under fliken där kommandot /exec skrevs in. + + +Serverns adress. + +Kanalnamnet. + + + +Här är ett exempel på ett skalskript (cmd). + + +#!/bin/sh + +# Kör ett kommando och skriver ut resultatet i Konversation. + +PORT=$1; +SERVER=$2; +TARGET=$3; +shift;shift;shift; + +$@ | while read line; do dcop $PORT Konversation say $SERVER "$TARGET" "$@: $line"; done + + + +Observera att skriptet använder DCOP för att kommunicera med &konversation;. Kommandot /say gör att utmatningen skickas till kanalen som ett normal meddelande. För att visa något under fliken utan att skicka det till andra användare, använd info istället. Titta i befintliga skriptfiler för mer exempel på att skriva skript. + +För att kunna köra ett skript som du har skrivit, måste du installera det genom att kopiera det till $KDEDIR/share/apps/konversation/scripts eller till $HOME/.kde/share/apps/konversation/scripts. Du måste också ge filen körrättigheter, till exempel med chmod a+x mitt_skript. + + + + + + + + +Kommandoreferens + + + + + + +Huvudfönstret i &konversation; + + +Menyn Arkiv + + + + F2 Arkiv Serverlista + Visar listan med servrar och kanaler. + + + F7 Arkiv Snabbanslutning + Visar skärmen Snabbanslutning för att ansluta till en server. + + + Arkiv Anslut igen + Ansluter igen till alla servrar som kopplades ner på grund av ett nätverksfel eller annat problem. + + + &Ctrl;J Arkiv Gå med i kanal + Visar en dialogruta där du kan skriva in namnet på en kanal att gå med i. Gör samma sak som att skriva in /join #kanalnamn i en kanal eller serverflik. + + + &Alt; &Ctrl;Q Arkiv Ange som borta globalt + Ändrar status för ditt smeknamn till frånvaro i alla kanaler. + + + &Ctrl;Q Arkiv Avsluta + Avslutar &konversation; + + + + + + +Menyn <guimenu +>Redigera</guimenu +> + + + + &Ctrl;F Redigera Sök + + Söker efter textsträngar på aktuell skärm. + + + + F3 Redigera Sök igen + + Söker igen efter textsträngar på aktuell skärm med användning av den föregående söksträngen. + + + + &Ctrl;L Redigera Töm fönster + + Tömmer aktuell skärm. + + + + &Ctrl; &Shift;L Redigera Töm alla fönsters + + Tömmer alla skärmar. + + + + + + + +Menyn <guimenu +>Infoga</guimenu +> + + + + &Ctrl;K Infoga &irc;-färg + + Se Skicka färglagda meddelanden. + + + + &Ctrl;R Infoga Komihåg-linje + + Se Markera kanal- och frågeloggar. + + + + &Alt; &Shift;C Infoga Specialtecken + + Används för att skriva in specialtecken, som tecken på främmande språk. + + + + + + + +Menyn <guimenu +>Bokmärken</guimenu +> + + + + &Ctrl;B Bokmärken Lägg till bokmärke + + Lägger till ett bokmärke för nuvarande nätverk och kanal + + + + Bokmärken Redigera bokmärken + + Öppnar bokmärkeseditorn + + + + Bokmärken Ny bokmärkeskatalog + + Skapar en ny bokmärkeskatalog + + + + + + + +Menyn <guimenu +>Inställningar</guimenu +> + + + + &Ctrl;M Inställningar Dölj menyrad + + Döljer huvudmenyn. Tryck på &Ctrl;M för att visa den igen. + + + + Inställningar Dölj verktygsrad + + Döljer verktygsraden. + + + + Inställningar Dölj statusrad + + Döljer statusraden längst ner på huvudskärmen. + + + + Inställningar Identiteter + Visar skärmen Identiteter för att ställa in din identifikationsinformation. + + + Inställningar Anpassa genvägar + + Låter dig ändra snabbtangenter i &konversation;. + + + + Inställningar Anpassa verktygsrader + + Låter dig lägga till eller ta bort knappar från verktygsraden i &konversation;. + + + + Inställningar Anpassa meddelanden + + Visar skärmen Meddelandeinställningar. + + + + Inställningar Anpassa &konversation; + + Visar skärmen Redigera inställningar. + + + + + + + +Menyn <guimenu +>Fönster</guimenu +> + + + + &Ctrl;. Fönster Föregående flik + + Visar skärmen som motsvarar föregående flik. + + + + &Ctrl;, Fönster Nästa flik + + Visar skärmen som motsvarar nästa flik. + + + + &Ctrl;W Fönster Stäng flik + + Stänger aktuell skärm. Om en kanal stängs, lämnas kanalen. Om en flik med Servermeddelanden stängs, stängs alla öppna kanaler på servern och servern kopplas ner. + + + + F11 Fönster Stäng alla öppna frågekanaler + + Stänger alla Privata konversationer (frågor). + + + + &Ctrl;H Fönster Dölj smeknamnslista + + Döljer (eller visar) rutan med smeknamn i kanalflikar. + + + + F4 Fönster Bevakade uppkopplade smeknamn + + Visar skärmen Bevakande uppkopplade smeknamn. Se Bevaka vem som är uppkopplad. + + + + F5 Fönster Kanaler + + Visar en lista över kanaler tillgängliga på servern. + + + + F6 Fönster Webbadressinfångning + + Visar skärmen Webbadressinfångning. + + + + Fönster Ny terminal + + Visar en terminalskärm. Du kan öppna så många terminalflikar som du vill. + + + + &Ctrl;O Fönster Öppna loggfil + + Visar en skärm med meddelandeloggen från aktuell flik. Fungerar bara för flikarna kanal, servermeddelanden och frågekanal. Loggning måste vara aktiverad med Inställningar Anpassa Konversation Loggning i huvudmenyn. + + + + + + + +Menyn <guimenu +>Hjälp</guimenu +> +&help.menu.documentation; + + + + + + + +Vanliga frågor +&reporting.bugs; &updating.documentation; + + + +När jag startar &konversation; vill jag ansluta till en server utan att gå med i några kanaler. Hur gör jag det? + + +Lämna rutan Kanaler tom på skärmen Redigera server. + + + + + +&konversation; ansluter inte till någon server. Vad är fel? + + +Det finns flera saker som kan vara fel. + + +Försäkra dig om att du har skrivit in rätt Servernamn och rätt Port på skärmen Lägg till server. + + +Kontrollera utmatningen på skärmen Servermeddelanden om det finns några felmeddelanden. Nekade servern till anslutningen på grund av ett felaktigt lösenord? Nekade servern till anslutningen eftersom den kräver IDENTD och din dator inte svarade på begäran om IDENT? Markerade du rutan SSL-protokoll, men servern stöder inte SSL? + + +Om du är bakom en brandvägg, försäkra dig om att riktiga portar är aktiverade. &konversation; kräver att följande portar är aktiverade: + + + +Utgående TCP 6667 (eller porten på servern som du anslöt till) +Inkommande TCP 113 (om servern kräver IDENTD) + + + + +För mer information om &irc;-anslutningsproblem, se irchelp.org. + + + + + + + + + +När jag går till Fönster Kanallista, kan jag inte välja alternativet. Vad beror det på? + + +Menyalternativet Fönster Kanallista är grått om en flik som inte är en kanal, t.ex. Bevakade uppkopplade smeknamn för närvarande visas. För att göra det valbart igen, gå tillbaka till en kanalflik eller serverfliken. + + + + + + + + + + +Tack till och licens + +&konversation; +Program copyright 2002-2005 av &konversation;-gruppen. +&konviwebsite; + +Bidragsgivare: +Dario Abatianni eisfuchs@tigress.com +Peter Simonsson psn@linux.se +Christian Muehlhaeuser chris@chris.de +John Tapsel john@geola.geo.uk +Ismail Donmez ismail.donmez@boun.edu.tr +Shintaro Matsuoka shin@shoegazed.org +Gary Cramblitt garycramblitt@comcast.net +Matthias Gierlings gismore@users.sourceforge.net +&Alex.Zepeda; garbanzo@hooked.net +Stanislav Karchebny berkus@users.sourceforge.net +Mickael Marchand marchand@kde.org + + + +Tack till: +Michael Goettsche michael.goettsche@kdemail.net +Benjamin Meyer ben+konversation@kdemail.net +Jacub Stachowski qbast@go2.pl +Sabastian Sariego segfault@kde.cl +Olivier Bedard www.konversation.org hosting +Frauke Oster frauke@frsv.de +Lucijan Busch lucijan@kde.org +Sascha Cunz mail@sacu.de +Steve Wollkind steve@njord.org +Thomas Nagy thomas.nagy@eleve.emn.fr +Tobias Olry tobias.olry@web.de +Ruud Nabben r.nabben@gawab.com + + + +Dokumentation Copyright © 2003-2005 Gary R. Cramblitt garycramblitt@comcast.net + +Översättning Stefan Asserhäll stefan.asserhall@comhem.se +&underFDL; &underGPL; + + +Installation + + + + +Hur man skaffar &konversation; +&install.intro.documentation; Den senaste versionen av &konversation;, inklusive källkod och bygginstruktioner kan också hämtas från &konviwebsite; hemsida. + + + + + + +Krav + + + +För att använda &konversation; med lyckat resultat behöver du &kde; 3.2 eller senare, och en nätverksanslutning. För tidigare &kde;-versioner kan vissa funktioner saknas. Om du kommer att köra &konversation; bakom en brandvägg, se Vanliga frågor. Om du vill använda SSL-protokollet, kanske du behöver OpenSSL. + + + + +&documentation.index; +
+ + diff --git a/doc/sv/kimproxy_create_screen2.png b/doc/sv/kimproxy_create_screen2.png new file mode 100644 index 0000000..bdfe978 Binary files /dev/null and b/doc/sv/kimproxy_create_screen2.png differ diff --git a/doc/sv/kimproxy_create_screen_co.png b/doc/sv/kimproxy_create_screen_co.png new file mode 100644 index 0000000..d86b127 Binary files /dev/null and b/doc/sv/kimproxy_create_screen_co.png differ diff --git a/doc/sv/logviewer_co.png b/doc/sv/logviewer_co.png new file mode 100644 index 0000000..060da4a Binary files /dev/null and b/doc/sv/logviewer_co.png differ diff --git a/doc/sv/nicksonline_co.png b/doc/sv/nicksonline_co.png new file mode 100644 index 0000000..22fbc21 Binary files /dev/null and b/doc/sv/nicksonline_co.png differ diff --git a/doc/sv/nickthemes_screen_co.png b/doc/sv/nickthemes_screen_co.png new file mode 100644 index 0000000..2b3421a Binary files /dev/null and b/doc/sv/nickthemes_screen_co.png differ diff --git a/doc/sv/notification_screen_co.png b/doc/sv/notification_screen_co.png new file mode 100644 index 0000000..f039025 Binary files /dev/null and b/doc/sv/notification_screen_co.png differ diff --git a/doc/sv/notifylist_screen_co.png b/doc/sv/notifylist_screen_co.png new file mode 100644 index 0000000..38743ed Binary files /dev/null and b/doc/sv/notifylist_screen_co.png differ diff --git a/doc/sv/osd_demo.png b/doc/sv/osd_demo.png new file mode 100644 index 0000000..8256151 Binary files /dev/null and b/doc/sv/osd_demo.png differ diff --git a/doc/sv/osd_screen_co.png b/doc/sv/osd_screen_co.png new file mode 100644 index 0000000..9455413 Binary files /dev/null and b/doc/sv/osd_screen_co.png differ diff --git a/doc/sv/quickbuttons_screen.png b/doc/sv/quickbuttons_screen.png new file mode 100644 index 0000000..e83ae07 Binary files /dev/null and b/doc/sv/quickbuttons_screen.png differ diff --git a/doc/sv/quickconnect_screen.png b/doc/sv/quickconnect_screen.png new file mode 100644 index 0000000..ec248f0 Binary files /dev/null and b/doc/sv/quickconnect_screen.png differ diff --git a/doc/sv/serverlist_co.png b/doc/sv/serverlist_co.png new file mode 100644 index 0000000..1c826af Binary files /dev/null and b/doc/sv/serverlist_co.png differ diff --git a/doc/sv/urlcatcher_screen_co.png b/doc/sv/urlcatcher_screen_co.png new file mode 100644 index 0000000..1508aec Binary files /dev/null and b/doc/sv/urlcatcher_screen_co.png differ diff --git a/doc/sv/webbrowser_screen_co.png b/doc/sv/webbrowser_screen_co.png new file mode 100644 index 0000000..1df054b Binary files /dev/null and b/doc/sv/webbrowser_screen_co.png differ diff --git a/konversation/Makefile.am b/konversation/Makefile.am new file mode 100644 index 0000000..4641e7b --- /dev/null +++ b/konversation/Makefile.am @@ -0,0 +1,19 @@ +SUBDIRS = src images scripts +EXTRA_DIST = AUTHORS COPYING ChangeLog INSTALL README TODO + +messages: rc.cpp + $(EXTRACTRC) `find . -name "*.rc" -o -name "*.ui" -o -name "*.kcfg"` > rc.cpp +# we haven't got a tips file atm, so there isn't a lot of point in making one... +# maybe someone will document the process of writing tips files, or tell me that +# it needs to be done +# $(PREPARETIPS) > tips.cpp + LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name *.cxx -o -name \*.ecpp -o -name \*.C`; \ + if test -n "$$LIST"; then \ + $(XGETTEXT) $$LIST -o $(podir)/konversation.pot; \ + fi +# rm -f tips.cpp + rm -f rc.cpp + + +include $(top_srcdir)/admin/Doxyfile.am + diff --git a/konversation/NEWS b/konversation/NEWS new file mode 100644 index 0000000..1e542ef --- /dev/null +++ b/konversation/NEWS @@ -0,0 +1,5 @@ +Mon Jul 14 08:40:00 CEST 2008 +- Konversation now depends on KDE 3.5 + +Tue Jan 17 16:11:00 CEST 2006 +- Konversation now depends on KDE 3.4 diff --git a/konversation/configure.files b/konversation/configure.files new file mode 100644 index 0000000..dc6867b --- /dev/null +++ b/konversation/configure.files @@ -0,0 +1,3 @@ +./admin/configure.in.min +configure.in.in + diff --git a/konversation/configure.in.in b/konversation/configure.in.in new file mode 100644 index 0000000..d6d72da --- /dev/null +++ b/konversation/configure.in.in @@ -0,0 +1,48 @@ +#MIN_CONFIG(3.2) +CXXFLAGS="$CXXFLAGS $KDE_DEFAULT_CXXFLAGS" + +KDE_CHECK_HEADER(knotifyclient.h, + [ + AC_DEFINE(USE_KNOTIFY, 1, [Define if you have KNotify] ) + ]) + + +KDE_CHECK_HEADER(kimiface.h, + [ + AC_DEFINE(HAVE_KIMIFACE, 1, [Define if you have Kimiface headers] ) + LIB_KIMIFACE="-lkimproxy" + AC_SUBST(LIB_KIMIFACE) + ]) + +# Check for XScreenSaver +AC_CHECK_HEADERS(tgmath.h)xss_save_ldflags="$LDFLAGS" +LDFLAGS="$X_LDFLAGS" + +LIB_XSS= + +KDE_CHECK_HEADER(X11/extensions/scrnsaver.h, + [ + AC_CHECK_LIB(Xext,XScreenSaverQueryInfo, + [ + AC_DEFINE(HAVE_XSCREENSAVER, 1, [Define if you have the XScreenSaver extension]) + LIB_XSS="-lXext" + ], + [ + ld_shared_flag= + KDE_CHECK_COMPILER_FLAG(shared, [ld_shared_flag="-shared"]) + AC_CHECK_LIB(Xss,XScreenSaverQueryInfo, + [ + AC_DEFINE(HAVE_XSCREENSAVER, 1, [Define if you have the XScreenSaver extension]) + LIB_XSS="-lXss" + ], + [], + [ $ld_shared_flag $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS ]) + ], + [ $X_PRE_LIBS -lX11 $X_EXTRA_LIBS ]) + ], [], + [ + #include + ] ) + +AC_SUBST(LIB_XSS) +LDFLAGS="$xss_save_ldflags" diff --git a/konversation/images/Makefile.am b/konversation/images/Makefile.am new file mode 100644 index 0000000..e565828 --- /dev/null +++ b/konversation/images/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = icons nickicons diff --git a/konversation/images/icons/Makefile.am b/konversation/images/icons/Makefile.am new file mode 100644 index 0000000..e5515a8 --- /dev/null +++ b/konversation/images/icons/Makefile.am @@ -0,0 +1 @@ +KDE_ICON = AUTO diff --git a/konversation/images/icons/README-kimproxy b/konversation/images/icons/README-kimproxy new file mode 100644 index 0000000..e0bf8eb --- /dev/null +++ b/konversation/images/icons/README-kimproxy @@ -0,0 +1,5 @@ +These are the icons that are shown in kaddressbook, kmail etc for konversation contacts. +This icons are provided via the kimiface dcop interface. + +The icons were created by Seba y Loretito (aka segfault2k). + diff --git a/konversation/images/icons/cr16-action-kimproxyaway.png b/konversation/images/icons/cr16-action-kimproxyaway.png new file mode 100644 index 0000000..cf7d168 Binary files /dev/null and b/konversation/images/icons/cr16-action-kimproxyaway.png differ diff --git a/konversation/images/icons/cr16-action-kimproxyoffline.png b/konversation/images/icons/cr16-action-kimproxyoffline.png new file mode 100644 index 0000000..c35816e Binary files /dev/null and b/konversation/images/icons/cr16-action-kimproxyoffline.png differ diff --git a/konversation/images/icons/cr16-action-kimproxyonline.png b/konversation/images/icons/cr16-action-kimproxyonline.png new file mode 100644 index 0000000..7252280 Binary files /dev/null and b/konversation/images/icons/cr16-action-kimproxyonline.png differ diff --git a/konversation/images/icons/cr22-action-char.png b/konversation/images/icons/cr22-action-char.png new file mode 100644 index 0000000..76917d5 Binary files /dev/null and b/konversation/images/icons/cr22-action-char.png differ diff --git a/konversation/images/icons/cr22-action-kimproxyaway.png b/konversation/images/icons/cr22-action-kimproxyaway.png new file mode 100644 index 0000000..dc1dc66 Binary files /dev/null and b/konversation/images/icons/cr22-action-kimproxyaway.png differ diff --git a/konversation/images/icons/cr22-action-kimproxyoffline.png b/konversation/images/icons/cr22-action-kimproxyoffline.png new file mode 100644 index 0000000..56c8270 Binary files /dev/null and b/konversation/images/icons/cr22-action-kimproxyoffline.png differ diff --git a/konversation/images/icons/cr22-action-kimproxyonline.png b/konversation/images/icons/cr22-action-kimproxyonline.png new file mode 100644 index 0000000..1c0ecd6 Binary files /dev/null and b/konversation/images/icons/cr22-action-kimproxyonline.png differ diff --git a/konversation/images/icons/cr22-action-konv_message.png b/konversation/images/icons/cr22-action-konv_message.png new file mode 100644 index 0000000..66b2771 Binary files /dev/null and b/konversation/images/icons/cr22-action-konv_message.png differ diff --git a/konversation/images/icons/cr32-action-kimproxyaway.png b/konversation/images/icons/cr32-action-kimproxyaway.png new file mode 100644 index 0000000..016c0fe Binary files /dev/null and b/konversation/images/icons/cr32-action-kimproxyaway.png differ diff --git a/konversation/images/icons/cr32-action-kimproxyoffline.png b/konversation/images/icons/cr32-action-kimproxyoffline.png new file mode 100644 index 0000000..52f2c2d Binary files /dev/null and b/konversation/images/icons/cr32-action-kimproxyoffline.png differ diff --git a/konversation/images/icons/cr32-action-kimproxyonline.png b/konversation/images/icons/cr32-action-kimproxyonline.png new file mode 100644 index 0000000..53308ff Binary files /dev/null and b/konversation/images/icons/cr32-action-kimproxyonline.png differ diff --git a/konversation/images/icons/crsc-action-kimproxyaway.svgz b/konversation/images/icons/crsc-action-kimproxyaway.svgz new file mode 100644 index 0000000..473befc Binary files /dev/null and b/konversation/images/icons/crsc-action-kimproxyaway.svgz differ diff --git a/konversation/images/icons/crsc-action-kimproxyoffline.svgz b/konversation/images/icons/crsc-action-kimproxyoffline.svgz new file mode 100644 index 0000000..b983517 Binary files /dev/null and b/konversation/images/icons/crsc-action-kimproxyoffline.svgz differ diff --git a/konversation/images/icons/crsc-action-kimproxyonline.svgz b/konversation/images/icons/crsc-action-kimproxyonline.svgz new file mode 100644 index 0000000..ffb4f42 Binary files /dev/null and b/konversation/images/icons/crsc-action-kimproxyonline.svgz differ diff --git a/konversation/images/icons/crsc-action-konv_message.svgz b/konversation/images/icons/crsc-action-konv_message.svgz new file mode 100644 index 0000000..fc42686 Binary files /dev/null and b/konversation/images/icons/crsc-action-konv_message.svgz differ diff --git a/konversation/images/icons/hi128-app-konversation.png b/konversation/images/icons/hi128-app-konversation.png new file mode 100644 index 0000000..3ca81d8 Binary files /dev/null and b/konversation/images/icons/hi128-app-konversation.png differ diff --git a/konversation/images/icons/hi16-app-konversation.png b/konversation/images/icons/hi16-app-konversation.png new file mode 100644 index 0000000..360ca30 Binary files /dev/null and b/konversation/images/icons/hi16-app-konversation.png differ diff --git a/konversation/images/icons/hi22-app-konversation.png b/konversation/images/icons/hi22-app-konversation.png new file mode 100644 index 0000000..6da9b6a Binary files /dev/null and b/konversation/images/icons/hi22-app-konversation.png differ diff --git a/konversation/images/icons/hi32-app-konversation.png b/konversation/images/icons/hi32-app-konversation.png new file mode 100644 index 0000000..7a85d5f Binary files /dev/null and b/konversation/images/icons/hi32-app-konversation.png differ diff --git a/konversation/images/icons/hi48-app-konversation.png b/konversation/images/icons/hi48-app-konversation.png new file mode 100644 index 0000000..4d0b066 Binary files /dev/null and b/konversation/images/icons/hi48-app-konversation.png differ diff --git a/konversation/images/icons/hi64-app-konversation.png b/konversation/images/icons/hi64-app-konversation.png new file mode 100644 index 0000000..b10e66f Binary files /dev/null and b/konversation/images/icons/hi64-app-konversation.png differ diff --git a/konversation/images/icons/hisc-app-konversation.svgz b/konversation/images/icons/hisc-app-konversation.svgz new file mode 100644 index 0000000..27dcd1f Binary files /dev/null and b/konversation/images/icons/hisc-app-konversation.svgz differ diff --git a/konversation/images/nickicons/Makefile.am b/konversation/images/nickicons/Makefile.am new file mode 100644 index 0000000..32c7af8 --- /dev/null +++ b/konversation/images/nickicons/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = alternative christmas classic default smiling square oxygen diff --git a/konversation/images/nickicons/alternative/Makefile.am b/konversation/images/nickicons/alternative/Makefile.am new file mode 100644 index 0000000..78b04ec --- /dev/null +++ b/konversation/images/nickicons/alternative/Makefile.am @@ -0,0 +1,3 @@ +konversationicondir = $(kde_datadir)/konversation/themes/alternative +konversationicon_DATA = irc_admin.png irc_away.png irc_halfop.png irc_normal.png irc_op.png \ + irc_owner.png irc_voice.png index.desktop diff --git a/konversation/images/nickicons/alternative/index.desktop b/konversation/images/nickicons/alternative/index.desktop new file mode 100644 index 0000000..cb7baa2 --- /dev/null +++ b/konversation/images/nickicons/alternative/index.desktop @@ -0,0 +1,57 @@ +[Desktop Entry] +Type=Theme +Name=Big Bullets +Name[bg]=Големи орнаменти +Name[br]=Melloù bras +Name[cs]=Velké odrážky +Name[de]=Große Kugeln +Name[el]=Μεγάλα Bullet +Name[fi]=Isot luettelomerkit +Name[fr]=Grosse balles +Name[he]=עיגולים גדולים +Name[hi]=बिग बुलेट्स +Name[ja]=ビュレット +Name[ka]=დიდი ტყვიები +Name[lt]=Dideli ženkliukai +Name[pa]=ਵੱਡੀਆਂ ਬਿੰਦੀਆਂ +Name[pt_BR]=Bolas grandes +Name[sr]=Велики предзнаци +Name[sr@Latn]=Veliki predznaci +Name[sv]=Stora punkter +Name[ta]=பெரிய புள்ளிகள் +Name[tr]=Büyük Mermiler +Name[uk]=Великі крапки +Name[xx]=xxBig Bulletsxx +Name[zh_CN]=圆点 +Comment="Big Bullets" by Dario Abatianni +Comment[ar]="Big Bullets" من Dario Abatianni +Comment[bg]="Големи орнаменти" от Dario Abatianni +Comment[ca]="Big Bullets" per Dario Abatianni +Comment[cs]=Velké odrážky od Daria Abatianniho +Comment[da]="Big Bullets" af Dario Abatianni +Comment[de]="Big Bullets" von Dario Abatianni +Comment[el]="Μεγάλα Bullet" από Dario Abatianni +Comment[es]=«Big Bullets» de Dario Abatianni +Comment[et]="Big Bullets" (autor Dario Abatianni) +Comment[fi]="Isot luettelomerkit" (Dario Abatianni) +Comment[fr]=« Grosses balles » par Dario Abatianni +Comment[ga]="Big Bullets" le Dario Abatianni +Comment[gl]="Big Bullets" por Dario Abatianni +Comment[he]="עיגולים גדולים" של Dario Abatianni +Comment[hi]="बिग बुलेट्स" दारियो अबातिआनी द्वारा +Comment[it]=«Big Bullets» di Dario Abatianni +Comment[ja]=Dario Abatianni 作のビュレットテーマ +Comment[ka]="დიდი ტყვიები" დარიო აბატიანის მიერ +Comment[lt]=„Dideli ženkliukai“, sukurti Dario Abatianni +Comment[nl]="Big Bullets", door Dario Abatianni +Comment[pt]="Big Bullets" por Dario Abatianni +Comment[pt_BR]="Bolas grandes" de Dario Abatianni +Comment[sr]=„Велики предзнаци“ од Дарија Абатијанија (Dario Abatianni) +Comment[sr@Latn]=„Veliki predznaci“ od Darija Abatijanija (Dario Abatianni) +Comment[sv]="Stora punkter" av Dario Abatianni +Comment[ta]="Big Bullets" டாரியோ அபடையானி +Comment[tr]=Dario Abatianni tarafından "Büyük Mermiler" +Comment[uk]="Великі крапки" - Dario Abatianni +Comment[xx]=xx"Big Bullets" by Dario Abatiannixx +Comment[zh_CN]=“圆点”,由 Dario Abatianni 设计 +Comment[zh_TW]="Big Bullets",由 Dario Abatianni 撰寫 diff --git a/konversation/images/nickicons/alternative/irc_admin.png b/konversation/images/nickicons/alternative/irc_admin.png new file mode 100644 index 0000000..d071f6f Binary files /dev/null and b/konversation/images/nickicons/alternative/irc_admin.png differ diff --git a/konversation/images/nickicons/alternative/irc_away.png b/konversation/images/nickicons/alternative/irc_away.png new file mode 100644 index 0000000..381982e Binary files /dev/null and b/konversation/images/nickicons/alternative/irc_away.png differ diff --git a/konversation/images/nickicons/alternative/irc_halfop.png b/konversation/images/nickicons/alternative/irc_halfop.png new file mode 100644 index 0000000..fab9b15 Binary files /dev/null and b/konversation/images/nickicons/alternative/irc_halfop.png differ diff --git a/konversation/images/nickicons/alternative/irc_normal.png b/konversation/images/nickicons/alternative/irc_normal.png new file mode 100644 index 0000000..89b9dd2 Binary files /dev/null and b/konversation/images/nickicons/alternative/irc_normal.png differ diff --git a/konversation/images/nickicons/alternative/irc_op.png b/konversation/images/nickicons/alternative/irc_op.png new file mode 100644 index 0000000..d8b849f Binary files /dev/null and b/konversation/images/nickicons/alternative/irc_op.png differ diff --git a/konversation/images/nickicons/alternative/irc_owner.png b/konversation/images/nickicons/alternative/irc_owner.png new file mode 100644 index 0000000..b52668a Binary files /dev/null and b/konversation/images/nickicons/alternative/irc_owner.png differ diff --git a/konversation/images/nickicons/alternative/irc_voice.png b/konversation/images/nickicons/alternative/irc_voice.png new file mode 100644 index 0000000..8090ad3 Binary files /dev/null and b/konversation/images/nickicons/alternative/irc_voice.png differ diff --git a/konversation/images/nickicons/christmas/Makefile.am b/konversation/images/nickicons/christmas/Makefile.am new file mode 100644 index 0000000..4c1aa5c --- /dev/null +++ b/konversation/images/nickicons/christmas/Makefile.am @@ -0,0 +1,3 @@ +konversationicondir = $(kde_datadir)/konversation/themes/christmas +konversationicon_DATA = irc_admin.png irc_away.png irc_halfop.png irc_normal.png irc_op.png \ + irc_owner.png irc_voice.png index.desktop diff --git a/konversation/images/nickicons/christmas/index.desktop b/konversation/images/nickicons/christmas/index.desktop new file mode 100644 index 0000000..c3ae670 --- /dev/null +++ b/konversation/images/nickicons/christmas/index.desktop @@ -0,0 +1,68 @@ +[Desktop Entry] +Type=Theme +Name=Christmas Theme +Name[ar]=سمة Christmas +Name[bg]=Коледна тема +Name[br]=Giz Nedeleg +Name[ca]=Tema nadalenc +Name[cs]=Vánoční téma +Name[da]=Juletema +Name[de]=Weihnachtsdesign +Name[el]=Χριστουγεννιάτικο θέμα +Name[es]=Tema navideño +Name[et]=Jõuluteema +Name[fi]=Jouluteema +Name[fr]=Thème de Noël +Name[gl]=Tema de Nadal +Name[he]=ערכת חג מולד +Name[it]=Tema natalizio +Name[ja]=クリスマス +Name[ka]=საშობაო გაფორმება +Name[lt]=Kalėdinė tema +Name[nl]=Kerstthema +Name[pa]=ਕਰਿਸਮਿਸ ਸਰੂਪ +Name[pt]=Tema de Natal +Name[pt_BR]=Tema de Natal +Name[ru]=Рождественская +Name[sr]=Божићна тема +Name[sr@Latn]=Božićna tema +Name[sv]=Jultema +Name[ta]=கிறிஸ்துமஸ் பொருள் +Name[tr]=Noel Teması +Name[uk]=Різдвяна тема +Name[xx]=xxChristmas Themexx +Name[zh_CN]=耶诞节主题 +Name[zh_TW]=聖誕主題 +Comment="Christmas Theme" by Kenichiro Takahashi +Comment[ar]=سمة "Christmas Theme" من Kenichiro Takahashi +Comment[bg]="Коледна тема" от Kenichiro Takahashi +Comment[br]=« Giz Nedeleg » gant Kenichiro Takahashi +Comment[ca]="Tema nadalenc" per Kenichiro Takahashi +Comment[cs]=Vánoční téma od Kenichiro Takahashi +Comment[da]="Juletema" af Kenichiro Takahashi +Comment[de]="Christmas Theme" von Kenichiro Takahashi +Comment[el]="Χριστουγεννιάτικο θέμα" από Kenichiro Takahashi +Comment[es]=«Tema navideño» de Kenichiro Takahashi +Comment[et]="Jõuluteema" (autor Kenichiro Takahashi) +Comment[fi]="Jouluteema" (Kenichiro Takahashi) +Comment[fr]=« Thème de Noël » par Kenichiro Takahashi +Comment[ga]="Christmas Theme" le Kenichiro Takahashi +Comment[gl]="Tema de Nadal" por Kenichiro Takahashi +Comment[he]="ערכת חג מולד " של Kenichiro Takahashi +Comment[it]=«Tema natalizio» di Kenichiro Takahashi +Comment[ja]=Kenichiro Takahashi 作のクリスマステーマ +Comment[ka]="საშობაო გაფორმება" კენიჩირო ტაკაჰაშის მიერ +Comment[lt]=„Kalėdinė tema“, sukurta Kenichiro Takahashi +Comment[nl]="Christmas Theme" door Kenichiro Takahashi +Comment[pt]="Tema de Natal" por Kenichiro Takahashi +Comment[pt_BR]="Tema de Natal" de Kenichiro Takahashi +Comment[ru]=Сделал Kenichiro Takahashi +Comment[sr]=„Божићна тема“ од Кеничира Такахашија (Kenichiro Takahashi) +Comment[sr@Latn]=„Božićna tema“ od Keničira Takahašija (Kenichiro Takahashi) +Comment[sv]="Jultema" av Kenichiro Takahashi +Comment[ta]="Christmas Theme" கெனிசிரோ டகாஹாஷி +Comment[tr]=Kenichiro Takahashi tarafından "Noel Teması" +Comment[uk]="Різдвяна тема" - Kenichiro Takahashi +Comment[xx]=xx"Christmas Theme" by Kenichiro Takahashixx +Comment[zh_CN]=“耶诞节主题”,由 Kenichiro Takahashi 设计 +Comment[zh_TW]="聖誕"主題,由 Kenichiro Takahashi 撰寫 diff --git a/konversation/images/nickicons/christmas/irc_admin.png b/konversation/images/nickicons/christmas/irc_admin.png new file mode 100644 index 0000000..ef64b8d Binary files /dev/null and b/konversation/images/nickicons/christmas/irc_admin.png differ diff --git a/konversation/images/nickicons/christmas/irc_away.png b/konversation/images/nickicons/christmas/irc_away.png new file mode 100644 index 0000000..e36e7ba Binary files /dev/null and b/konversation/images/nickicons/christmas/irc_away.png differ diff --git a/konversation/images/nickicons/christmas/irc_halfop.png b/konversation/images/nickicons/christmas/irc_halfop.png new file mode 100644 index 0000000..130c552 Binary files /dev/null and b/konversation/images/nickicons/christmas/irc_halfop.png differ diff --git a/konversation/images/nickicons/christmas/irc_normal.png b/konversation/images/nickicons/christmas/irc_normal.png new file mode 100644 index 0000000..ce45e5c Binary files /dev/null and b/konversation/images/nickicons/christmas/irc_normal.png differ diff --git a/konversation/images/nickicons/christmas/irc_op.png b/konversation/images/nickicons/christmas/irc_op.png new file mode 100644 index 0000000..c4608ff Binary files /dev/null and b/konversation/images/nickicons/christmas/irc_op.png differ diff --git a/konversation/images/nickicons/christmas/irc_owner.png b/konversation/images/nickicons/christmas/irc_owner.png new file mode 100644 index 0000000..c18bff4 Binary files /dev/null and b/konversation/images/nickicons/christmas/irc_owner.png differ diff --git a/konversation/images/nickicons/christmas/irc_voice.png b/konversation/images/nickicons/christmas/irc_voice.png new file mode 100644 index 0000000..5043867 Binary files /dev/null and b/konversation/images/nickicons/christmas/irc_voice.png differ diff --git a/konversation/images/nickicons/classic/Makefile.am b/konversation/images/nickicons/classic/Makefile.am new file mode 100644 index 0000000..343835b --- /dev/null +++ b/konversation/images/nickicons/classic/Makefile.am @@ -0,0 +1,3 @@ +konversationicondir = $(kde_datadir)/konversation/themes/classic +konversationicon_DATA = irc_admin.png irc_away.png irc_halfop.png irc_normal.png irc_op.png \ + irc_owner.png irc_voice.png index.desktop diff --git a/konversation/images/nickicons/classic/index.desktop b/konversation/images/nickicons/classic/index.desktop new file mode 100644 index 0000000..5191fd9 --- /dev/null +++ b/konversation/images/nickicons/classic/index.desktop @@ -0,0 +1,70 @@ +[Desktop Entry] +Type=Theme +Name=Classic Theme +Name[ar]=سمة كلاسيكية +Name[bg]=Класическа тема +Name[br]=Giz da gustum +Name[ca]=Tema clàssic +Name[cs]=Klasické téma +Name[da]=Klassisk tema +Name[de]=Klassisches Design +Name[el]=Κλασικό θέμα +Name[es]=Tema clásico +Name[et]=Klassikaline teema +Name[fi]=Klassinen teema +Name[fr]=Thème classique +Name[ga]=Téama Clasaiceach +Name[gl]=Tema Clásico +Name[he]=הערכה הישנה והטובה +Name[hi]=क्लासिक प्रसंग +Name[it]=Tema classico +Name[ja]=クラシック +Name[ka]=კლასიკური გაფორმება +Name[lt]=Klasikinė tema +Name[nl]=Klassiek thema +Name[pa]=ਟਕਸਾਲੀ ਸਰੂਪ +Name[pt]=Tema Clássico +Name[pt_BR]=Tema Clássico +Name[ru]=Классическая +Name[sr]=Класична тема +Name[sr@Latn]=Klasična tema +Name[sv]=Klassiskt tema +Name[ta]=சிறந்த தலைப்பு +Name[tr]=Klasik tema +Name[uk]=Класична тема +Name[xx]=xxClassic Themexx +Name[zh_CN]=经典主题 +Name[zh_TW]=傳統式主題 +Comment="LED" by Dario Abatianni +Comment[ar]="LED" من Dario Abatianni +Comment[bg]="LED" от Dario Abatianni +Comment[br]=« LED » gant Dario Abatianni +Comment[ca]="LED" per Dario Abatianni +Comment[cs]=LED od Daria Abatianniho +Comment[da]="LED" af Dario Abatianni +Comment[de]="LED" von Dario Abatianni +Comment[el]="LED" από Dario Abatianni +Comment[es]=«LED» de Dario Abatianni +Comment[et]="LED" (autor Dario Abatianni) +Comment[fi]="LEDit" (Dario Abatianni) +Comment[fr]=« LED » par Dario Abatianni +Comment[ga]="LED" le Dario Abatianni +Comment[gl]="LED" led Dario Abatianni +Comment[he]="LED" של Dario Abatianni +Comment[hi]="एलईडी" दारियो अबातिआनी द्वारा +Comment[it]=«LED» di Dario Abatianni +Comment[ja]=Dario Abatianni 作の LED テーマ +Comment[ka]="LED" დარიო აბატიანის მიერ +Comment[lt]=„LED“, sukurta Dario Abatianni +Comment[nl]="LED", door Dario Abatianni +Comment[pt]="LED" por Dario Abatianni +Comment[pt_BR]="LED" de Dario Abatianni +Comment[sr]=„LED“ од Дарија Абатијанија (Dario Abatianni) +Comment[sr@Latn]=„LED“ od Darija Abatijanija (Dario Abatianni) +Comment[sv]="Lampor" av Dario Abatianni +Comment[ta]="LED" டைரியோ அபடியானி +Comment[tr]=Dario Abatianni tarafından "LED" +Comment[uk]="LED" - Dario Abatianni +Comment[xx]=xx"LED" by Dario Abatiannixx +Comment[zh_CN]=“指示灯”,由 Dario Abatianni 设计 +Comment[zh_TW]="LED" 由 Dario Abatianni 撰寫 diff --git a/konversation/images/nickicons/classic/irc_admin.png b/konversation/images/nickicons/classic/irc_admin.png new file mode 100644 index 0000000..6a04b69 Binary files /dev/null and b/konversation/images/nickicons/classic/irc_admin.png differ diff --git a/konversation/images/nickicons/classic/irc_away.png b/konversation/images/nickicons/classic/irc_away.png new file mode 100644 index 0000000..ba569b1 Binary files /dev/null and b/konversation/images/nickicons/classic/irc_away.png differ diff --git a/konversation/images/nickicons/classic/irc_halfop.png b/konversation/images/nickicons/classic/irc_halfop.png new file mode 100644 index 0000000..b4bc2ce Binary files /dev/null and b/konversation/images/nickicons/classic/irc_halfop.png differ diff --git a/konversation/images/nickicons/classic/irc_normal.png b/konversation/images/nickicons/classic/irc_normal.png new file mode 100644 index 0000000..78b9be4 Binary files /dev/null and b/konversation/images/nickicons/classic/irc_normal.png differ diff --git a/konversation/images/nickicons/classic/irc_op.png b/konversation/images/nickicons/classic/irc_op.png new file mode 100644 index 0000000..539a97d Binary files /dev/null and b/konversation/images/nickicons/classic/irc_op.png differ diff --git a/konversation/images/nickicons/classic/irc_owner.png b/konversation/images/nickicons/classic/irc_owner.png new file mode 100644 index 0000000..cdb0aa4 Binary files /dev/null and b/konversation/images/nickicons/classic/irc_owner.png differ diff --git a/konversation/images/nickicons/classic/irc_voice.png b/konversation/images/nickicons/classic/irc_voice.png new file mode 100644 index 0000000..dd103a2 Binary files /dev/null and b/konversation/images/nickicons/classic/irc_voice.png differ diff --git a/konversation/images/nickicons/default/Makefile.am b/konversation/images/nickicons/default/Makefile.am new file mode 100644 index 0000000..10886c0 --- /dev/null +++ b/konversation/images/nickicons/default/Makefile.am @@ -0,0 +1,3 @@ +konversationicondir = $(kde_datadir)/konversation/themes/default +konversationicon_DATA = irc_admin.png irc_away.png irc_halfop.png irc_normal.png irc_op.png \ + irc_owner.png irc_voice.png index.desktop diff --git a/konversation/images/nickicons/default/index.desktop b/konversation/images/nickicons/default/index.desktop new file mode 100644 index 0000000..d0c1222 --- /dev/null +++ b/konversation/images/nickicons/default/index.desktop @@ -0,0 +1,69 @@ +[Desktop Entry] +Type=Theme +Name=Default Theme +Name[ar]=السِمة الإفتراضية +Name[bg]=Стандартна тема +Name[br]=Giz dre ziouer +Name[ca]=Tema per omissió +Name[cs]=Výchozí téma +Name[da]=Standardtema +Name[de]=Standard-Design +Name[el]=Προκαθορισμένο θέμα +Name[es]=Tema predeterminado +Name[et]=Vaiketeema +Name[fi]=Oletusteema +Name[fr]=Thème par défaut +Name[ga]=Téama Réamhshocraithe +Name[gl]=Tema por omisión +Name[he]=ערכת ברירת מחדל +Name[hi]=डिफ़ॉल्ट प्रसंग +Name[it]=Tema predefinito +Name[ja]=標準テーマ +Name[ka]=ნაგულისხმები გაფორმება +Name[lt]=Numatyta tema +Name[nl]=Standaardthema +Name[pa]=ਮੂਲ ਸਰੂਪ +Name[pt]=Tema Predefinido +Name[pt_BR]=Tema Padrão +Name[ru]=Стандартная +Name[sr]=Подразумевана тема +Name[sr@Latn]=Podrazumevana tema +Name[sv]=Standardtema +Name[ta]=முன்னிருப்பு தலைப்பு +Name[tr]=Öntanımlı tema +Name[uk]=Типова тема +Name[xx]=xxDefault Themexx +Name[zh_CN]=默认页面 +Name[zh_TW]=預設主題 +Comment="Simplistic" by Shintaro Matsuoka +Comment[ar]="Simplistic" من Shintaro Matsuoka +Comment[bg]="Опростена" от Shintaro Matsuoka +Comment[ca]="Simplistic" per Shintaro Matsuoka +Comment[cs]=Jednoduché téma od Shintara Matsuoky +Comment[da]="Simplistic" af Shintaro Matsuoka +Comment[de]="Simplistic" von Shintaro Matsuoka +Comment[el]="Απλοϊκό" από Shintaro Matsuoka +Comment[es]=«Simplistic» de Shintaro Matsuoka +Comment[et]="Simplistic" (autor Shintaro Matsuoka) +Comment[fi]="Yksinkertainen" (Shintaro Matsuoka) +Comment[fr]=« Simpliste » par Shintaro Matsuoka +Comment[ga]="Simplistic" le Shintaro Matsuoka +Comment[gl]="Simples" por Shintaro Matsuoka +Comment[he]="מראה פשוט" של Shintaro Matsuoka +Comment[hi]="सिम्प्लिस्टिक" शिनतारो मात्सुओका द्वारा +Comment[it]=«Simplistic» di Shintaro Matsuoka +Comment[ja]=Shintaro Matsuoka 作のシンプルなテーマ +Comment[ka]="Simplistic" შინტარო მაცუოკას მიერ +Comment[lt]=„Supaprastinta“, sukurta Shintaro Matsuoka +Comment[nl]="Simplistic", door Shintaro Matsuoka +Comment[pt]="Simplistic" por Shintaro Matsuoka +Comment[pt_BR]="Simplista" de Shintaro Matsuoka +Comment[sr]=„Једноставно“ од Шинтара Мацуоке (Shintaro Matsuoka) +Comment[sr@Latn]=„Jednostavno“ od Šintara Macuoke (Shintaro Matsuoka) +Comment[sv]="Förenklat" av Shintaro Matsuoka +Comment[ta]="Simplistic" ஷிண்டாரோ மாட்சொக்கா +Comment[tr]=Shintaro Matsuoka tarafından "Basitlik" +Comment[uk]="Проста" - Shintaro Matsuoka +Comment[xx]=xx"Simplistic" by Shintaro Matsuokaxx +Comment[zh_CN]=“简洁”,由 Shintaro Matsuoka 设计 +Comment[zh_TW]="Simplistic" 由 Shintaro Matsuoka 撰寫 diff --git a/konversation/images/nickicons/default/irc_admin.png b/konversation/images/nickicons/default/irc_admin.png new file mode 100644 index 0000000..dc4cfc8 Binary files /dev/null and b/konversation/images/nickicons/default/irc_admin.png differ diff --git a/konversation/images/nickicons/default/irc_away.png b/konversation/images/nickicons/default/irc_away.png new file mode 100644 index 0000000..1a209e2 Binary files /dev/null and b/konversation/images/nickicons/default/irc_away.png differ diff --git a/konversation/images/nickicons/default/irc_halfop.png b/konversation/images/nickicons/default/irc_halfop.png new file mode 100644 index 0000000..3494353 Binary files /dev/null and b/konversation/images/nickicons/default/irc_halfop.png differ diff --git a/konversation/images/nickicons/default/irc_normal.png b/konversation/images/nickicons/default/irc_normal.png new file mode 100644 index 0000000..3402cf3 Binary files /dev/null and b/konversation/images/nickicons/default/irc_normal.png differ diff --git a/konversation/images/nickicons/default/irc_op.png b/konversation/images/nickicons/default/irc_op.png new file mode 100644 index 0000000..8dd62fb Binary files /dev/null and b/konversation/images/nickicons/default/irc_op.png differ diff --git a/konversation/images/nickicons/default/irc_owner.png b/konversation/images/nickicons/default/irc_owner.png new file mode 100644 index 0000000..289ee21 Binary files /dev/null and b/konversation/images/nickicons/default/irc_owner.png differ diff --git a/konversation/images/nickicons/default/irc_voice.png b/konversation/images/nickicons/default/irc_voice.png new file mode 100644 index 0000000..2ea8713 Binary files /dev/null and b/konversation/images/nickicons/default/irc_voice.png differ diff --git a/konversation/images/nickicons/oxygen/Makefile.am b/konversation/images/nickicons/oxygen/Makefile.am new file mode 100644 index 0000000..66ef8e5 --- /dev/null +++ b/konversation/images/nickicons/oxygen/Makefile.am @@ -0,0 +1,3 @@ +konversationicondir = $(kde_datadir)/konversation/themes/oxygen +konversationicon_DATA = irc_admin.png irc_away.png irc_halfop.png irc_normal.png irc_op.png \ + irc_owner.png irc_voice.png index.desktop diff --git a/konversation/images/nickicons/oxygen/index.desktop b/konversation/images/nickicons/oxygen/index.desktop new file mode 100644 index 0000000..07796da --- /dev/null +++ b/konversation/images/nickicons/oxygen/index.desktop @@ -0,0 +1,22 @@ +[Desktop Entry] +Type=Theme +Name=Oxygen Theme +Name[da]=Oxygen-tema +Name[de]=Oxygen-Design +Name[et]=Oxygeni teema +Name[it]=Tema Oxygen +Name[ja]=Oxygen テーマ +Name[sr]=Кисеоник тема +Name[sr@Latn]=Kiseonik tema +Name[sv]=Oxygen-tema +Name[zh_TW]=Oxygen 主題 +Comment="Oxygen" by Nuno Pinheiro +Comment[da]="Oxygen" af Nuno Pinheiro +Comment[de]="Oxygen" von Nuno Pinheiro +Comment[et]="Oxygen" (autor Nuno Pinheiro) +Comment[it]=«Oxygen» di Nuno Pinheiro +Comment[ja]=Nuno Pinheiro 作の Oxygen テーマ +Comment[sr]=„Кисеоник“ од Нуна Пињеира +Comment[sr@Latn]=„Kiseonik“ od Nuna Pinjeira +Comment[sv]="Oxygen" av Nuno Pinheiro +Comment[zh_TW]="Oxygen",由 Nuno Pinheiro 提供 diff --git a/konversation/images/nickicons/oxygen/irc_admin.png b/konversation/images/nickicons/oxygen/irc_admin.png new file mode 100644 index 0000000..0f94c26 Binary files /dev/null and b/konversation/images/nickicons/oxygen/irc_admin.png differ diff --git a/konversation/images/nickicons/oxygen/irc_away.png b/konversation/images/nickicons/oxygen/irc_away.png new file mode 100644 index 0000000..9569339 Binary files /dev/null and b/konversation/images/nickicons/oxygen/irc_away.png differ diff --git a/konversation/images/nickicons/oxygen/irc_halfop.png b/konversation/images/nickicons/oxygen/irc_halfop.png new file mode 100644 index 0000000..a3ae78f Binary files /dev/null and b/konversation/images/nickicons/oxygen/irc_halfop.png differ diff --git a/konversation/images/nickicons/oxygen/irc_normal.png b/konversation/images/nickicons/oxygen/irc_normal.png new file mode 100644 index 0000000..1ad0090 Binary files /dev/null and b/konversation/images/nickicons/oxygen/irc_normal.png differ diff --git a/konversation/images/nickicons/oxygen/irc_op.png b/konversation/images/nickicons/oxygen/irc_op.png new file mode 100644 index 0000000..308beba Binary files /dev/null and b/konversation/images/nickicons/oxygen/irc_op.png differ diff --git a/konversation/images/nickicons/oxygen/irc_owner.png b/konversation/images/nickicons/oxygen/irc_owner.png new file mode 100644 index 0000000..3fb0969 Binary files /dev/null and b/konversation/images/nickicons/oxygen/irc_owner.png differ diff --git a/konversation/images/nickicons/oxygen/irc_voice.png b/konversation/images/nickicons/oxygen/irc_voice.png new file mode 100644 index 0000000..7bfdb40 Binary files /dev/null and b/konversation/images/nickicons/oxygen/irc_voice.png differ diff --git a/konversation/images/nickicons/smiling/Makefile.am b/konversation/images/nickicons/smiling/Makefile.am new file mode 100644 index 0000000..8b92cf0 --- /dev/null +++ b/konversation/images/nickicons/smiling/Makefile.am @@ -0,0 +1,3 @@ +konversationicondir = $(kde_datadir)/konversation/themes/smiling +konversationicon_DATA = irc_admin.png irc_away.png irc_halfop.png irc_normal.png irc_op.png \ + irc_owner.png irc_voice.png index.desktop diff --git a/konversation/images/nickicons/smiling/index.desktop b/konversation/images/nickicons/smiling/index.desktop new file mode 100644 index 0000000..f749f61 --- /dev/null +++ b/konversation/images/nickicons/smiling/index.desktop @@ -0,0 +1,70 @@ +[Desktop Entry] +Type=Theme +Name=Smiling Theme +Name[ar]=سمة ضاحِكة ( Smiling ) +Name[bg]=Тема "Усмивка" +Name[br]=Giz Mousc'hoarzh +Name[ca]=Tema Smiling +Name[cs]=Smajlíkové téma +Name[da]=Smilende tema +Name[de]=Smiley-Design +Name[el]=Θέμα χαμόγελου +Name[es]=Tema «Smiling» +Name[et]=Naerusuuteema +Name[fi]=Hymiöteema +Name[fr]=Thème sourire +Name[ga]=Téama "Smiling" +Name[gl]=Tema Sorrinte +Name[he]=ערכה מחייכת +Name[hi]=मुस्कुराता प्रसंग +Name[it]=Tema sorridente +Name[ja]=スマイリー +Name[ka]=მომღიმარი გაფორმება +Name[lt]=Besišypsanti tema +Name[nl]=Smiling-thema +Name[pa]=ਖੁਸ਼ ਸਰੂਪ +Name[pt]=Tema "Smiling" +Name[pt_BR]=Tema Sorridente +Name[ru]=Улыбочки +Name[sr]=Насмејана тема +Name[sr@Latn]=Nasmejana tema +Name[sv]=Leende tema +Name[ta]=சிரிக்கின்ற பொருள் +Name[tr]=Gülümseyen Tema +Name[uk]=Тема посмішок +Name[xx]=xxSmiling Themexx +Name[zh_CN]=微笑主题 +Name[zh_TW]=微笑主題 +Comment="Smiling" stolen from Kopete by John Tapsell +Comment[ar]=أخِذ "Smiling" من Kopete من قِبل John Tapsell +Comment[bg]=Тема "Усмивка" е откраднато от Kopete от John Tapsell +Comment[ca]="Smiling" robat del Kopete per John Tapsell +Comment[cs]=Smajlíkové téma od Johna Tapsella převzato z Kopete +Comment[da]="Smilende" stjålet fra Kopete af John Tapsell +Comment[de]="Smiling" geklaut bei Kopete von John Tapsell +Comment[el]="Χαμόγελο" κλεμμένο από το Kopete από John Tapsell +Comment[es]=«Smiling» tomado de Kopete por John Tapsell +Comment[et]="Smiling" (Kopetest hiivas John Tapsell) +Comment[fi]="Hymiöteema" Kopetesta (John Tapsell) +Comment[fr]=« Sourire » volé à Kopete par John Tapsell +Comment[ga]="Smiling", goidte ó Kopete ag John Tapsell +Comment[gl]="Sorriso" roubado de Kopete por John Tapsell +Comment[he]="ערכה מחייכת" נגנבה מ־Kopete על ידי John Tapsell +Comment[hi]="मुस्कान" को के-ऑप्टी से जॉन तापसेल द्वारा चुराया गया +Comment[it]=«Sorridente» rubato a Kopete da John Tapsell +Comment[ja]=John Tapsell 作の Kopete のテーマを借用 +Comment[ka]="მომღიმარი" მოპარულია Kopete-დან ჯონ ტაპსელის მიერ +Comment[lt]=„Besišypsanti tema“, John Tapsell pavogta iš Kopete programos +Comment[nl]="Smiling", overgenomen van Kopete, door John Tapsell +Comment[pt]="Smiling" retirado do Kopete por John Tapsell +Comment[pt_BR]="Sorridente" roubado do Kopete por John Tapsell +Comment[ru]=Украл у Kopete John Tapsell +Comment[sr]=„Насмејано“ украо из Kopete-а Џон Тапсел (John Tapsell) +Comment[sr@Latn]=„Nasmejano“ ukrao iz Kopete-a Džon Tapsel (John Tapsell) +Comment[sv]="Leende" stulen från Kopete av John Tapsell +Comment[ta]=Kopeteல் இருந்து "Smiling" ஸ்டோலன் ஜான் டாப்செல் +Comment[tr]=John Tapsell tarafından Kopete'in "Gülümseyen"i +Comment[uk]="Посмішки" взято з Kopete - John Tapsell +Comment[xx]=xx"Smiling" stolen from Kopete by John Tapsellxx +Comment[zh_CN]=“微笑”,借鉴自 John Tapsell 为 Kopete 设计的造型 +Comment[zh_TW]="微笑"主題,從 Kopete 偷來的,由 John Tapsell 撰寫 diff --git a/konversation/images/nickicons/smiling/irc_admin.png b/konversation/images/nickicons/smiling/irc_admin.png new file mode 100644 index 0000000..7b259d5 Binary files /dev/null and b/konversation/images/nickicons/smiling/irc_admin.png differ diff --git a/konversation/images/nickicons/smiling/irc_away.png b/konversation/images/nickicons/smiling/irc_away.png new file mode 100644 index 0000000..3a3f3c2 Binary files /dev/null and b/konversation/images/nickicons/smiling/irc_away.png differ diff --git a/konversation/images/nickicons/smiling/irc_halfop.png b/konversation/images/nickicons/smiling/irc_halfop.png new file mode 100644 index 0000000..2335545 Binary files /dev/null and b/konversation/images/nickicons/smiling/irc_halfop.png differ diff --git a/konversation/images/nickicons/smiling/irc_normal.png b/konversation/images/nickicons/smiling/irc_normal.png new file mode 100644 index 0000000..2224c37 Binary files /dev/null and b/konversation/images/nickicons/smiling/irc_normal.png differ diff --git a/konversation/images/nickicons/smiling/irc_op.png b/konversation/images/nickicons/smiling/irc_op.png new file mode 100644 index 0000000..a9317a2 Binary files /dev/null and b/konversation/images/nickicons/smiling/irc_op.png differ diff --git a/konversation/images/nickicons/smiling/irc_owner.png b/konversation/images/nickicons/smiling/irc_owner.png new file mode 100644 index 0000000..fb7e483 Binary files /dev/null and b/konversation/images/nickicons/smiling/irc_owner.png differ diff --git a/konversation/images/nickicons/smiling/irc_voice.png b/konversation/images/nickicons/smiling/irc_voice.png new file mode 100644 index 0000000..8df68ee Binary files /dev/null and b/konversation/images/nickicons/smiling/irc_voice.png differ diff --git a/konversation/images/nickicons/square/Makefile.am b/konversation/images/nickicons/square/Makefile.am new file mode 100644 index 0000000..6ef4b68 --- /dev/null +++ b/konversation/images/nickicons/square/Makefile.am @@ -0,0 +1,3 @@ +konversationicondir = $(kde_datadir)/konversation/themes/square +konversationicon_DATA = irc_admin.png irc_away.png irc_halfop.png irc_normal.png irc_op.png \ + irc_owner.png irc_voice.png index.desktop diff --git a/konversation/images/nickicons/square/index.desktop b/konversation/images/nickicons/square/index.desktop new file mode 100644 index 0000000..955b293 --- /dev/null +++ b/konversation/images/nickicons/square/index.desktop @@ -0,0 +1,69 @@ +[Desktop Entry] +Type=Theme +Name=Square Theme +Name[ar]=سمة Square +Name[bg]=Тема "Квадрат" +Name[br]=Giz karrez +Name[ca]=Tema Square +Name[cs]=Square téma +Name[da]=Square tema +Name[de]=Rechteck-Design +Name[el]=Τετράγωνο θέμα +Name[es]=Tema «Square» +Name[et]=Kandiline teema +Name[fi]=Neliöteema +Name[fr]=Thème carré +Name[ga]=Téama "Square" +Name[gl]=Tema Cadrado +Name[he]=ערכה מרובעת +Name[it]=Tema quadrato +Name[ja]=四角 +Name[ka]=კვადრატული გაფორმება +Name[lt]=Kvadratinė tema +Name[nl]=Vierkant thema +Name[pa]=ਵਰਗ ਸਰੂਪ +Name[pt]=Tema Quadrado +Name[pt_BR]=Tema Quadrado +Name[ru]=Квадратики +Name[sr]=Квадратна тема +Name[sr@Latn]=Kvadratna tema +Name[sv]=Kvadratiskt tema +Name[ta]=சதுர பொருள் +Name[tr]=Kare Teması +Name[uk]=Квадратна тема +Name[xx]=xxSquare Themexx +Name[zh_CN]=方块主题 +Name[zh_TW]=方塊主題 +Comment="SQUARE" by Kenichiro Takahashi +Comment[ar]="SQUARE" تأليف Kenichiro Takahashi +Comment[bg]=Тема "Квадрат" от Kenichiro Takahashi +Comment[br]=« SQUARE » gant Kenichiro Takahashi +Comment[ca]="SQUARE" per Kenichiro Takahashi +Comment[cs]="SQUARE" od Kenichiro Takahashi +Comment[da]="SQUARE" af Kenichiro Takahashi +Comment[de]="SQUARE" von Kenichiro Takahashi +Comment[el]="Τετράγωνο" από Kenichiro Takahashi +Comment[es]=«SQUARE» de Kenichiro Takahashi +Comment[et]="SQUARE" (autor Kenichiro Takahashi) +Comment[fi]="NELIÖT" (Kenichiro Takahashi) +Comment[fr]=« CARRÉ » par Kenichiro Takahashi +Comment[ga]="SQUARE" le Kenichiro Takahashi +Comment[gl]="Cadrado" por Kenichiro Takahashi +Comment[he]="ערכה מרובעת" של Kenichiro Takahashi +Comment[it]=«Quadrato» di Kenichiro Takahashi +Comment[ja]=Kenichiro Takahashi 作の四角いテーマ +Comment[ka]="კვადრატული" კენიჩირო ტაკაჰაშის მიერ +Comment[lt]=„Kvadratinė tema“, sukurta Kenichiro Takahashi +Comment[nl]="SQUARE" door Kenichiro Takahashi +Comment[pt]="QUADRADO" por Kenichiro Takahashi +Comment[pt_BR]="Quadrado" por Kenichiro Takahashi +Comment[ru]=Сделал Kenichiro Takahashi +Comment[sr]=„Квадрат“ од Кеничира Такахашија (Kenichiro Takahashi) +Comment[sr@Latn]=„Kvadrat“ od Keničira Takahašija (Kenichiro Takahashi) +Comment[sv]="KVADRATISK" av Kenichiro Takahashi +Comment[ta]="SQUARE" கெனிசிரோ டகாஹாஷி +Comment[tr]=Kenichiro Takahashi tarafından "KARE" +Comment[uk]="КВАДРАТ" - Kenichiro Takahashi +Comment[xx]=xx"SQUARE" by Kenichiro Takahashixx +Comment[zh_CN]=“方块”,由 Kenichiro Takahashi 设计 +Comment[zh_TW]="方塊"主題,由 Kenichiro Takahashi 撰寫 diff --git a/konversation/images/nickicons/square/irc_admin.png b/konversation/images/nickicons/square/irc_admin.png new file mode 100644 index 0000000..8c78d47 Binary files /dev/null and b/konversation/images/nickicons/square/irc_admin.png differ diff --git a/konversation/images/nickicons/square/irc_away.png b/konversation/images/nickicons/square/irc_away.png new file mode 100644 index 0000000..532b0d4 Binary files /dev/null and b/konversation/images/nickicons/square/irc_away.png differ diff --git a/konversation/images/nickicons/square/irc_halfop.png b/konversation/images/nickicons/square/irc_halfop.png new file mode 100644 index 0000000..6047bc6 Binary files /dev/null and b/konversation/images/nickicons/square/irc_halfop.png differ diff --git a/konversation/images/nickicons/square/irc_normal.png b/konversation/images/nickicons/square/irc_normal.png new file mode 100644 index 0000000..5a25719 Binary files /dev/null and b/konversation/images/nickicons/square/irc_normal.png differ diff --git a/konversation/images/nickicons/square/irc_op.png b/konversation/images/nickicons/square/irc_op.png new file mode 100644 index 0000000..a9dd9f5 Binary files /dev/null and b/konversation/images/nickicons/square/irc_op.png differ diff --git a/konversation/images/nickicons/square/irc_owner.png b/konversation/images/nickicons/square/irc_owner.png new file mode 100644 index 0000000..e9f51df Binary files /dev/null and b/konversation/images/nickicons/square/irc_owner.png differ diff --git a/konversation/images/nickicons/square/irc_voice.png b/konversation/images/nickicons/square/irc_voice.png new file mode 100644 index 0000000..7aab216 Binary files /dev/null and b/konversation/images/nickicons/square/irc_voice.png differ diff --git a/konversation/scripts/Makefile.am b/konversation/scripts/Makefile.am new file mode 100644 index 0000000..77ce9cd --- /dev/null +++ b/konversation/scripts/Makefile.am @@ -0,0 +1,4 @@ +scriptsdir=$(kde_datadir)/konversation/scripts +scripts_SCRIPTS=bug fortune gauge uptime kdeversion cmd sayclip weather sysinfo media mail tinyurl +scripts_DATA=fortunes.dat + diff --git a/konversation/scripts/README b/konversation/scripts/README new file mode 100644 index 0000000..6efdefe --- /dev/null +++ b/konversation/scripts/README @@ -0,0 +1,55 @@ +Here are some scripts that can help you in everyday life with konvi. + +They are usually put in ~/.kde/share/apps/konversation/scripts/ and executed by +typing /exec in konversation. + +Since scripts are executed by system, they should have 'executable' flag on. +This is most easily achieved by running chmod +x + +Please add descriptions here as new scripts appear: + +bug Opens up konqueror with kde bugzilla on specified bug number. + usage: /bug 65090 + +gauge Displays funny "beer load" meter. Author: Eisfuchs, Idea: berkus. + usage: /gauge 55 + + +uptime Displays the system uptime on the current channel. + usage: /uptime + +fortune Displays a random fortune cookie + usage: /fortune + +kdeversion Displays the Qt/KDE version. + usage: /kdeversion + +cmd Prints the output of a given command. + usage: /cmd command + +sayclip Prints the contents of the clipboard on the current channel + with flood protection. Klipper must be running. + usage: /sayclip [pause-time] + +weather Displays current weather using KWeather applet. + usage: /weather + +colorizer Randomly colorizes the message. + usage: /colorize message + +media Plays the currently played media. + Supports amaroK,JuK,Noatun,Kaffeine + Usage: /media + +mail Print the number of unread emails in your inbox folder in + kmail. Kmail or kontact must be running. + Usage: /mail [folder-substring] + +google Use Google services + Usage: /google (--search) # Search in Google + /google --spell # Spellcheck using Google + /google -b|--browser # Launch konqueror with google search for + +qurl Display a short version of the url using qurl.net + Requires Ruby. + usage: /qurl http://some.very.long.url.com/ diff --git a/konversation/scripts/bug b/konversation/scripts/bug new file mode 100755 index 0000000..0f5ec86 --- /dev/null +++ b/konversation/scripts/bug @@ -0,0 +1,18 @@ +#!/bin/sh + +PORT=$1 +SERVER=$2 +TARGET=$3 +BUG=$4 + +if [ ! $TARGET ] +then + dcop $PORT default error "Can't write into status view." +else + if [ -z $BUG ] + then + dcop $PORT default error "You forgot the bug number!" + else + kfmclient openURL http://bugs.kde.org/show_bug.cgi?id=$4 + fi +fi diff --git a/konversation/scripts/cmd b/konversation/scripts/cmd new file mode 100755 index 0000000..ebd7112 --- /dev/null +++ b/konversation/scripts/cmd @@ -0,0 +1,31 @@ +#!/usr/bin/env perl +# Copyright (C) 2004 by İsmail Dönmez +# Licensed under GPL v2 or later at your option + +$PORT= shift; +$SERVER= shift; +$TARGET= shift; + +my $i; +my $command; + +if( $ARGV[0] eq "yes" ){ + exec 'dcop', $PORT, 'default', 'error', 'Requested command is not executed!'; +} + +foreach $word (@ARGV) { + $command = $command." ".$word; +} + +$ARG_MESSAGE = `exec $command`; + +foreach $entry (split(/\n/, $ARG_MESSAGE)) { + chomp $entry; + $i=1; + $entry =~ s/^\//\/\//; + system 'dcop', $PORT, 'default', 'say', $SERVER, $TARGET, $entry; +} + +unless($i) { + exec 'dcop', $PORT, 'default', 'error', "Command @ARGV doesn't exist"; +} diff --git a/konversation/scripts/fortune b/konversation/scripts/fortune new file mode 100755 index 0000000..a3b61d3 --- /dev/null +++ b/konversation/scripts/fortune @@ -0,0 +1,53 @@ +#!/usr/bin/env perl +# Copyright (C) 2004 by İsmail Dönmez +# Licensed under GPL v2 or later at your option + +$PORT = shift; +$SERVER = shift; +$TARGET = shift; + +sub RANDOM_INT ($$) { + my($min, $max) = @_; + return $min if $min == $max; + ($min, $max) = ($max, $min) if $min > $max; + return $min + int rand(1 + $max - $min); +} + +open(FORTUNES,"fortunes.dat") or die("Could not open fortunes file!"); + +while () { + chomp; + ++$TOTAL_LINES; +} + +seek(FORTUNES,0,0); + +srand; +$LINE = RANDOM_INT(0,$TOTAL_LINES - 5); + +$MESSAGE = "4Random Fortune: "; + +while () { + $LINE_COUNT++; + + if ( !$START && $LINE_COUNT >= $LINE ) { + if ( $_ eq "\%\n" ) { + $START = 1; + next; + } + next; + } + + elsif ( $START ) { + if( $_ eq "\%\n" ) { + last; + } + else { + chomp; + s/(\s)+/$1/g; + $MESSAGE .= $_." "; + } + } +} +close(FORTUNES); +exec 'dcop', $PORT, 'default', 'say', $SERVER, $TARGET, $MESSAGE; diff --git a/konversation/scripts/fortunes.dat b/konversation/scripts/fortunes.dat new file mode 100644 index 0000000..756f18a --- /dev/null +++ b/konversation/scripts/fortunes.dat @@ -0,0 +1,680 @@ +% +Documentation is like sex: when it is good, it is very, very good; and when it is bad, it is better than nothing. +% +Let's call it an accidental feature. + -- Larry Wall +% +I did this 'cause Linux gives me a woody. It doesn't generate revenue. + -- Dave '-ddt->` Taylor, announcing DOOM for Linux +% +Feel free to contact me (flames about my english and the useless of this +driver will be redirected to /dev/null, oh no, it's full...). + -- Michael Beck, describing the PC-speaker sound device +% +lp1 on fire + -- One of the more obfuscated kernel messages +% +A Linux machine! Because a 486 is a terrible thing to waste! + -- Joe Sloan, jjs@wintermute.ucr.edu +% +Microsoft is not the answer. +Microsoft is the question. +NO (or Linux) is the answer. + -- Taken from a .signature from someone from the UK, source unknown +% +In most countries selling harmful things like drugs is punishable. +Then howcome people can sell Microsoft software and go unpunished? + -- Hasse Skrifvars, hasku@rost.abo.fi, +% +Windows without the X is like making love without a partner. +Sex, Drugs & Linux Rules +win-nt from the people who invented edlin. +Apples have meant trouble since eden. +Linux, the way to get rid of boot viruses + -- MaDsen Wikholm, mwikholm@at8.abo.fi +% +Once upon a time there was a DOS user who saw Unix, and saw that it was +good. After typing cp on his DOS machine at home, he downloaded GNU's +unix tools ported to DOS and installed them. He rm'd, cp'd, and mv'd +happily for many days, and upon finding elvis, he vi'd and was happy. After +a long day at work (on a Unix box) he came home, started editing a file, +and couldn't figure out why he couldn't suspend vi (w/ ctrl-z) to do +a compile. + -- Erik Troan, ewt@tipper.oit.unc.edu +% +We are MicroSoft. You will be assimilated. Resistance is futile. + -- Attributed to B.G., Gill Bates +% +Avoid the Gates of Hell. Use Linux + -- unknown source +% +Intel engineering seem to have misheard Intel marketing strategy. The +phrase was "Divide and conquer" not "Divide and cock up" + -- Alan Cox, iialan@www.linux.org.uk +% +Linux! Guerrilla UNIX Development Venimus, Vidimus, Dolavimus. + -- Mark A. Horton KA4YBR, mah@ka4ybr.com +% +"Who is General Failure and why is he reading my hard disk?" +Microsoft spel chekar vor sail, worgs grate !! + -- Felix von Leitner, leitner@inf.fu-berlin.de +% +Personally, I think my choice in the mostest-superlative-computer wars has to +be the HP-48 series of calculators. They'll run almost anything. And if they +can't, while I'll just plug a Linux box into the serial port and load up the +HP-48 VT-100 emulator. + -- Jeff Dege, jdege@winternet.com +% +There are no threads in a.b.p.erotica, so there's no gain in using a +threaded news reader. + -- unknown source +% +/* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. +*/ +die_if_kernel("Oops", regs, error_code); + -- From linux/arch/i386/mm/fault.c +% +Linux: because a PC is a terrible thing to waste + -- ksh@cis.ufl.edu put this on Tshirts in '93 +% +Linux: the choice of a GNU generation + -- ksh@cis.ufl.edu put this on Tshirts in '93 +% +There are two types of Linux developers - those who can spell, and +those who can't. There is a constant pitched battle between the two. + -- From one of the post-1.1.54 kernel update messages posted to c.o.l.a +% +When you say "I wrote a program that crashed Windows", people just stare at +you blankly and say "Hey, I got those with the system, *for free*". + -- Linus Torvalds +% +We come to bury DOS, not to praise it. + -- Paul Vojta, vojta@math.berkeley.edu +% +Be warned that typing killall name may not have the desired +effect on non-Linux systems, especially when done by a privileged user. + -- From the killall manual page +% +Note that if I can get you to "su and say" something just by asking, +you have a very serious security problem on your system and you should +look into it. + -- Paul Vixie, vixie-cron 3.0.1 installation notes +% +How should I know if it works? That's what beta testers are for. I +only coded it. + -- Attributed to Linus Torvalds, somewhere in a posting +% +I develop for Linux for a living, I used to develop for DOS. +Going from DOS to Linux is like trading a glider for an F117. + -- Lawrence Foard, entropy@world.std.com +% +Absolutely nothing should be concluded from these figures except that +no conclusion can be drawn from them. + -- Joseph L. Brothers, Linux/PowerPC Project) +% +If the future navigation system [for interactive networked services on +the NII] looks like something from Microsoft, it will never work. + -- Chairman of Walt Disney Television & Telecommunications +% +Problem solving under Linux has never been the circus that it is under +AIX. + -- Pete Ehlke in comp.unix.aix +% +I don't know why, but first C programs tend to look a lot worse than +first programs in any other language (maybe except for fortran, but then +I suspect all fortran programs look like `firsts') + -- Olaf Kirch +% +On a normal ascii line, the only safe condition to detect is a 'BREAK' +- everything else having been assigned functions by Gnu EMACS. + -- Tarl Neustaedter +% +By golly, I'm beginning to think Linux really *is* the best thing since +sliced bread. + -- Vance Petree, Virginia Power +% +I'd crawl over an acre of 'Visual This++' and 'Integrated Development +That' to get to gcc, Emacs, and gdb. Thank you. + -- Vance Petree, Virginia Power +% +Oh, I've seen copies [of Linux Journal] around the terminal room at The Labs. + -- Dennis Ritchie +% +If you want to travel around the world and be invited to speak at a lot +of different places, just write a Unix operating system. + -- Linus Torvalds +% +...and scantily clad females, of course. Who cares if it's below zero +outside. + -- Linus Torvalds +% +...you might as well skip the Xmas celebration completely, and instead +sit in front of your linux computer playing with the all-new-and-improved +linux kernel version. + -- Linus Torvalds +% +Besides, I think Slackware sounds better than 'Microsoft,' don't you? + -- Patrick Volkerding +% +All language designers are arrogant. Goes with the territory... + -- Larry Wall +% +And the next time you consider complaining that running Lucid Emacs +19.05 via NFS from a remote Linux machine in Paraguay doesn't seem to +get the background colors right, you'll know who to thank. + -- Matt Welsh +% +Are Linux users lemmings collectively jumping off of the cliff of +reliable, well-engineered commercial software? + -- Matt Welsh +% +Even more amazing was the realization that God has Internet access. I +wonder if He has a full newsfeed? + -- Matt Welsh +% +I once witnessed a long-winded, month-long flamewar over the use of +mice vs. trackballs... It was very silly. + -- Matt Welsh +% +Linux poses a real challenge for those with a taste for late-night +hacking (and/or conversations with God). + -- Matt Welsh +% +What you end up with, after running an operating system concept through +these many marketing coffee filters, is something not unlike plain hot +water. + -- Matt Welsh +% +...Deep Hack Mode -- that mysterious and frightening state of +consciousness where Mortal Users fear to tread. + -- Matt Welsh +% +...Unix, MS-DOS, and Windows NT (also known as the Good, the Bad, and +the Ugly). + -- Matt Welsh +% +...very few phenomena can pull someone out of Deep Hack Mode, with two +noted exceptions: being struck by lightning, or worse, your *computer* +being struck by lightning. + -- Matt Welsh +% +..you could spend *all day* customizing the title bar. Believe me. I +speak from experience. + -- Matt Welsh +% +[In 'Doctor' mode], I spent a good ten minutes telling Emacs what I +thought of it. (The response was, 'Perhaps you could try to be less +abusive.') + -- Matt Welsh +% +I would rather spend 10 hours reading someone else's source code than +10 minutes listening to Musak waiting for technical support which isn't. + -- Dr. Greg Wettstein, Roger Maris Cancer Center +% +...[Linux's] capacity to talk via any medium except smoke signals. + -- Dr. Greg Wettstein, Roger Maris Cancer Center +% +Whip me. Beat me. Make me maintain AIX. + -- Stephan Zielinski +% +Your job is being a professor and researcher: That's one hell of a good excuse +for some of the brain-damages of minix. + -- Linus Torvalds to Andrew Tanenbaum +% +I still maintain the point that designing a monolithic kernel in 1991 is a +fundamental error. Be thankful you are not my student. You would not get a +high grade for such a design :-) + -- Andrew Tanenbaum to Linus Torvalds +% +We use Linux for all our mission-critical applications. Having the source code +means that we are not held hostage by anyone's support department. + -- Russell Nelson, President of Crynwr Software +% +Linux is obsolete + -- Andrew Tanenbaum +% +Dijkstra probably hates me. + -- Linus Torvalds, in kernel/sched.c +% +And 1.1.81 is officially BugFree(tm), so if you receive any bug-reports +on it, you know they are just evil lies. + -- Linus Torvalds +% +We are Pentium of Borg. Division is futile. You will be approximated. + -- seen in someone's .signature +% +Linux: the operating system with a CLUE... Command Line User Environment. + -- seen in a posting in comp.software.testing +% +quit When the quit statement is read, the bc processor + is terminated, regardless of where the quit state- + ment is found. For example, "if (0 == 1) quit" + will cause bc to terminate. + -- seen in the manpage for "bc". Note the "if" statement's logic +% +Sic transit discus mundi + -- From the System Administrator's Guide, by Lars Wirzenius +% +Sigh. I like to think it's just the Linux people who want to be on +the "leading edge" so bad they walk right off the precipice. + -- Craig E. Groeschel +% +We all know Linux is great... it does infinite loops in 5 seconds. + - Linus Torvalds about the superiority of Linux on the Amterdam Linux Symposium +% +Waving away a cloud of smoke, I look up, and am blinded by a bright, white +light. It's God. No, not Richard Stallman, or Linus Torvalds, but God. In +a booming voice, He says: "THIS IS A SIGN. USE LINUX, THE FREE UNIX SYSTEM +FOR THE 386. + -- Matt Welsh +% +The chat program is in public domain. This is not the GNU public license. +If it breaks then you get to keep both pieces. + -- Copyright notice for the chat program +% +'Mounten' wird fr drei Dinge benutzt: 'Aufsitzen' auf Pferde, 'einklinken' +von Festplatten in Dateisysteme, und, nun, 'besteigen' beim Sex. + -- Christa Keil +% +Manchmal stehe nachts auf und installier's mir einfach... + -- H0arry @ IRC +% +'Mounting' is used for three things: climbing on a horse, linking in a +hard disk unit in data systems, and, well, mounting during sex. + -- Christa Keil +% +We are using Linux daily to UP our productivity - so UP yours! + -- Adapted from Pat Paulsen by Joe Sloan +% +But what can you do with it? + -- ubiquitous cry from Linux-user partner +% +/* + * [...] Note that 120 sec is defined in the protocol as the maximum + * possible RTT. I guess we'll have to use something other than TCP + * to talk to the University of Mars. + * PAWS allows us longer timeouts and large windows, so once implemented + * ftp to mars will work nicely. + */ + -- from /usr/src/linux/net/inet/tcp.c, concerning RTT [round trip time] +% +DOS: n., A small annoying boot virus that causes random spontaneous system + crashes, usually just before saving a massive project. Easily cured by + UNIX. See also MS-DOS, IBM-DOS, DR-DOS. + -- David Vicker's .plan +% +MSDOS didn't get as bad as it is overnight -- it took over ten years +of careful development. + -- dmeggins@aix1.uottawa.ca +% +LILO, you've got me on my knees! + -- David Black, dblack@pilot.njin.net, with apologies to Derek and the +Dominos, and Werner Almsberger +% +I've run DOOM more in the last few days than I have the last few +months. I just love debugging ;-) + -- Linus Torvalds +% +Microsoft Corp., concerned by the growing popularity of the free 32-bit +operating system for Intel systems, Linux, has employed a number of top +programmers from the underground world of virus development. Bill Gates stated +yesterday: "World domination, fast -- it's either us or Linus". Mr. Torvalds +was unavailable for comment ... + -- Robert Manners, rjm@swift.eng.ox.ac.uk, in comp.os.linux.setup +% +The only "intuitive" interface is the nipple. After that, it's all learned. + -- Bruce Ediger, bediger@teal.csn.org, on X interfaces +% +After watching my newly-retired dad spend two weeks learning how to make a new +folder, it became obvious that "intuitive" mostly means "what the writer or +speaker of intuitive likes". + -- Bruce Ediger, bediger@teal.csn.org, on X the intuitiveness of a Mac interface +% +Now I know someone out there is going to claim, "Well then, UNIX is intuitive, +because you only need to learn 5000 commands, and then everything else follows +from that! Har har har!" + -- Andy Bates on "intuitive interfaces", slightly defending Macs +% +> No manual is ever necessary. +May I politely interject here: BULLSHIT. That's the biggest Apple lie of all! + -- Discussion in comp.os.linux.misc on the intuitiveness of interfaces +% +How do I type "for i in *.dvi do xdvi $i done" in a GUI? + -- Discussion in comp.os.linux.misc on the intuitiveness of interfaces +% +>Ever heard of .cshrc? +That's a city in Bosnia. Right? + -- Discussion in comp.os.linux.misc on the intuitiveness of commands +% +Who wants to remember that escape-x-alt-control-left shift-b puts you into +super-edit-debug-compile mode? + -- Discussion on the intuitiveness of commands, especially Emacs +% +Anyone who thinks UNIX is intuitive should be forced to write 5000 lines of +code using nothing but vi or emacs. AAAAACK! + -- Discussion on the intuitiveness of commands, especially Emacs +% +Now, it we had this sort of thing: + yield -a for yield to all traffic + yield -t for yield to trucks + yield -f for yield to people walking (yield foot) + yield -d t* for yield on days starting with t + +...you'd have a lot of dead people at intersections, and traffic jams you +wouldn't believe... + -- Discussion on the intuitiveness of commands +% +Actually, typing random strings in the Finder does the equivalent of +filename completion. + -- Discussion on file completion vs. the Mac Finder +% +Not me, guy. I read the Bash man page each day like a Jehovah's Witness reads +the Bible. No wait, the Bash man page IS the bible. Excuse me... + -- More on confusing aliases, taken from comp.os.linux.misc +% +On the Internet, no one knows you're using Windows NT + -- Submitted by Ramiro Estrugo, restrugo@fateware.com +% +> I'm an idiot.. At least this [bug] took about 5 minutes to find.. +Disquieting ... + -- Gonzalo Tornaria in response to Linus Torvalds's +% +> I'm an idiot.. At least this [bug] took about 5 minutes to find.. +We need to find some new terms to describe the rest of us mere mortals +then. + -- Craig Schlenter in response to Linus Torvalds's +% +> I'm an idiot.. At least this [bug] took about 5 minutes to find.. +Surely, Linus is talking about the kind of idiocy that others aspire to :-). + -- Bruce Perens in response to Linus Torvalds's +% +Never make any mistaeks. + -- Anonymous, in a mail discussion about to a kernel bug report +% ++#if defined(__alpha__) && defined(CONFIG_PCI) ++ /* ++ * The meaning of life, the universe, and everything. Plus ++ * this makes the year come out right. ++ */ ++ year -= 42; ++#endif + -- From the patch for 1.3.2: (kernel/time.c), submitted by Marcus Meissner +% +As usual, this being a 1.3.x release, I haven't even compiled this +kernel yet. So if it works, you should be doubly impressed. + -- Linus Torvalds, announcing kernel 1.3.3 +% +People disagree with me. I just ignore them. + -- Linus Torvalds, regarding the use of C++ for the Linux kernel +% +It's now the GNU Emacs of all terminal emulators. + -- Linus Torvalds, regarding the fact that Linux started off as a terminal emulator +% +Audience: What will become of Linux when the Hurd is ready? +Eric Youngdale: Err... is Richard Stallman here? + -- From the Linux conference in spring '95, Berlin +% +Linux: The OS people choose without $200,000,000 of persuasion. + -- Mike Coleman +% +The memory management on the PowerPC can be used to frighten small children. + -- Linus Torvalds +% +... faster BogoMIPS calculations (yes, it now boots 2 seconds faster than +it used to: we're considering changing the name from "Linux" to "InstaBOOT" + -- Linus, in the announcement for 1.3.26 +% +... of course, this probably only happens for tcsh which uses wait4(), +which is why I never saw it. Serves people who use that abomination +right 8^) + -- Linus Torvalds, about a patch that fixes getrusage for 1.3.26 +% +It's a bird.. +It's a plane.. +No, it's KernelMan, faster than a speeding bullet, to your rescue. +Doing new kernel versions in under 5 seconds flat.. + -- Linus, in the announcement for 1.3.27 +% +Eh, that's it, I guess. No 300 million dollar unveiling event for this +kernel, I'm afraid, but you're still supposed to think of this as the +"happening of the century" (at least until the next kernel comes along). + -- Linus, in the announcement for 1.3.27 +% +Oh, and this is another kernel in that great and venerable "BugFree(tm)" +series of kernels. So be not afraid of bugs, but go out in the streets +and deliver this message of joy to the masses. + -- Linus, in the announcement for 1.3.27 +% +When you say 'I wrote a program that crashed Windows', people just stare at +you blankly and say 'Hey, I got those with the system, *for free*'. + -- Linus Torvalds +% +Never trust an operating system you don't have sources for. ;-) + -- Unknown source +% +> Linux is not user-friendly. +It _is_ user-friendly. It is not ignorant-friendly and idiot-friendly. + -- Seen somewhere on the net +% +Keep me informed on the behaviour of this kernel.. As the "BugFree(tm)" +series didn't turn out too well, I'm starting a new series called the +"ItWorksForMe(tm)" series, of which this new kernel is yet another +shining example. + -- Linus, in the announcement for 1.3.29 +% +Seriously, the way I did this was by using a special /sbin/loader binary +with debugging hooks that I made ("dd" is your friend: binary editors +are for wimps). + -- Linus Torvalds, in an article on a dnserver +% +(I tried to get some documentation out of Digital on this, but as far as +I can tell even _they_ don't have it ;-) + -- Linus Torvalds, in an article on a dnserver +% +Q: Why shouldn't I simply delete the stuff I never use, it's just taking up + space? +A: This question is in the category of Famous Last Words.. + -- From the Frequently Unasked Questions +% +Q: What's the big deal about rm, I have been deleting stuff for years? And + never lost anything.. oops! +A: ... + -- From the Frequently Unasked Questions +% +Linux is addictive, I'm hooked! + -- MaDsen Wikholm's .sig +% +panic("Foooooooood fight!"); + -- In the kernel source aha1542.c, after detecting a bad segment list +% +Convention organizer to Linus Torvalds: "You might like to come with us +to some licensed[1] place, and have some pizza." + +Linus: "Oh, I did not know that you needed a license to eat pizza". + +[1] Licenced - refers in Australia to a restaurant which has government +licence to sell liquor. + -- Linus at a talk at the Melbourne University +% +Footnotes are for things you believe don't really belong in LDP manuals, +but want to include anyway. + -- Joel N. Weber II discussing the 'make' chapter of LPG +% +Eh, that's it, I guess. No 300 million dollar unveiling event for this +kernel, I'm afraid, but you're still supposed to think of this as the +"happening of the century" (at least until the next kernel comes along). +Oh, and this is another kernel in that great and venerable "BugFree(tm)" +series of kernels. So be not afraid of bugs, but go out in the streets +and deliver this message of joy to the masses. + -- Linus Torvalds, on releasing 1.3.27 +% +Ok, I'm just uploading the new version of the kernel, v1.3.33, also +known as "the buggiest kernel ever". + -- Linus Torvalds +% +Go not unto the Usenet for advice, for you will be told both yea and nay (and +quite a few things that just have nothing at all to do with the question). + -- seen in a .sig somewhere +% +Those who don't understand Linux are doomed to reinvent it, poorly. + -- unidentified source +% +Look, I'm about to buy me a double barreled sawed off shotgun and show +Linus what I think about backspace and delete not working. + -- some anonymous .signature +% +We apologize for the inconvenience, but we'd still like yout to test out +this kernel. + -- Linus Torvalds, announcing another kernel patch +% +The new Linux anthem will be "He's an idiot, but he's ok", as performed by +Monthy Python. You'd better start practicing. + -- Linus Torvalds, announcing another kernel patch +% +How do you power off this machine? + -- Linus, when upgrading linux.cs.helsinki.fi, and after using the machine for several months +% +Excusing bad programming is a shooting offence, no matter _what_ the +circumstances. + -- Linus Torvalds, to the linux-kernel list +% +Linus? Whose that? + -- clueless newbie on #Linux +% +Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God... + -- mikecd on #Linux +% +Some people have told me they don't think a fat penguin really embodies the +grace of Linux, which just tells me they have never seen a angry penguin +charging at them in excess of 100mph. They'd be a lot more careful about what +they say if they had. + -- Linus Torvalds, announcing Linux v2.0 +% +MS-DOS, you can't live with it, you can live without it. + -- from Lars Wirzenius' .sig +% +.. I used to get in more fights with SCO than I did my girlfriend, but +now, thanks to Linux, she has more than happily accepted her place back at +number one antagonist in my life.. + -- Jason Stiefel, krypto@s30.nmex.com +% +I mean, well, if it were not for Linux I might be roaming the streets looking +for drugs or prostitutes or something. Hannu and Linus have my highest +admiration (apple polishing mode off). + -- Phil Lewis, plewis@nyx.nyx.net +% +> What does ELF stand for (in respect to Linux?) +ELF is the first rock group that Ronnie James Dio performed with back in +the early 1970's. In constrast, a.out is a misspelling of the French word +for the month of August. What the two have in common is beyond me, but +Linux users seem to use the two words together. + -- seen on c.o.l.misc +% +"Linux was made by foreign terrorists to take money from true US companies +like Microsoft." - Some AOL'er. +"To this end we dedicate ourselves..." -Don + -- From the sig of "Don", don@cs.byu.edu +% +Shoot me again. +Just proving that the quickest way to solve the problem is to post a +whine to the newsgroups: within moments the solution presents itself to +me, and meanwhile my ass is hanging out on the Net... *sigh*... + -- Dave Phillips, dlphilp@bright.net, about problem solving via news +% +Besides, its really not worthwhile to use more than two times your physical +ram in swap (except in a select few situations). The performance of the system +becomes so abysmal you'd rather heat pins under your toenails while reciting +Windows95 source code and staring at porn flicks of Bob Dole than actually try +to type something. + -- seen on c.o.l.development.system, about the size of the swap space +% +Only wimps use tape backup: _real_ men just upload their important stuff +on ftp, and let the rest of the world mirror it ;) + -- Linus Torvalds, about his failing hard drive on linux.cs.helsinki.fi +% +One of the things that hamper Linux's climb to world domination is the +shortage of bad Computer Role Playing Games, or CRaPGs. No operating system +can be considered respectable without one. + -- Brian O'Donnell, odonnllb@tcd.ie +% +The game, anoraks.2.0.0.tgz, will be available from sunsite until somebody +responsible notices it and deletes it, and shortly from +ftp.mee.tcd.ie/pub/Brian, though they don't know that yet. + -- Brian O'Donnell, odonnllb@tcd.ie +% +'Ooohh.. "FreeBSD is faster over loopback, when compared to Linux +over the wire". Film at 11.' + -- Linus Torvalds +% +Q: Would you like to see the WINE list? +A: What's on it, anything expensive? +Q: No, just Solitaire and MineSweeper for now, but the WINE is free. + -- Kevin M. Bealer, about the WINdows Emulator +% +So in the future, one 'client' at a time or you'll be spending CPU time with +lots of little 'child processes'. + -- Kevin M. Bealer, commenting on the private life of a Linux nerd +% +By the way, I can hardly feel sorry for you... All last night I had to listen +to her tears, so great they were redirected to a stream. What? Of _course_ +you didn't know. You and your little group no longer have any permissions +around here. She changed her .lock files, too. + -- Kevin M. Bealer, commenting on the private life of a Linux nerd +% +We should start referring to processes which run in the background by their +correct technical name... paenguins. + -- Kevin M. Bealer, commenting on the penguin Linux logo +% +We can use symlinks of course... syslogd would be a symlink to syslogp and +ftpd and ircd would be linked to ftpp and ircp... and of course the +point-to-point protocal paenguin. + -- Kevin M. Bealer, commenting on the penguin Linux logo +% +This is a logical analogy too... anyone who's been around, knows the world is +run by paenguins. Always a paenguin behind the curtain, really getting things +done. And paenguins in politics--who can deny it? + -- Kevin M. Bealer, commenting on the penguin Linux logo +% +Linux: Where Don't We Want To Go Today? + -- Submitted by Pancrazio De Mauro, paraphrasing some well-known sales talk +% +The most important design issue... is the fact that Linux is supposed to +be fun... + -- Linus Torvalds at the First Dutch International Symposium on Linux +% +In short, at least give the penguin a fair viewing. If you still don't +like it, that's ok: that's why I'm boss. I simply know better than you do. + -- Linus "what, me arrogant?" Torvalds, on c.o.l.advocacy +% + what's the difference between chattr and chmod? + SomeLamer: man chattr > 1; man chmod > 2; diff -u 1 2 | less + -- Seen on #linux on irc +% +The linuX Files -- The Source is Out There. + -- Sent in by Craig S. Bell, goat@aracnet.com +% +"... being a Linux user is sort of like living in a house inhabited +by a large family of carpenters and architects. Every morning when +you wake up, the house is a little different. Maybe there is a new +turret, or some walls have moved. Or perhaps someone has temporarily +removed the floor under your bed." - Unix for Dummies, 2nd Edition + -- found in the .sig of Rob Riggs, rriggs@tesser.com +% +C is quirky, flawed, and an enormous success + -- Dennis M. Ritchie +% +If Bill Gates is the Devil then Linus Torvalds must be the Messiah. + -- Unknown source +% +Vini, vidi, Linux! + -- Unknown source +% +The good thing about standards is that there are so many to choose from. + -- Andrew S. Tanenbaum +% +I'm telling you that the kernel is stable not because it's a kernel, +but because I refuse to listen to arguments like this. + -- Linus Torvalds +% \ No newline at end of file diff --git a/konversation/scripts/gauge b/konversation/scripts/gauge new file mode 100755 index 0000000..2befb87 --- /dev/null +++ b/konversation/scripts/gauge @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +PORT=$1 +SERVER=$2 +TARGET=$3 + +shift +shift +shift + +PERCENTAGE=$1 + +if [ ! $TARGET ] +then + dcop $PORT default error "Can't write into status view." +else + if [ ! $PERCENTAGE ] + then + dcop $PORT default error "USAGE: $0 " + else + PERCENTAGE=`echo $PERCENTAGE | sed 's/^0\+//'` + LEFT=$(($PERCENTAGE/5)) + RIGHT=$((20-$LEFT)) + + if [[ $PERCENTAGE -lt 0 ]]; then + dcop $PORT default error "Percentage has to be bigger than 0" + exit + fi + + if [[ $PERCENTAGE -gt 100 ]]; then + dcop $PORT default error "Percentage has to be smaller than 100" + exit + fi + + + if [ $PERCENTAGE = 50 ] + then + METER="|" + else + if [[ $PERCENTAGE -lt 50 ]] + then + METER="\\" + else + METER="/" + fi + fi + + for (( i=$LEFT ; $i != 0 ; i-- )) + do + OUTPUT="$OUTPUT," + done + + OUTPUT="$OUTPUT$METER" + + for (( i=$RIGHT ; $i != 0 ; i-- )) + do + OUTPUT="$OUTPUT," + done + + OUTPUT=`echo $OUTPUT | sed 's/,/ /g'` + + OUTPUT="[$OUTPUT] $PERCENTAGE%" + + if [ $PERCENTAGE = 100 ] + then + OUTPUT="$OUTPUT *ding*" + fi + + dcop $PORT default say $SERVER "$TARGET" "Beer load $OUTPUT" + fi +fi diff --git a/konversation/scripts/kdeversion b/konversation/scripts/kdeversion new file mode 100755 index 0000000..34fef02 --- /dev/null +++ b/konversation/scripts/kdeversion @@ -0,0 +1,9 @@ +#!/bin/sh + +# Prints the KDE version. + +PORT=$1; +SERVER=$2; +TARGET=$3; + +kde-config --version | while read line; do dcop $PORT default say $SERVER "$TARGET" "$line"; done diff --git a/konversation/scripts/mail b/konversation/scripts/mail new file mode 100755 index 0000000..b5882b1 --- /dev/null +++ b/konversation/scripts/mail @@ -0,0 +1,70 @@ +#!/bin/bash + +# +# Licensed under GPL v2 or later at your option +# Copyright 2005 by John Tapsell + +PORT=$1; +SERVER=$2; +TARGET=$3; + +FOLDER=$4; + + +if [ "$FOLDER" = "" ] ; then + FOLDER="inbox" +fi + + +getmails() +{ + + dcop kmail > /dev/null || { + dcop $PORT default info "Sorry kmail is not running" + exit + } + + for f in $(dcop kmail KMailIface folderList) ; do + MAILFOLDER=$(dcop $(dcop kmail KMailIface getFolder $f) "displayPath" | grep -i $FOLDER) + if [ "$MAILFOLDER" != "" ] ; then + FOUNDFOLDER=1 + MAILCOUNT=$(dcop $(dcop kmail KMailIface getFolder $f ) "unreadMessages()" ) + MAILTOTALCOUNT=$(dcop $(dcop kmail KMailIface getFolder $f ) "messages()" ) + MAILTOTALCOUNT=$(($MAILCOUNT + $MAILTOTALCOUNT)) + if [[ -z "$MAILCOUNT" ]] ; then MAILCOUNT = "0" ; fi + if [ "$MAILCOUNT" != 0 ] ; then + FOUNDEMAIL=1 + echo "Email folder %B$MAILFOLDER%B has %B$MAILCOUNT%B unread messages, out of %B$MAILTOTALCOUNT%B" + fi + fi + done + + if [[ -z "$FOUNDEMAIL" ]] ; then + if [[ -z "$FOUNDFOLDER" ]] ; then + dcop $PORT default info "No email folders were found that had a name containing '$FOLDER'" + exit + else + echo "No new emails in any folders matching '$FOLDER'" + fi + fi + +} + +if [[ -z "$3" ]] ; then + echo "Scripts are not meant to be called from the command line." + echo "This script should be installed to $KDEDIR/share/apps/konversation/scripts" + echo "Then executed with /script from the konversation" + echo + echo The output is: + getmails + exit +fi + +#LINECOUNT=$(getmails | wc -l) +#if [[ "$LINECOUNT" -gt 5 ]] ; then +# dcop $PORT default info "There are more than 5 matches. Cancelling to avoid flooding the server" +# exit +#fi + +getmails | head -n 3 | while read line; do dcop $PORT default say $SERVER "$TARGET" "$line"; done + diff --git a/konversation/scripts/media b/konversation/scripts/media new file mode 100755 index 0000000..e369262 --- /dev/null +++ b/konversation/scripts/media @@ -0,0 +1,484 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +#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. + +# Copyright 2006 Eli J. MacKenzie +# Inspired by `media` (Copyright 2005 İsmail Dönmez) + + +# If you wish to customize the formatting strings, do so in this table. +# Do not change the numbers unless you're changing the logic. +# Title, artist, and album will be set once the player is queried. +# See Player.format() for how these are used. + + +#Changing these 3 values will likely cause the script to fail +Title =4 +Artist=2 +Album =1 + +#To disable self-titled (eponymous) checking, subtract 8 +SelfTitled=11 + +outputFormat="/me $intro $info [$player]" +formatStrings = { + Title+SelfTitled : "$title by $artist (eponymous)", + SelfTitled : "${artist}'s self-titled album", + Title+Artist+Album : "$title by $artist on $album", #7,15 + Title+Artist : "$title by $artist", #6,14 + Title+Album : "$title from $album", #5,13 + Album+Artist : "$album by $artist", #3,11 + Title : "$title", #4,12 + Artist : "$artist", #2,10 + Album : "$album", #1,9 +} + +#Intro defaults to first type the player supports when a specific type was not demanded +formatVariables={'audio': 'is listening to', 'video': 'is watching'} + +## Static player ranking list +## If you add a new player, you must add it here or it won't get checked when in audio-only or video-only modes. +playerRankings= { + 'video' :['kaffeine','kmplayer', 'kplayer', 'noatun', 'kdetv'], + 'audio' :['amarok', 'MPD' 'juk', 'noatun', 'kscd', 'kaffeine', 'kmplayer', 'Audacious', 'xmms', 'yammi'] +} + +## Title, album and artist fields to be quoted depending on contents +# List the possible trigger characters here. +# If you want a '-', it must be first. if you want a '^', it must be last. +SIMPLE_FIXUP = '' #I use ' ' + +# If you want to use a regex for the above, specify it here in which case it will be used +REGEX_FIXUP = '' + +# Quote chars to use: +QUOTE_BEFORE = '"' +QUOTE_AFTER = '"' + + + ############################### + ## The Real work is done below +############################# + +import os +import sys +import re +import string + +try: + APP_ID = sys.argv[1] + IRC_SERVER = sys.argv[2] + TARGET = sys.argv[3] +except IndexError: + print >>sys.stderr, "This script is intended to be run from within Konversation." + sys.exit(0) + +if (sys.hexversion >> 16) < 0x0204: + err="The media script requires Python 2.4." + os.popen('dcop %s default error "%s"' %(APP_ID,err)) + sys.exit(err) + +import subprocess + +# Python 2.5 has this ... +try: + any(()) +except NameError: + def any(data): + """Return true of any of the items in the sequence 'data' are true. + + (ie non-zero or not empty)""" + try: + return reduce(lambda x,y: bool(x) or bool(y), data) + except TypeError: + return False + +def tell(data, feedback='info'): + """Report back to the user""" + l=['dcop', APP_ID, 'default', feedback] + if type(data) is type(''): + l.append(data) + else: + l.extend(data) + subprocess.Popen(l).communicate() + +class Player(object): + def __init__(self, display_name, playerType=None): + if playerType is None: + self.type = "audio" + else: + self.type=playerType + self.displayName=display_name + self.running = False + d={} + d.update(formatVariables) + d['player']=self.displayName + self._format = d + + def get(self, mode): + data=self.getData() + if any(data): + self._format['info']=self.format(*data) + if mode and mode != self.displayName: + self._format['intro']=self._format[mode] + else: + self._format['intro']=self._format[self.type.replace(',','').split()[0]] + return string.Template(outputFormat).safe_substitute(self._format) + return '' + + def format(self, title='', artist='', album=''): + """Return a 'pretty-printed' info string for the track. + + Uses formatStrings from above.""" + #Update args last to prevent non-sensical override in formatVariables + x={'title':title, 'artist':artist, 'album':album} + if FIXUP: + for i,j in x.items(): + if re.search(FIXUP,j): + x[i]='%s%s%s'%(QUOTE_BEFORE,j,QUOTE_AFTER) + self._format.update(x) + n=0 + if title: + n|=4 #Still binary to make you read the code ;p + if artist: + if artist == album: + n|=SelfTitled + else: + n|=2 + if album: + n|=1 + if n: + return string.Template(formatStrings[n]).safe_substitute(self._format) + return '' + + def getData(self): + """Implement this to do the work""" + return '' + + def reEncodeString(self, input): + if input: + try: + input = input.decode('utf-8') + except UnicodeError: + try: + input = input.decode('latin-1') + except UnicodeError: + input = input.decode('ascii', 'replace') + except NameError: + pass + return input.encode('utf-8') + + def test_format(self, title='', artist='', album=''): + s=[] + l=["to","by","on"] + if title: + s.append(title) + else: + album,artist=artist,album + l.pop() + if artist: + s.append(artist) + else: + del l[1] + if album: + s.append(album) + else: + l.pop() + t=["is listening"] + while l: + t.append(l.pop(0)) + t.append(s.pop(0)) + return ' '.join(t) + + def isRunning(self): + return self.running + +class DCOPPlayer(Player): + def __init__(self, display_name, service_name, getTitle='', getArtist='', getAlbum='',playerType=None): + Player.__init__(self, display_name, playerType) + self.serviceName=service_name + self._title=getTitle + self._artist=getArtist + self._album=getAlbum + self.DCOP="" + + def getData(self): + self.getService() + return (self.grab(self._title), self.grab(self._artist), self.grab(self._album)) + + def getService(self): + if self.DCOP: + return self.DCOP + running = re.findall('^' + self.serviceName + "(?:-\\d*)?$", DCOP_ITEMS, re.M) + if type(running) is list: + try: + running=running[0] + except IndexError: + running='' + self.DCOP=running.strip() + self.running=bool(self.DCOP) + return self.DCOP + + def grab(self, item): + if item and self.isRunning(): + return self.reEncodeString(os.popen("dcop %s %s"%(self.DCOP, item)).readline().rstrip('\n')) + return '' + + def isRunning(self): + self.getService() + return self.running + +class AmarokPlayer(DCOPPlayer): + def __init__(self): + DCOPPlayer.__init__(self,'Amarok','amarok','player title','player artist','player album') + + def getData(self): + data=DCOPPlayer.getData(self) + if not any(data): + data=(self.grab('player nowPlaying'),'','') + if not data[0]: + return '' + return data + +#class Amarok2Player(Player): +# def __init__(self): +# Player.__init__(self, 'Amarok2', 'audio') +# self.isRunning() +# +# def getData(self): +# playing=os.popen("qdbus org.mpris.amarok /Player PositionGet").readline().strip() != "0" +# if playing and self.isRunning(): +# for line in os.popen("qdbus org.mpris.amarok /Player GetMetadata").readlines(): +# if re.match("^title", line): +# title=self.reEncodeString(line.strip().split(None,1)[1]) +# if re.match("^artist", line): +# artist=self.reEncodeString(line.strip().split(None,1)[1]) +# if re.match("^album", line): +# album=self.reEncodeString(line.strip().split(None,1)[1]) +# return (title, artist, album) +# else: +# return '' +# +# def isRunning(self): +# qdbus_items=subprocess.Popen(['qdbus'], stdout=subprocess.PIPE).communicate()[0] +# running=re.findall('^ org.mpris.amarok$', qdbus_items, re.M) +# if type(running) is list: +# try: +# running=running[0] +# except IndexError: +# running='' +# self.running=bool(running.strip()) +# return self.running + +import socket + +class MPD(Player): + def __init__(self, display_name): + Player.__init__(self, display_name) + + self.host = "localhost" + self.port = 6600 + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.settimeout(0.5) + + try: + self.sock.connect((self.host, self.port)) + # just welcome message, we don't need it + self.sock.recv(1024) + self.running = True + except socket.error: + self.running = False + + def getData(self): + if not self.running: + return '' + try: + self.sock.send("currentsong\n") + data = self.sock.recv(1024) + except socket.error: + return '' + + # mpd sends OK always, so if nothing to show, we should seek for at least 3 chars + if len(data) < 4: + return '' + else: + # if there is Artist, Title and Album, get it + data=data.splitlines() + d={} + for i in data: + if ':' not in i: + continue + k,v=i.split(':',1) + d[k.lower()]=self.reEncodeString(v.strip()) + data=(d.get('title',''),d.get('artist',''),d.get('album','')) + if not any(data): + return d.get('file','') + return data + +class StupidPlayer(DCOPPlayer): + def getData(self): + data=DCOPPlayer.getData(self)[0] + if data: + if data.startswith('URL'): + # KMPlayer window titles in the form of "URL - file:///path/to/ - KMPlayer" + data=data.split(None,2)[2].rsplit(None,2)[0].rsplit('/')[-1] + else: + # KPlayer window titles in the form of " - KPlayer" + data=data.rsplit(None,2)[0] + return (data,'','') + return '' + +try: + import xmms.common + class XmmsPlayer(Player): + def __init__(self, display_name): + Player.__init__(self, display_name) + + def isRunning(self): + self.running = xmms.control.is_running() + return self.running + + def getData(self): + if self.isRunning() and xmms.control.is_playing(): + # get the position in the playlist for current playing track + index = xmms.control.get_playlist_pos(); + # get the title of the currently playing track + return (self.reEncodeString(xmms.control.get_playlist_title(index)),'','') + return '' + +except ImportError: + XmmsPlayer=Player + +class AudaciousPlayer(Player): + def __init__(self, display_name): + Player.__init__(self, display_name) + + def isRunning(self): + self.running = not os.system('audtool current-song') + return self.running + + def getData(self): + if self.isRunning() and not os.system('audtool playback-playing'): + # get the title of the currently playing track + data = os.popen('audtool current-song').read().strip() + data_list = data.split(' - ') + list_length = len(data_list) + if list_length == 1: + return (self.reEncodeString(data_list[0]),'','') + elif list_length == 3: + return (self.reEncodeString(data_list[-1]),data_list[0],data_list[1]) + else: + return (self.reEncodeString(data),'','') + else: + return '' + + +def playing(playerList, mode=None): + for i in playerList: + s=i.get(mode) + if s: + tell([IRC_SERVER, TARGET, s], 'say' ) + return 1 + return 0 + +def handleErrors(playerList, kind): + if kind: + kind=kind.strip() + kind=kind.center(len(kind)+2) + else: + kind= ' supported ' + x=any([i.running for i in playerList]) + if x: + l=[i.displayName for i in playerList if i.isRunning()] + err= "Nothing is playing in %s."%(', '.join(l)) + else: + err= "No%splayers are running."%(kind,) + tell(err,'error') + +def run(kind): + if not kind: + kind = '' + play=PLAYERS + else: + if kind in ['audio', 'video']: + unsorted=dict([(i.displayName.lower(),i) for i in PLAYERS if kind in i.type]) + play=[unsorted.pop(i.lower(),Player("ImproperlySupported")) for i in playerRankings[kind]] + if len(unsorted): + play.extend(unsorted.values()) + else: + play=[i for i in PLAYERS if i.displayName.lower() == kind] + try: + kind=play[0].displayName + except IndexError: + tell("%s is not a supported player."%(kind,),'error') + sys.exit(0) + + if not playing(play, kind): + handleErrors(play, kind) + + +#It would be so nice to just keep this pipe open and use it for all the dcop action, +#but of course you're supposed to use the big iron (language bindings) instead of +#the command line tools. One could consider `dcop` the bash dcop language binding, +#but of course when using shell you don't need to be efficient at all, right? + +DCOP_ITEMS=subprocess.Popen(['dcop'], stdout=subprocess.PIPE).communicate()[0] #re.findall("^amarok(?:-\\d*)?$",l,re.M) + +# Add your new players here. No more faulty logic due to copy+paste. + +PLAYERS = [ +AmarokPlayer(), +DCOPPlayer("JuK","juk","Player trackProperty Title","Player trackProperty Artist","Player trackProperty Album"), +DCOPPlayer("Noatun",'noatun',"Noatun title",playerType='audio, video'), +DCOPPlayer("Kaffeine","kaffeine","KaffeineIface title","KaffeineIface artist","KaffeineIface album",playerType='video, audio'), +StupidPlayer("KMPlayer","kmplayer","kmplayer-mainwindow#1 caption",playerType="video audio"), +StupidPlayer("KPlayer","kplayer","kplayer-mainwindow#1 caption",playerType="video audio"), +DCOPPlayer("KsCD","kscd","CDPlayer currentTrackTitle","CDPlayer currentArtist","CDPlayer currentAlbum"), +DCOPPlayer("kdetv","kdetv","KdetvIface channelName",playerType='video'), +AudaciousPlayer('Audacious'), XmmsPlayer('XMMS'), +DCOPPlayer("Yammi","yammi","YammiPlayer songTitle","YammiPlayer songArtist","YammiPlayer songAlbum"), +MPD('MPD') +] + +# Get rid of players that didn't get subclassed so they don't appear in the available players list +for i in PLAYERS[:]: + if type(i) is Player: + PLAYERS.remove(i) + +if REGEX_FIXUP: + FIXUP=REGEX_FIXUP +elif SIMPLE_FIXUP: + FIXUP="[%s]"%(SIMPLE_FIXUP) +else: + FIXUP='' + +# It all comes together right here +if __name__=="__main__": + + if not TARGET: + s="""media v2.0.1 for Konversation 1.0. One media command to rule them all, inspired from Kopete's now listening plugin. +Usage: + "\00312/media\017" - report what the first player found is playing + "\00312/media\017 [ '\00312audio\017' | '\00312video\017' ]" - report what is playing in a supported audio or video player + "\00312/media\017 { \00312Player\017 }" - report what is playing in \00312Player\017 if it is supported + + Available players are: + """ + ', '.join([("%s (%s)"%(i.displayName,i.type)) for i in PLAYERS]) + + for i in s.splitlines(): + tell(i) + #tell("%s"%(len(s.splitlines()),)) + # called from the server tab + pass + else: + try: + kind = sys.argv[4].lower() + except IndexError: + kind = None + + run(kind) + diff --git a/konversation/scripts/sayclip b/konversation/scripts/sayclip new file mode 100755 index 0000000..06b8234 --- /dev/null +++ b/konversation/scripts/sayclip @@ -0,0 +1,19 @@ +#!/bin/sh + +# Prints the contents of the clipbaord into Konversation with flood protection. +# Klipper must be running. +# Usage: /exec sayclip [pause-time] +# Pause time defaults to 1 second. +# By Gary Cramblitt (garycramblitt@comcast.net) +# Use however you wish. + +PORT=$1; +SERVER=$2; +TARGET=$3; +PAUSETIME="1s"; +if [ -n "$4" ] +then + PAUSETIME="$4" +fi + +dcop klipper klipper getClipboardContents | while read line; do dcop $PORT default say $SERVER "$TARGET" " $line"; sleep $PAUSETIME; done diff --git a/konversation/scripts/sysinfo b/konversation/scripts/sysinfo new file mode 100644 index 0000000..d2b3851 --- /dev/null +++ b/konversation/scripts/sysinfo @@ -0,0 +1,86 @@ +#!/bin/sh +# +# Licensed under GPL v2 or later at your option +# Copyright 2004 by Michiel de Boer +# Copyright 2006 by Emil Obermayr +# +# this version is stripped down to no-color +# +# get full original version at http://rebelhomicide.demon.nl/scripts/ + +PORT=$1; +SERVER=$2; +TARGET=$3; + +export LC_ALL="C" + +HN="$(hostname)" +OSKERN="$(uname -s) $(uname -r)" +if [ "$KDE_FULL_SESSION" = "true" ]; then + if [ "$KDE_SESSION_VERSION" = 4 ]; then + KDE="$(kde4-config --version | sed -n '2p' | sed 's/://;s/ *$//')" + else + KDE="$(kde-config --version | sed -n '2p' | sed 's/://;s/ *$//')" + fi +fi + +CPU=$(awk -F':' '/model name/{name=$2} + /cpu MHz/{mhz=int($2)} + /bogomips/ {bogo=int($2) +} +END{ + gsub (/ *\(tm\) */, " ", name); + gsub (/ *\(TM\) */, " ", name); + gsub (/ *Processor */, " ", name); + gsub (/ *$/, "", name); + gsub (/^ */, "", name); + printf "CPU: %s at %d MHz (%d bogomips)", name, mhz, bogo; +} +' /proc/cpuinfo ) + +HDD=$(df -lP| awk '($1~/\/dev/){ + use+=$3/1024^2; + tot+=$2/1024^2; + } + END{print "HD: " int(use) "/" int(tot) "GB"}') + +MEM=$(awk '($1=="MemTotal:"){tot=int($2/1024)} + ($1=="MemFree:"){free=int($2/1024)} + END{ +use=tot-free +print "RAM: " use "/" tot "MB"} +' /proc/meminfo) + +PROC="$(($(ps aux | wc -l)-1))" + +UPT=$(awk '{u="s"; +n=$1; +if (n>60){ + n2=n%60; + n/=60; + u="min"; + if (n>60){ + n2=n%60; + n/=60; + u="h"; + if (n>24){ + n2=n%24; + n/=24; + u="d"; + } + } + } +printf ("%d.%d%s up",n, n2, u); +}' /proc/uptime ) + +out="Sysinfo for '$HN': $OSKERN running $KDE, $CPU, $HDD, $MEM, $PROC proc's, ${UPT}" + +if [ "x$PORT" = "x" ] ; then + echo "$out" +else + if [ "x$TARGET" = "x" ] ; then + dcop $PORT default error "$out" + else + dcop $PORT default say $SERVER "$TARGET" "$out" + fi +fi diff --git a/konversation/scripts/tinyurl b/konversation/scripts/tinyurl new file mode 100755 index 0000000..14efde9 --- /dev/null +++ b/konversation/scripts/tinyurl @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# +# Creates a TinyURL from a long URL +# Licensed under GPL v2 or later at your option +# Copyright 2007 Terence Simpson + +PORT=$1 +SERVER=$2 +TARGET=$3 +export URL="$4" +NICK="$5" + +if test ! -z $URL; then + if test $(which curl); then + TINYURL="$(curl -s -i http://tinyurl.com/create.php?url=$URL|grep "The following URL" -A3|tail -1|awk -F\> '{print $3}'|sed 's, '{print $3}'|sed 's,= 86400) +{ + $days = int($seconds/86400); + $seconds = $seconds-($days*86400); +} +if($seconds >= 3600) +{ + $hours = int($seconds/3600); + $seconds = $seconds-($hours*3600); +} +if($seconds > 60) +{ + $minutes = int($seconds/60); +} +if( $days && $hours ) { + exec 'dcop', $PORT, 'default', 'say', $SERVER, $TARGET, "Uptime: $days days, $hours hours and $minutes minutes"; +} +elsif( !$days && $hours ) { + exec 'dcop', $PORT, 'default', 'say', $SERVER, $TARGET, "Uptime: $hours hours and $minutes minutes"; +} +elsif( $days && !$hours ) { + exec 'dcop', $PORT, 'default', 'say', $SERVER, $TARGET, "Uptime: $days days and $minutes minutes"; +} +elsif( !$days && !$hours ) { + exec 'dcop', $PORT, 'default', 'say', $SERVER, $TARGET, "Uptime: $minutes minutes"; +} + diff --git a/konversation/scripts/weather b/konversation/scripts/weather new file mode 100755 index 0000000..5d3dafb --- /dev/null +++ b/konversation/scripts/weather @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2005,2007 by İsmail Dönmez +# Licensed under GPL v2 or later at your option + +import sys +from subprocess import * + +port = sys.argv[1] +server = sys.argv[2] +target = sys.argv[3] + +msg_template = "Current weather for %%B%s%%B : Temperature: %%B%s%%B, Pressure: %%B%s%%B, Wind: %%B%s%%B" +msg_detailed_template = "Current weather for %%B%s%%B : %%B%s%%B, Temperature: %%B%s%%B, Pressure: %%B%s%%B, Wind: %%B%s%%B" + +def printMessage(message=None): + Popen(['dcop', port, 'default', 'say', server, target, message]).communicate() + +def printError(message=None): + Popen(['dcop', port, 'default', 'error', message]).communicate() + +def getData(section, station=None): + if station: + data = Popen(['dcop','KWeatherService','WeatherService', section, station], stdout=PIPE).communicate()[0].rstrip("\n") + else: + data = Popen(['dcop','KWeatherService','WeatherService', section], stdout=PIPE).communicate()[0].rstrip("\n") + + return data + +def stationMessage(station): + city = getData("stationName", station) + temperature = getData("temperature", station) + pressure = getData("pressure", station) + wind = getData("wind", station) + detail = getData("weather", station) + detail2 = getData("cover", station) + + if detail2: + if detail: + detail = detail+', '+detail2 + else: + detail = detail2 + + if detail: + return msg_detailed_template % (city,detail,temperature,pressure,wind) + else: + return msg_template % (city,temperature,pressure,wind) + +def printWeather(index): + stations = getData("listStations").split("\n") + + if index != None: + if index <= 0: + printError("Station index should be bigger than zero!") + elif index > len(stations): + printError("Station index is out of range") + else: + printMessage(stationMessage(stations[index-1])) + else: + for station in stations: + printMessage(stationMessage(station)) + +if __name__ == "__main__": + try: + index = int(sys.argv[4]) + except IndexError: + index = None + + printWeather(index) diff --git a/konversation/src/Makefile.am b/konversation/src/Makefile.am new file mode 100644 index 0000000..ee2fb29 --- /dev/null +++ b/konversation/src/Makefile.am @@ -0,0 +1,73 @@ +SUBDIRS = config linkaddressbook blowfish . + +METASOURCES = AUTO + +bin_PROGRAMS = konversation + +konversation_SOURCES = konviface.skel konviconfigdialog.cpp konversationstatusbar.cpp \ + konvisettingsdialog.cpp viewcontainer.cpp viewtree.cpp viewtreeitem.cpp konversationmainwindow.cpp \ + valuelistviewitem.cpp urlcatcher.cpp scriptlauncher.cpp rawlog.cpp konvdcop.cpp channellistpanel.cpp \ + konsolepanel.cpp identity.cpp statuspanel.cpp dccrecipientdialog.cpp topiccombobox.cpp nicksonline.cpp \ + dcctransferpanel.cpp dcctransferpanelitem.cpp highlight.cpp highlightviewitem.cpp modebutton.cpp \ + ignore_preferencesui.ui ignore_preferences.cpp ignore.cpp nicklistview.cpp ircinput.cpp \ + channeloptionsui.ui channeloptionsdialog.cpp ignorelistviewitem.cpp images.cpp quickbutton.cpp \ + chatwindow.cpp outputfilter.cpp logfilereader.cpp query.cpp konversationapplication.cpp nick.cpp \ + inputfilter.cpp channel.cpp ircview.cpp server.cpp main.cpp dcc_preferencesui.ui log_preferences.ui \ + tabs_preferencesui.ui tabs_preferences.cpp chatwindowappearance_preferences.ui irccolorchooserui.ui \ + colorsappearance_preferences.ui irccolorchooser.cpp channellistviewitem.cpp osd.cpp trayicon.cpp \ + dccchat.cpp multilineedit.cpp nickinfo.cpp dccresumedialog.cpp konversationsound.cpp quickconnectdialog.cpp \ + serverlistdialog.cpp dcctransfersend.cpp dcctransferrecv.cpp channelnick.cpp insertchardialog.cpp \ + irccharsets.cpp editnotifydialog.cpp common.cpp serverison.cpp sslsocket.cpp servergroupsettings.cpp \ + serversettings.cpp servergroupdialog.cpp ssllabel.cpp serverdialog.cpp channeldialog.cpp identitydialog.cpp \ + topiclabel.cpp notificationhandler.cpp joinchannelui.ui joinchanneldialog.cpp emoticon.cpp \ + chatwindowbehaviour_preferences.ui alias_preferencesui.ui osd_preferencesui.ui theme_preferencesui.ui \ + highlight_preferencesui.ui warnings_preferencesui.ui warnings_preferences.cpp quickbuttons_preferencesui.ui \ + watchednicknames_preferencesui.ui generalbehavior_preferences.ui connectionbehavior_preferences.ui \ + fontappearance_preferences.ui nicklistbehavior_preferencesui.ui konvibookmarkhandler.cpp konvibookmarkmenu.cpp \ + ircviewbox.cpp searchbar.cpp osd_preferences.cpp theme_preferences.cpp dcc_preferences.cpp \ + alias_preferences.cpp highlight_preferences.cpp watchednicknames_preferences.cpp quickbuttons_preferences.cpp \ + nicklistbehavior_preferences.cpp tabnotifications_preferences.ui multilinetextedit.cpp serverlistview.cpp \ + nicksonlineitem.cpp searchbarbase.ui autoreplace_preferencesui.ui autoreplace_preferences.cpp \ + servergroupdialogui.ui dcctransfer.cpp dcctransfermanager.cpp dcctransferdetailedinfopanelui.ui \ + dcctransferdetailedinfopanel.cpp dcccommon.cpp queuetunerbase.ui queuetuner.cpp ircqueue.cpp \ + connectionsettings.cpp connectionmanager.cpp awaymanager.cpp + +konversation_COMPILE_FIRST = config/preferences_base.h +konversation_LDADD = $(LIB_KIO) $(LIB_XSS) $(LIB_KABC) $(LIB_KIMIFACE) linkaddressbook/liblinkaddressbookui.la blowfish/libblowfish.la config/libkonversationconfig.la + +xdg_apps_DATA = konversation.desktop + +# set the include path for X, qt and KDE +INCLUDES= -Ilinkaddressbook -I$(srcdir)/linkaddressbook -Iblowfish -I$(srcdir)/blowfish\ + -Iconfig -I$(srcdir)/config $(all_includes) +# the library search path. +konversation_LDFLAGS = $(all_libraries) $(KDE_RPATH) + +rcdir = $(kde_datadir)/konversation +rc_DATA = konversationui.rc eventsrc + +kdelnk_DATA = konvirc.protocol konvirc6.protocol +kdelnkdir = $(kde_servicesdir) + +updatedir = $(kde_datadir)/kconf_update +update_DATA = konversation.upd +update_SCRIPTS = konversation-0.19-colors.pl konversation-0.19-sortorder.pl konversation-0.19-appearance.pl \ + konversation-0.19-tabplacement.pl konversation-0.19-custombrowser.pl \ + konversation-0.19-colorcodes.pl konversation-0.19-notifylists.pl \ + konversation-0.20-quickbuttons.pl konversation-0.20-customfonts.pl + +messages: rc.cpp + LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \ + if test -n "$$LIST"; then \ + $(XGETTEXT) $$LIST -o $(podir)/konversation.pot; \ + fi + +noinst_HEADERS = serverlistdialog.h dcctransfersend.h dcctransferrecv.h \ + insertchardialog.h editnotifydialog.h serverison.h \ + servergroupsettings.h serversettings.h servergroupdialog.h serverdialog.h channeldialog.h \ + identitydialog.h topiclabel.h channeloptionsdialog.h joinchanneldialog.h \ + highlight_preferences.h watchednicknames_preferences.h quickbuttons_preferences.h \ + nicklistbehavior_preferences.h konvisettingspage.h nicksonlineitem.h + +# User might still have these in src/ instead of src/config, so remove these in that case +CLEANFILES = preferences_base.h preferences_base.cpp watchednicknamesconfigcontroller.* diff --git a/konversation/src/alias_preferences.cpp b/konversation/src/alias_preferences.cpp new file mode 100644 index 0000000..ed3498e --- /dev/null +++ b/konversation/src/alias_preferences.cpp @@ -0,0 +1,223 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006 John Tapsell +*/ + +#include "alias_preferences.h" +#include "config/preferences.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +Alias_Config::Alias_Config(QWidget* parent, const char* name) + : Alias_ConfigUI(parent, name) +{ + // reset flag to defined state (used to block signals when just selecting a new item) + m_newItemSelected = false; + + // populate listview + loadSettings(); + + // make items react to drag & drop + aliasListView->setSorting(-1,false); + aliasListView->header()->setMovingEnabled(false); + + connect(aliasListView, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(entrySelected(QListViewItem*))); + connect(aliasListView, SIGNAL(clicked(QListViewItem*)), this, SLOT(entrySelected(QListViewItem*)) ); + connect(aliasListView, SIGNAL(moved()), this, SIGNAL(modified())); + + connect(aliasInput, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&))); + connect(replacementInput, SIGNAL(textChanged(const QString&)), this, SLOT(actionChanged(const QString&))); + + connect(newButton, SIGNAL(clicked()), this, SLOT(addEntry())); + connect(removeButton, SIGNAL(clicked()), this, SLOT(removeEntry())); +} + +Alias_Config::~Alias_Config() +{ +} + +void Alias_Config::loadSettings() +{ + setAliasListView(Preferences::aliasList()); +} + +void Alias_Config::saveSettings() +{ + QStringList newList=currentAliasList(); + Preferences::setAliasList(newList); + + // saved list is now old list, to check for changes + m_oldAliasList=newList; +} + +void Alias_Config::restorePageToDefaults() +{ + aliasListView->clear(); + setAliasListView(Preferences::defaultAliasList()); +} + +bool Alias_Config::hasChanged() +{ + return (currentAliasList() != m_oldAliasList); +} + +void Alias_Config::setAliasListView(const QStringList& aliasList) +{ + aliasListView->clear(); + + // Insert alias items backwards to get them sorted properly + for(int index=aliasList.count(); index!=0; index--) + { + QString item=aliasList[index-1]; + new KListViewItem(aliasListView,item.section(' ',0,0),item.section(' ',1)); + } + + aliasListView->setSelected(aliasListView->firstChild(), true); + // remember alias list + m_oldAliasList=aliasList; +} + +QStringList Alias_Config::currentAliasList() +{ + QStringList newList; + + QListViewItem* item=aliasListView->itemAtIndex(0); + while(item) + { + newList.append(item->text(0)+' '+item->text(1)); + item=item->itemBelow(); + } + return newList; +} + +// what to do when the user selects an item +void Alias_Config::entrySelected(QListViewItem* aliasEntry) +{ + // play it safe, assume disabling all widgets first + bool enabled = false; + + // check if there really was an item selected + if (aliasEntry) + { + // remember to enable the editing widgets + enabled = true; + // tell the editing widgets not to emit modified() on signals now + m_newItemSelected = true; + // update editing widget contents + aliasInput->setText(aliasEntry->text(0)); + replacementInput->setText(aliasEntry->text(1)); + // re-enable modified() signal on text changes in edit widgets + m_newItemSelected = false; + } + // enable or disable editing widgets + removeButton->setEnabled(enabled); + aliasLabel->setEnabled(enabled); + aliasInput->setEnabled(enabled); + replacementLabel->setEnabled(enabled); + replacementInput->setEnabled(enabled); +} + +// what to do when the user change the name of a quick button +void Alias_Config::nameChanged(const QString& newName) +{ + // get possible first selected item + QListViewItem* item = aliasListView->selectedItem(); + + // sanity check + if (item) + { + // rename item + item->setText(0,newName); + // tell the config system that something has changed + if (!m_newItemSelected) emit modified(); + } +} + +// what to do when the user change the action definition of a quick button +void Alias_Config::actionChanged(const QString& newAction) +{ + // get possible first selected item + QListViewItem* item = aliasListView->selectedItem(); + + // sanity check + if (item) + { + // rename item + item->setText(1,newAction); + // tell the config system that something has changed + if(!m_newItemSelected) emit modified(); + } +} + +// add button pressed +void Alias_Config::addEntry() +{ + // add new item at the bottom of list view + KListViewItem* newItem = new KListViewItem(aliasListView,aliasListView->lastChild(),i18n("New"),QString()); + // if successful ... + if (newItem) + { + // select new item and make it the current one + aliasListView->setSelected(newItem,true); + aliasListView->setCurrentItem(newItem); + // set input focus on item name edit + aliasInput->setFocus(); + // select all text to make overwriting easier + aliasInput->selectAll(); + // tell the config system that something has changed + emit modified(); + } +} + +// remove button pressed +void Alias_Config::removeEntry() +{ + // get possible first selected item + QListViewItem* item = aliasListView->selectedItem(); + + // sanity check + if (item) + { + // get item below the current one + QListViewItem* nextItem = item->itemBelow(); + // if there was none, get the one above + if(!nextItem) nextItem = item->itemAbove(); + + // remove the item from the list + delete item; + + // check if we found the next item + if (nextItem) + { + // select the item and make it the current ite, + aliasListView->setSelected(nextItem,true); + aliasListView->setCurrentItem(nextItem); + } + else + { + // no next item found, this means the list is empty + entrySelected(0); + } + // tell the config system that somethig has changed + emit modified(); + } +} + +#include "alias_preferences.moc" diff --git a/konversation/src/alias_preferences.h b/konversation/src/alias_preferences.h new file mode 100644 index 0000000..4f1cfff --- /dev/null +++ b/konversation/src/alias_preferences.h @@ -0,0 +1,51 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006 John Tapsell +*/ + +#ifndef EXALIASPREFERENCES_H +#define EXALIASPREFERENCES_H + +#include "alias_preferencesui.h" +#include "konvisettingspage.h" + +class Alias_Config : public Alias_ConfigUI, public KonviSettingsPage +{ + Q_OBJECT + + public: + explicit Alias_Config(QWidget* parent, const char* name = 0); + ~Alias_Config(); + + virtual void saveSettings(); + virtual void loadSettings(); + virtual void restorePageToDefaults(); + virtual bool hasChanged(); + + signals: + void modified(); + + protected slots: + void entrySelected(QListViewItem* aliasEntry); + void nameChanged(const QString& newName); + void actionChanged(const QString& newAction); + void addEntry(); + void removeEntry(); + + protected: + void setAliasListView(const QStringList& aliasList); + + bool m_newItemSelected; + + QStringList m_oldAliasList; + QStringList currentAliasList(); +}; + +#endif diff --git a/konversation/src/alias_preferencesui.ui b/konversation/src/alias_preferencesui.ui new file mode 100644 index 0000000..2e144cc --- /dev/null +++ b/konversation/src/alias_preferencesui.ui @@ -0,0 +1,174 @@ + +Alias_ConfigUI + + + Alias_ConfigUI + + + + 0 + 0 + 292 + 206 + + + + + unnamed + + + 0 + + + + layout7 + + + + unnamed + + + + aliasLabel + + + false + + + Alias: + + + + + replacementLabel + + + false + + + Replacement: + + + + + aliasInput + + + false + + + + + replacementInput + + + false + + + + + + + + Alias + + + true + + + true + + + + + Replacement + + + true + + + true + + + + aliasListView + + + true + + + Auto + + + true + + + true + + + true + + + true + + + + + layout8 + + + + unnamed + + + + newButton + + + &New... + + + + + removeButton + + + &Remove + + + + + spacer18 + + + Vertical + + + Expanding + + + + 20 + 350 + + + + + + + + + aliasListView + aliasInput + replacementInput + newButton + removeButton + + + + + klineedit.h + klineedit.h + klistview.h + + diff --git a/konversation/src/autoreplace_preferences.cpp b/konversation/src/autoreplace_preferences.cpp new file mode 100644 index 0000000..67fd9cd --- /dev/null +++ b/konversation/src/autoreplace_preferences.cpp @@ -0,0 +1,403 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006 Eike Hein +*/ + +#include "autoreplace_preferences.h" +#include "config/preferences.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DIRECTION_OUTPUT 0 +#define DIRECTION_INPUT 1 +#define DIRECTION_BOTH 2 + + +Autoreplace_Config::Autoreplace_Config(QWidget* parent, const char* name) + : Autoreplace_ConfigUI(parent, name) +{ + // reset flag to defined state (used to block signals when just selecting a new item) + m_newItemSelected=false; + + //Check if the regexp editor is installed + bool installed = !KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty(); + + if(installed) + { + regExpEditorButton->setEnabled(true); + QToolTip::add(regExpEditorButton, i18n("Click to run Regular Expression Editor (KRegExpEditor)")); + } + else + { + regExpEditorButton->setEnabled(false); + QToolTip::add(regExpEditorButton, i18n("The Regular Expression Editor (KRegExpEditor) is not installed")); + } + + // populate combobox + directionCombo->insertItem(i18n("Outgoing"),DIRECTION_OUTPUT); + directionCombo->insertItem(i18n("Incoming"),DIRECTION_INPUT); + directionCombo->insertItem(i18n("Both"),DIRECTION_BOTH); + + // make items react to drag & drop + patternListView->setSorting(-1,false); + patternListView->setShowSortIndicator(true); + patternListView->setShadeSortColumn(true); + patternListView->header()->setMovingEnabled(false); + + // populate listview + loadSettings(); + + connect(patternListView, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(entrySelected(QListViewItem*))); + connect(patternListView, SIGNAL(clicked(QListViewItem*)), this, SLOT(entrySelected(QListViewItem*))); + connect(patternListView, SIGNAL(moved()), SIGNAL(modified())); + + connect(patternListView, SIGNAL(aboutToMove()), SLOT(disableSort())); + connect(patternListView->header(), SIGNAL(clicked(int)), SLOT(sort(int))); + + connect(directionCombo, SIGNAL(activated(int)), this, SLOT(directionChanged(int))); + + connect(patternInput, SIGNAL(textChanged(const QString&)), this, SLOT(patternChanged(const QString&))); + connect(regExpEditorButton, SIGNAL(clicked()), this, SLOT(showRegExpEditor())); + connect(replacementInput, SIGNAL(textChanged(const QString&)), this, SLOT(replacementChanged(const QString&))); + + connect(newButton, SIGNAL(clicked()), this, SLOT(addEntry())); + connect(removeButton, SIGNAL(clicked()), this, SLOT(removeEntry())); +} + +Autoreplace_Config::~Autoreplace_Config() +{ +} + +void Autoreplace_Config::loadSettings() +{ + setAutoreplaceListView(Preferences::autoreplaceList()); + + // remember autoreplace list for hasChanged() + m_oldAutoreplaceList=Preferences::autoreplaceList(); +} + +// fill listview with autoreplace definitions +void Autoreplace_Config::setAutoreplaceListView(const QStringList &autoreplaceList) +{ + // clear listView + patternListView->clear(); + // go through the list + for(unsigned int index=autoreplaceList.count();index!=0;index--) + { + // get autoreplace definition + QString definition=autoreplaceList[index-1]; + // cut definition apart in name and action, and create a new listview item + QCheckListItem* newItem=new QCheckListItem(patternListView,QString(),QCheckListItem::CheckBox); + // Regular expression? + if(definition.section(',',0,0)=="1") newItem->setOn(true); + // direction input/output/both + if(definition.section(',',1,1)=="i") newItem->setText(1,directionCombo->text(DIRECTION_INPUT)); + else if(definition.section(',',1,1)=="o") newItem->setText(1,directionCombo->text(DIRECTION_OUTPUT)); + else if(definition.section(',',1,1)=="io") newItem->setText(1,directionCombo->text(DIRECTION_BOTH)); + // pattern + newItem->setText(2,definition.section(',',2,2)); + // replacement + newItem->setText(3,definition.section(',',3)); + // hidden column, so we are independent of the i18n()ed display string + newItem->setText(4,definition.section(',',1,1)); + } // for + patternListView->setSelected(patternListView->firstChild(), true); +} + +// save autoreplace entries to configuration +void Autoreplace_Config::saveSettings() +{ + // get configuration object + KConfig* config=kapp->config(); + + // delete all patterns + config->deleteGroup("Autoreplace List"); + // create new empty autoreplace group + config->setGroup("Autoreplace List"); + + // create empty list + QStringList newList=currentAutoreplaceList(); + + // check if there are any patterns in the list view + if(newList.count()) + { + // go through all patterns and save them into the configuration + for(unsigned int index=0;indexwriteEntry(QString("Autoreplace%1").arg(index),newList[index]+'#'); + } // for + } + // if there were no entries at all, write a dummy entry to prevent KConfigXT from "optimizing" + // the group out, which would in turn make konvi restore the default entries + else + config->writeEntry("Empty List",QString()); + + // set internal autoreplace list + Preferences::setAutoreplaceList(newList); + + // remember autoreplace list for hasChanged() + m_oldAutoreplaceList=newList; +} + +void Autoreplace_Config::restorePageToDefaults() +{ + setAutoreplaceListView(Preferences::defaultAutoreplaceList()); +} + +QStringList Autoreplace_Config::currentAutoreplaceList() +{ + // get first item of the autoreplace listview + QListViewItem* item=patternListView->firstChild(); + // create empty list + QStringList newList; + + // go through all items and save them into the configuration + while(item) + { + QString checked="0"; + if(static_cast(item)->isOn()) checked="1"; + + // remember entry in internal list (col 4 is hidden for input/output) + newList.append(checked+','+item->text(4)+','+item->text(2)+','+item->text(3)); + // get next item in the listview + item=item->itemBelow(); + } // while + + // return list + return newList; +} + +bool Autoreplace_Config::hasChanged() +{ + return(m_oldAutoreplaceList!=currentAutoreplaceList()); +} + +// slots + +// what to do when the user selects an item +void Autoreplace_Config::entrySelected(QListViewItem* autoreplaceEntry) +{ + // play it safe, assume disabling all widgets first + bool enabled=false; + + // check if there really was an item selected + if(autoreplaceEntry) + { + // remember to enable the editing widgets + enabled=true; + + // tell the editing widgets not to emit modified() on signals now + m_newItemSelected=true; + // update editing widget contents + patternInput->setText(autoreplaceEntry->text(2)); + replacementInput->setText(autoreplaceEntry->text(3)); + + // set combobox to selected item + int itemIndex=0; + QString direction=autoreplaceEntry->text(4); + if(direction=="i") itemIndex=DIRECTION_INPUT; + else if(direction=="o") itemIndex=DIRECTION_OUTPUT; + else if(direction=="io") itemIndex=DIRECTION_BOTH; + directionCombo->setCurrentItem(itemIndex); + // re-enable modified() signal on text changes in edit widgets + m_newItemSelected=false; + } + // enable or disable editing widgets + removeButton->setEnabled(enabled); + directionLabel->setEnabled(enabled); + directionCombo->setEnabled(enabled); + patternLabel->setEnabled(enabled); + patternInput->setEnabled(enabled); + replacementLabel->setEnabled(enabled); + replacementInput->setEnabled(enabled); + + if(!KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty()) + { + regExpEditorButton->setEnabled(enabled); + } + + // make checkboxes work + emit modified(); +} + +// what to do when the user changes the direction of an entry +void Autoreplace_Config::directionChanged(int newDirection) +{ + // get possible selected item + QListViewItem* item=patternListView->selectedItem(); + + // sanity check + if(item) + { + // prepare hidden identifier string + QString id; + // find the direction strings to set up in the item + if(newDirection==DIRECTION_INPUT) id="i"; + else if(newDirection==DIRECTION_OUTPUT) id="o"; + else if(newDirection==DIRECTION_BOTH) id="io"; + // rename direction + item->setText(1,directionCombo->text(newDirection)); + item->setText(4,id); + // tell the config system that something has changed + if(!m_newItemSelected) emit modified(); + } +} + +// what to do when the user changes the pattern of an entry +void Autoreplace_Config::patternChanged(const QString& newPattern) +{ + // get possible selected item + QListViewItem* item=patternListView->selectedItem(); + + // sanity check + if(item) + { + // rename pattern + item->setText(2,newPattern); + // tell the config system that something has changed + if(!m_newItemSelected) emit modified(); + } +} + +// what to do when the user changes the replacement of an entry +void Autoreplace_Config::replacementChanged(const QString& newReplacement) +{ + // get possible selected item + QListViewItem* item=patternListView->selectedItem(); + + // sanity check + if(item) + { + // rename item + item->setText(3,newReplacement); + // tell the config system that something has changed + if(!m_newItemSelected) emit modified(); + } +} + +// add button pressed +void Autoreplace_Config::addEntry() +{ + disableSort(); + + // add new item at the bottom of list view + QCheckListItem* newItem=new QCheckListItem(patternListView,QString(),QCheckListItem::CheckBox); + // if successful ... + if(newItem) + { + // set default direction + newItem->setText(1,directionCombo->text(DIRECTION_OUTPUT)); + // set default pattern name + newItem->setText(2,i18n("New")); + // set default direction + newItem->setText(4,"o"); + // select new item and make it the current one + patternListView->setSelected(newItem,true); + patternListView->setCurrentItem(newItem); + // set input focus on item pattern edit + patternInput->setFocus(); + // select all text to make overwriting easier + patternInput->selectAll(); + // tell the config system that something has changed + emit modified(); + } +} + +// remove button pressed +void Autoreplace_Config::removeEntry() +{ + // get possible first selected item + QListViewItem* item=patternListView->selectedItem(); + + // sanity check + if(item) + { + // get item below the current one + QListViewItem* nextItem=item->itemBelow(); + // if there was none, get the one above + if(!nextItem) nextItem=item->itemAbove(); + + // remove the item from the list + delete item; + + // check if we found the next item + if(nextItem) + { + // select the item and make it the current item + patternListView->setSelected(nextItem,true); + patternListView->setCurrentItem(nextItem); + } + else + { + // no next item found, this means the list is empty + entrySelected(0); + } + // tell the config system that somethig has changed + emit modified(); + } +} + +void Autoreplace_Config::sort(int column) +{ + bool ascending = true; + + if (patternListView->sortColumn() != -1) + ascending = (patternListView->sortOrder() == Qt::Ascending); + + patternListView->setSorting(column, ascending); + + emit modified(); +} + +void Autoreplace_Config::disableSort() +{ + patternListView->setSorting(-1); +} + +void Autoreplace_Config::showRegExpEditor() +{ + QDialog *editorDialog = + KParts::ComponentFactory::createInstanceFromQuery( "KRegExpEditor/KRegExpEditor" ); + + if(editorDialog) + { + // kdeutils was installed, so the dialog was found. Fetch the editor interface. + KRegExpEditorInterface *reEditor = + static_cast(editorDialog->qt_cast( "KRegExpEditorInterface" ) ); + Q_ASSERT(reEditor); // This should not fail! + reEditor->setRegExp(patternInput->text()); + int dlgResult = editorDialog->exec(); + + if(dlgResult == QDialog::Accepted) + { + QString re = reEditor->regExp(); + patternInput->setText(re); + } + + delete editorDialog; + } +} + +#include "autoreplace_preferences.moc" diff --git a/konversation/src/autoreplace_preferences.h b/konversation/src/autoreplace_preferences.h new file mode 100644 index 0000000..303487c --- /dev/null +++ b/konversation/src/autoreplace_preferences.h @@ -0,0 +1,57 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006 Eike Hein +*/ + +#ifndef AUTOREPLACECONFIG_H +#define AUTOREPLACECONFIG_H + +#include "autoreplace_preferencesui.h" +#include "konvisettingspage.h" + + +class Autoreplace_Config : public Autoreplace_ConfigUI, public KonviSettingsPage +{ + Q_OBJECT + + public: + explicit Autoreplace_Config(QWidget* parent, const char* name=NULL); + ~Autoreplace_Config(); + + virtual void saveSettings(); + virtual void loadSettings(); + virtual void restorePageToDefaults(); + + virtual bool hasChanged(); + + signals: + void modified(); + + protected slots: + void entrySelected(QListViewItem* autoreplaceEntry); + void directionChanged(int newDirection); + void patternChanged(const QString& newPattern); + void replacementChanged(const QString& newReplacement); + void addEntry(); + void removeEntry(); + void sort(int column); + void disableSort(); + void showRegExpEditor(); + + protected: + void setAutoreplaceListView(const QStringList &autoreplaceList); + + bool m_newItemSelected; + + QStringList m_oldAutoreplaceList; + QStringList currentAutoreplaceList(); +}; + +#endif diff --git a/konversation/src/autoreplace_preferencesui.ui b/konversation/src/autoreplace_preferencesui.ui new file mode 100644 index 0000000..db6521c --- /dev/null +++ b/konversation/src/autoreplace_preferencesui.ui @@ -0,0 +1,292 @@ + +Autoreplace_ConfigUI +Dario Abatianni + + + Autoreplace_ConfigUI + + + + 0 + 0 + 586 + 576 + + + + + unnamed + + + 0 + + + + layout6 + + + + unnamed + + + + newButton + + + Ne&w + + + + + removeButton + + + R&emove + + + + + spacer1 + + + Vertical + + + Expanding + + + + 20 + 506 + + + + + + + + + RegEx + + + true + + + true + + + + + Replace In + + + true + + + true + + + + + Find + + + true + + + true + + + + + Replace With + + + true + + + true + + + + patternListView + + + + 7 + 7 + 0 + 1 + + + + true + + + true + + + true + + + false + + + true + + + + + layout16 + + + + unnamed + + + + regExpEditorButton + + + false + + + + 0 + 0 + 0 + 0 + + + + ... + + + + + + + + directionLabel + + + false + + + + 5 + 5 + 0 + 0 + + + + Replace in: + + + + + patternInput + + + false + + + + 7 + 0 + 0 + 0 + + + + + + replacementInput + + + false + + + + 7 + 0 + 0 + 0 + + + + + + patternLabel + + + false + + + + 5 + 5 + 0 + 0 + + + + Find: + + + + + replacementLabel + + + false + + + + 5 + 5 + 0 + 0 + + + + Replace with: + + + + + directionCombo + + + false + + + + 5 + 0 + 1 + 0 + + + + + + + + + patternListView + directionCombo + patternInput + regExpEditorButton + replacementInput + newButton + removeButton + + + + klistview.h + klineedit.h + klineedit.h + + diff --git a/konversation/src/awaymanager.cpp b/konversation/src/awaymanager.cpp new file mode 100644 index 0000000..5676bd1 --- /dev/null +++ b/konversation/src/awaymanager.cpp @@ -0,0 +1,372 @@ +/* + 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. +*/ + +/* + Copyright (c) 1999 Martin R. Jones + Copyright (C) 2008 Eike Hein +*/ + +#include "awaymanager.h" +#include "konversationapplication.h" +#include "konversationmainwindow.h" +#include "connectionmanager.h" +#include "server.h" +#include "preferences.h" + +#include + +#include +#include +#include + +#include + +#ifdef Q_WS_X11 +#include +#include +#include +#include +#ifdef HAVE_XSCREENSAVER +#define HasScreenSaver +#include +#endif +#endif + +// Don't use XIdle for now, it's experimental. +#undef HAVE_XIDLE +#undef HasXidle + + +struct AwayManagerPrivate +{ + int mouseX; + int mouseY; + unsigned int mouseMask; +#ifdef Q_WS_X11 + Window root; + Screen* screen; + Time xIdleTime; +#endif + bool useXidle; + bool useMit; +}; + +AwayManager::AwayManager(QObject* parent) : QObject(parent) +{ + int dummy = 0; + dummy = dummy; + + d = new AwayManagerPrivate; + + d->mouseX = d->mouseY = 0; + d->mouseMask = 0; + d->useXidle = false; + d->useMit = false; + + m_connectionManager = static_cast(kapp)->getConnectionManager(); + +#ifdef Q_WS_X11 + Display* display = qt_xdisplay(); + d->root = DefaultRootWindow(display); + d->screen = ScreenOfDisplay(display, DefaultScreen (display)); + + d->xIdleTime = 0; +#endif + +#ifdef HasXidle + d->useXidle = XidleQueryExtension(qt_xdisplay(), &dummy, &dummy); +#endif + +#ifdef HasScreenSaver + if (!d->useXidle) + d->useMit = XScreenSaverQueryExtension(qt_xdisplay(), &dummy, &dummy); +#endif + + m_activityTimer = new QTimer(this, "AwayTimer"); + connect(m_activityTimer, SIGNAL(timeout()), this, SLOT(checkActivity())); + + m_idleTime.start(); +} + +AwayManager::~AwayManager() +{ + delete d; +} + +void AwayManager::identitiesChanged() +{ + QValueList newIdentityList; + + QPtrList serverList = m_connectionManager->getServerList(); + Server* server = 0; + + for (server = serverList.first(); server; server = serverList.next()) + { + IdentityPtr identity = server->getIdentity(); + + if (identity && identity->getAutomaticAway() && server->isConnected()) + newIdentityList.append(identity->id()); + } + + m_identitiesOnAutoAway = newIdentityList; + + toggleTimer(); +} + +void AwayManager::identityOnline(int identityId) +{ + IdentityPtr identity = Preferences::identityById(identityId); + + if (identity && identity->getAutomaticAway() && + !m_identitiesOnAutoAway.contains(identityId)) + { + m_identitiesOnAutoAway.append(identityId); + + toggleTimer(); + } +} + +void AwayManager::identityOffline(int identityId) +{ + if (m_identitiesOnAutoAway.contains(identityId)) + { + m_identitiesOnAutoAway.remove(identityId); + + toggleTimer(); + } +} + +void AwayManager::toggleTimer() +{ + if (m_identitiesOnAutoAway.count() > 0) + { + if (!m_activityTimer->isActive()) + m_activityTimer->start(Preferences::autoAwayPollInterval() * 1000); + } + else if (m_activityTimer->isActive()) + m_activityTimer->stop(); +} + +void AwayManager::checkActivity() +{ + // Allow the event loop to be called, to avoid deadlock. + static bool rentrencyProtection = false; + if (rentrencyProtection) return; + + rentrencyProtection = true; + + DCOPRef screenSaver("kdesktop", "KScreensaverIface"); + DCOPReply isBlanked = screenSaver.callExt("isBlanked", DCOPRef::UseEventLoop, 10); + + rentrencyProtection = false; + + if (!(isBlanked.isValid() && isBlanked.type == "bool" && ((bool)isBlanked))) + implementIdleAutoAway(Xactivity()); +} + +bool AwayManager::Xactivity() +{ + bool activity = false; + +#ifdef Q_WS_X11 + Display* display = qt_xdisplay(); + Window dummyW; + int dummyC; + unsigned int mask; + int rootX; + int rootY; + + if (!XQueryPointer (display, d->root, &(d->root), &dummyW, &rootX, &rootY, + &dummyC, &dummyC, &mask)) + { + // Figure out which screen the pointer has moved to. + for (int i = 0; i < ScreenCount(display); i++) + { + if (d->root == RootWindow(display, i)) + { + d->screen = ScreenOfDisplay (display, i); + + break; + } + } + } + + Time xIdleTime = 0; + + #ifdef HasXidle + if (d->useXidle) + XGetIdleTime(display, &xIdleTime); + else + #endif + { + #ifdef HasScreenSaver + if (d->useMit) + { + static XScreenSaverInfo* mitInfo = 0; + if (!mitInfo) mitInfo = XScreenSaverAllocInfo(); + XScreenSaverQueryInfo (display, d->root, mitInfo); + xIdleTime = mitInfo->idle; + } + #endif + } + + if (rootX != d->mouseX || rootY != d->mouseY || mask != d->mouseMask + || ((d->useXidle || d->useMit) && xIdleTime < d->xIdleTime + 2000)) + { + // Set by setManagedIdentitiesAway() to skip X-based activity checking for one + // round, to avoid jumping on residual mouse activity after manual screensaver + // activation. + if (d->mouseX != -1) activity = true; + + d->mouseX = rootX; + d->mouseY = rootY; + d->mouseMask = mask; + d->xIdleTime = xIdleTime; + } +#endif + + return activity; +} + +void AwayManager::implementIdleAutoAway(bool activity) +{ + if (activity) + { + m_idleTime.start(); + + QPtrList serverList = m_connectionManager->getServerList(); + Server* server = 0; + + for (server = serverList.first(); server; server = serverList.next()) + { + IdentityPtr identity = server->getIdentity(); + + if (m_identitiesOnAutoAway.contains(identity->id()) && identity->getAutomaticUnaway() + && server->isConnected() && server->isAway()) + { + server->requestUnaway(); + } + } + } + else + { + long int idleTime = m_idleTime.elapsed() / 1000; + + QValueList identitiesIdleTimeExceeded; + QValueList::ConstIterator it; + + for (it = m_identitiesOnAutoAway.begin(); it != m_identitiesOnAutoAway.end(); ++it) + { + if (idleTime >= Preferences::identityById((*it))->getAwayInactivity() * 60) + identitiesIdleTimeExceeded.append((*it)); + } + + QPtrList serverList = m_connectionManager->getServerList(); + Server* server = 0; + + for (server = serverList.first(); server; server = serverList.next()) + { + int identityId = server->getIdentity()->id(); + + if (identitiesIdleTimeExceeded.contains(identityId) && server->isConnected() && !server->isAway()) + server->requestAway(); + } + } +} + +void AwayManager::setManagedIdentitiesAway() +{ + // Used to skip X-based activity checking for one round, to avoid jumping + // on residual mouse activity after manual screensaver activation. + d->mouseX = -1; + + QPtrList serverList = m_connectionManager->getServerList(); + Server* server = 0; + + for (server = serverList.first(); server; server = serverList.next()) + { + if (m_identitiesOnAutoAway.contains(server->getIdentity()->id()) && server->isConnected() && !server->isAway()) + server->requestAway(); + } +} + +void AwayManager::setManagedIdentitiesUnaway() +{ + QPtrList serverList = m_connectionManager->getServerList(); + Server* server = 0; + + for (server = serverList.first(); server; server = serverList.next()) + { + IdentityPtr identity = server->getIdentity(); + + if (m_identitiesOnAutoAway.contains(identity->id()) && identity->getAutomaticUnaway() + && server->isConnected() && server->isAway()) + { + server->requestUnaway(); + } + } +} + +void AwayManager::requestAllAway(const QString& reason) +{ + QPtrList serverList = m_connectionManager->getServerList(); + Server* server = 0; + + for (server = serverList.first(); server; server = serverList.next()) + if (server->isConnected()) server->requestAway(reason); +} + +void AwayManager::requestAllUnaway() +{ + QPtrList serverList = m_connectionManager->getServerList(); + Server* server = 0; + + for (server = serverList.first(); server; server = serverList.next()) + if (server->isConnected() && server->isAway()) server->requestUnaway(); +} + +void AwayManager::toggleGlobalAway(bool away) +{ + if (away) + requestAllAway(); + else + requestAllUnaway(); +} + +void AwayManager::updateGlobalAwayAction(bool away) +{ + KonversationApplication* konvApp = static_cast(kapp); + KToggleAction* awayAction = static_cast(konvApp->getMainWindow()->actionCollection()->action("toggle_away")); + + if (!awayAction) return; + + if (away) + { + QPtrList serverList = m_connectionManager->getServerList(); + Server* server = 0; + uint awayCount = 0; + + for (server = serverList.first(); server; server = serverList.next()) + { + if (server->isAway()) + awayCount++; + } + + if (awayCount == serverList.count()) + { + awayAction->setChecked(true); + awayAction->setIcon("konversationaway"); + } + } + else + { + awayAction->setChecked(false); + awayAction->setIcon("konversationavailable"); + } +} + +#include "awaymanager.moc" diff --git a/konversation/src/awaymanager.h b/konversation/src/awaymanager.h new file mode 100644 index 0000000..76819f3 --- /dev/null +++ b/konversation/src/awaymanager.h @@ -0,0 +1,73 @@ +/* + 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. +*/ + +/* + Copyright (C) 2008 Eike Hein +*/ + +#ifndef AWAYMANAGER_H +#define AWAYMANAGER_H + + +#include +#include + + +class ConnectionManager; + +class QTimer; + + +struct AwayManagerPrivate; + + +class AwayManager : public QObject +{ + Q_OBJECT + + public: + explicit AwayManager(QObject* parent = 0); + ~AwayManager(); + + + public slots: + void identitiesChanged(); + + void identityOnline(int identityId); + void identityOffline(int identityId); + + void requestAllAway(const QString& reason = ""); + void requestAllUnaway(); + + void setManagedIdentitiesAway(); + void setManagedIdentitiesUnaway(); + + void toggleGlobalAway(bool away); + void updateGlobalAwayAction(bool away); + + + private slots: + void checkActivity(); + + + private: + void toggleTimer(); + bool Xactivity(); + + void implementIdleAutoAway(bool activity); + + AwayManagerPrivate* d; + + QTime m_idleTime; + QTimer* m_activityTimer; + + QValueList m_identitiesOnAutoAway; + + ConnectionManager* m_connectionManager; +}; + +#endif diff --git a/konversation/src/blowfish/BlowfishCbc.cpp b/konversation/src/blowfish/BlowfishCbc.cpp new file mode 100644 index 0000000..fd8ff2f --- /dev/null +++ b/konversation/src/blowfish/BlowfishCbc.cpp @@ -0,0 +1,654 @@ +/* + Public Domain. Without any warranty. + + Copyright (C) George Anescu + Copyright (C) mouser +*/ + +//--------------------------------------------------------------------------- +//The implementation of blowfish for CBC mode is from http://www.thecodeproject.com/cpp/blowfish.asp by George Anescu +// I removed exception handling, so it is callers responsibility to insure +// that strings are length multiples of 8 bytes +// -mouser 1/08/05 +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Mouser 1/14/05 +// I'm not sure this implementation of cbc is exactly the same as other cbc +// algorithms you may find, though the different is insignificant and just +// requires you to call your other algorithm slightly differently. +// This blowfish cbc class basically pretends that the IV is 00000000 but +// but that the first 8byte block of the plaintext to encrypt is treated +// like the IV (ie its a random nonce). +// In other words, it does not accept a separate IV, but expects the first +// 8bytes to be the IV (this is a slight difference from textbook cbc since +// the encrypted IV is now part of the ciphertext). +// This actually works out well for us since we want to send the IV to +// our recipient as part of our message. +// ANYWAY, bottom line is, if you have a blowfish implementation that takes +// an explicit IV parameter as its input, just pass it 0 as the IV, and +// when encrypting, prefix your plaintext with an 8 byte random nonce, and +// you will have a compatible algorithm. Remember its not that this +// algorithm uses a fixed IV of 0, but rather that the IV is the first +// block of the test to encrypt. +//--------------------------------------------------------------------------- + + +//////////////////////////////////////////////////////////////////////////// +/// +// BlowFish.cpp +// +// Implementation of Bruce Schneier's BLOWFISH algorithm from "Applied +// Cryptography", Second Edition. + +#include "BlowfishCbc.h" + +#include +#include + +//#include + +//Initialization with a fixed string which consists of the hexadecimal digits of PI (less the initial 3) +//P-array, 18 32-bit subkeys +const unsigned int CBlowFish::scm_auiInitP[18] = { + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b +}; + +//Four 32-bit S-boxes with 256 entries each +const unsigned int CBlowFish::scm_auiInitS[4][256] = { + //0 + {0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a}, + + //1 + {0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7}, + + //2 + {0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0}, + + //3 + {0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6} +}; + +//Constructor - Initialize the P and S boxes for a given Key +CBlowFish::CBlowFish(unsigned char* ucKey, size_t keysize, const SBlock& roChain) : m_oChain0(roChain), m_oChain(roChain) +{ + if(keysize<1) + // throw exception("Incorrect key length"); + return; + + + //Check the Key - the key length should be between 1 and 56 bytes + if(keysize>56) + keysize = 56; + unsigned char aucLocalKey[56]; + unsigned int i, j; + memcpy(aucLocalKey, ucKey, keysize); + //Reflexive Initialization of the Blowfish. + //Generating the Subkeys from the Key flood P and S boxes with PI + memcpy(m_auiP, scm_auiInitP, sizeof m_auiP); + memcpy(m_auiS, scm_auiInitS, sizeof m_auiS); + //Load P boxes with key bytes + const unsigned char* p = aucLocalKey; + unsigned int x=0; + //Repeatedly cycle through the key bits until the entire P array has been XORed with key bits + unsigned int iCount = 0; + for(i=0; i<18; i++) + { + x=0; + for(int n=4; n--; ) + { + //int iVal = (int)(*p); + x <<= 8; + x |= *(p++); + iCount++; + if(iCount == keysize) + { + //All bytes used, so recycle bytes + iCount = 0; + p = aucLocalKey; + } + } + m_auiP[i] ^= x; + } + //Reflect P and S boxes through the evolving Blowfish + SBlock block(0UL,0UL); //all-zero block + for(i=0; i<18; ) + Encrypt(block), m_auiP[i++] = block.m_uil, m_auiP[i++] = block.m_uir; + for(j=0; j<4; j++) + for(int k=0; k<256; ) + Encrypt(block), m_auiS[j][k++] = block.m_uil, m_auiS[j][k++] = block.m_uir; +} + +//Sixteen Round Encipher of Block +void CBlowFish::Encrypt(SBlock& block) +{ + unsigned int uiLeft = block.m_uil; + unsigned int uiRight = block.m_uir; + uiLeft ^= m_auiP[0]; + uiRight ^= F(uiLeft)^m_auiP[1]; uiLeft ^= F(uiRight)^m_auiP[2]; + uiRight ^= F(uiLeft)^m_auiP[3]; uiLeft ^= F(uiRight)^m_auiP[4]; + uiRight ^= F(uiLeft)^m_auiP[5]; uiLeft ^= F(uiRight)^m_auiP[6]; + uiRight ^= F(uiLeft)^m_auiP[7]; uiLeft ^= F(uiRight)^m_auiP[8]; + uiRight ^= F(uiLeft)^m_auiP[9]; uiLeft ^= F(uiRight)^m_auiP[10]; + uiRight ^= F(uiLeft)^m_auiP[11]; uiLeft ^= F(uiRight)^m_auiP[12]; + uiRight ^= F(uiLeft)^m_auiP[13]; uiLeft ^= F(uiRight)^m_auiP[14]; + uiRight ^= F(uiLeft)^m_auiP[15]; uiLeft ^= F(uiRight)^m_auiP[16]; + uiRight ^= m_auiP[17]; + block.m_uil = uiRight; + block.m_uir = uiLeft; +} + +//Sixteen Round Decipher of SBlock +void CBlowFish::Decrypt(SBlock& block) +{ + unsigned int uiLeft = block.m_uil; + unsigned int uiRight = block.m_uir; + uiLeft ^= m_auiP[17]; + uiRight ^= F(uiLeft)^m_auiP[16]; uiLeft ^= F(uiRight)^m_auiP[15]; + uiRight ^= F(uiLeft)^m_auiP[14]; uiLeft ^= F(uiRight)^m_auiP[13]; + uiRight ^= F(uiLeft)^m_auiP[12]; uiLeft ^= F(uiRight)^m_auiP[11]; + uiRight ^= F(uiLeft)^m_auiP[10]; uiLeft ^= F(uiRight)^m_auiP[9]; + uiRight ^= F(uiLeft)^m_auiP[8]; uiLeft ^= F(uiRight)^m_auiP[7]; + uiRight ^= F(uiLeft)^m_auiP[6]; uiLeft ^= F(uiRight)^m_auiP[5]; + uiRight ^= F(uiLeft)^m_auiP[4]; uiLeft ^= F(uiRight)^m_auiP[3]; + uiRight ^= F(uiLeft)^m_auiP[2]; uiLeft ^= F(uiRight)^m_auiP[1]; + uiRight ^= m_auiP[0]; + block.m_uil = uiRight; + block.m_uir = uiLeft; +} + +//Semi-Portable Byte Shuffling +inline void BytesToBlock(unsigned char const* p, SBlock& b) +{ + unsigned int y; + //Left + b.m_uil = 0; + y = *p++; + y <<= 24; + b.m_uil |= y; + y = *p++; + y <<= 16; + b.m_uil |= y; + y = *p++; + y <<= 8; + b.m_uil |= y; + y = *p++; + b.m_uil |= y; + //Right + b.m_uir = 0; + y = *p++; + y <<= 24; + b.m_uir |= y; + y = *p++; + y <<= 16; + b.m_uir |= y; + y = *p++; + y <<= 8; + b.m_uir |= y; + y = *p++; + b.m_uir |= y; +} + +inline void BlockToBytes(SBlock const& b, unsigned char* p) +{ + unsigned int y; + //Right + y = b.m_uir; + *--p = Byte(y); + y = b.m_uir >> 8; + *--p = Byte(y); + y = b.m_uir >> 16; + *--p = Byte(y); + y = b.m_uir >> 24; + *--p = Byte(y); + //Left + y = b.m_uil; + *--p = Byte(y); + y = b.m_uil >> 8; + *--p = Byte(y); + y = b.m_uil >> 16; + *--p = Byte(y); + y = b.m_uil >> 24; + *--p = Byte(y); +} + +//Encrypt Buffer in Place +//Returns false if n is multiple of 8 +void CBlowFish::Encrypt(unsigned char* buf, size_t n, int iMode) +{ + //Check the buffer's length - should be > 0 and multiple of 8 + if((n==0)||(n%8!=0)) + //throw exception("Incorrect buffer length"); + return; + + SBlock work; + if(iMode == CBC) //CBC mode, using the Chain + { + SBlock chain(m_oChain); + for(; n >= 8; n -= 8) + { + BytesToBlock(buf, work); + work ^= chain; + Encrypt(work); + chain = work; + BlockToBytes(work, buf+=8); + } + } + else if(iMode == CFB) //CFB mode, using the Chain + { + SBlock chain(m_oChain); + for(; n >= 8; n -= 8) + { + Encrypt(chain); + BytesToBlock(buf, work); + work ^= chain; + chain = work; + BlockToBytes(work, buf+=8); + } + } + else //ECB mode, not using the Chain + { + for(; n >= 8; n -= 8) + { + BytesToBlock(buf, work); + Encrypt(work); + BlockToBytes(work, buf+=8); + } + } +} + +//Decrypt Buffer in Place +//Returns false if n is multiple of 8 +void CBlowFish::Decrypt(unsigned char* buf, size_t n, int iMode) +{ + //Check the buffer's length - should be > 0 and multiple of 8 + if((n==0)||(n%8!=0)) + //throw exception("Incorrect buffer length"); + return; + + SBlock work; + if(iMode == CBC) //CBC mode, using the Chain + { + SBlock crypt, chain(m_oChain); + for(; n >= 8; n -= 8) + { + BytesToBlock(buf, work); + crypt = work; + Decrypt(work); + work ^= chain; + chain = crypt; + BlockToBytes(work, buf+=8); + } + } + else if(iMode == CFB) //CFB mode, using the Chain, not using Decrypt() + { + SBlock crypt, chain(m_oChain); + for(; n >= 8; n -= 8) + { + BytesToBlock(buf, work); + Encrypt(chain); + crypt = work; + work ^= chain; + chain = crypt; + BlockToBytes(work, buf+=8); + } + } + else //ECB mode, not using the Chain + { + for(; n >= 8; n -= 8) + { + BytesToBlock(buf, work); + Decrypt(work); + BlockToBytes(work, buf+=8); + } + } +} + +//Encrypt from Input Buffer to Output Buffer +//Returns false if n is multiple of 8 +void CBlowFish::Encrypt(const unsigned char* in, unsigned char* out, size_t n, int iMode) +{ + //Check the buffer's length - should be > 0 and multiple of 8 + if((n==0)||(n%8!=0)) + //throw exception("Incorrect buffer length"); + return; + + SBlock work; + if(iMode == CBC) //CBC mode, using the Chain + { + SBlock chain(m_oChain); + for(; n >= 8; n -= 8, in += 8) + { + BytesToBlock(in, work); + work ^= chain; + Encrypt(work); + chain = work; + BlockToBytes(work, out+=8); + } + } + else if(iMode == CFB) //CFB mode, using the Chain + { + SBlock chain(m_oChain); + for(; n >= 8; n -= 8, in += 8) + { + Encrypt(chain); + BytesToBlock(in, work); + work ^= chain; + chain = work; + BlockToBytes(work, out+=8); + } + } + else //ECB mode, not using the Chain + { + for(; n >= 8; n -= 8, in += 8) + { + BytesToBlock(in, work); + Encrypt(work); + BlockToBytes(work, out+=8); + } + } +} + +//Decrypt from Input Buffer to Output Buffer +//Returns false if n is multiple of 8 +void CBlowFish::Decrypt(const unsigned char* in, unsigned char* out, size_t n, int iMode) +{ + //Check the buffer's length - should be > 0 and multiple of 8 + if((n==0)||(n%8!=0)) + //throw exception("Incorrect buffer length"); + return; + + SBlock work; + if(iMode == CBC) //CBC mode, using the Chain + { + SBlock crypt, chain(m_oChain); + for(; n >= 8; n -= 8, in += 8) + { + BytesToBlock(in, work); + crypt = work; + Decrypt(work); + work ^= chain; + chain = crypt; + BlockToBytes(work, out+=8); + } + } + else if(iMode == CFB) //CFB mode, using the Chain, not using Decrypt() + { + SBlock crypt, chain(m_oChain); + for(; n >= 8; n -= 8, in += 8) + { + BytesToBlock(in, work); + Encrypt(chain); + crypt = work; + work ^= chain; + chain = crypt; + BlockToBytes(work, out+=8); + } + } + else //ECB mode, not using the Chain + { + for(; n >= 8; n -= 8, in += 8) + { + BytesToBlock(in, work); + Decrypt(work); + BlockToBytes(work, out+=8); + } + } +} + diff --git a/konversation/src/blowfish/BlowfishCbc.h b/konversation/src/blowfish/BlowfishCbc.h new file mode 100644 index 0000000..2abb335 --- /dev/null +++ b/konversation/src/blowfish/BlowfishCbc.h @@ -0,0 +1,228 @@ +/* + Public Domain. Without any warranty. + + Copyright (C) George Anescu + Copyright (C) mouser +*/ + +//--------------------------------------------------------------------------- +//The implementation of blowfish for CBC mode is from http://www.thecodeproject.com/cpp/blowfish.asp by George Anescu +// I removed exception handling, so it is callers responsibility to insure +// that strings are length multiples of 8 bytes +// -mouser 1/08/05 +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Mouser 1/14/05 +// I'm not sure this implementation of cbc is exactly the same as other cbc +// algorithms you may find, though the difference is insignificant and just +// requires you to call your other algorithm slightly differently. +// This blowfish cbc class basically pretends that the IV is 00000000 but +// but that the first 8byte block of the plaintext to encrypt is treated +// like the IV (ie its a random nonce). +// In other words, it does not accept a separate IV, but expects the first +// 8bytes to be the IV (this is a slight difference from textbook cbc since +// the encrypted IV is now part of the ciphertext). +// This actually works out well for us since we want to send the IV to +// our recipient as part of our message. +// ANYWAY, bottom line is, if you have a blowfish implementation that takes +// an explicit IV parameter as its input, just pass it 0 as the IV, and +// when encrypting, prefix your plaintext with an 8 byte random nonce, and +// you will have a compatible algorithm. Remember its not that this +// algorithm uses a fixed IV of 0, but rather that the IV is the first +// block of the test to encrypt. +//--------------------------------------------------------------------------- + + + +//////////////////////////////////////////////////////////////////////////// +/// +// Blowfish.h Header File +// +// BLOWFISH ENCRYPTION ALGORITHM +// +// Encryption and Decryption of Byte Strings using the Blowfish Encryption Algorithm. +// Blowfish is a block cipher that encrypts data in 8-byte blocks. The algorithm consists +// of two parts: a key-expansion part and a data-ancryption part. Key expansion converts a +// variable key of at least 1 and at most 56 bytes into several subkey arrays totaling +// 4168 bytes. Blowfish has 16 rounds. Each round consists of a key-dependent permutation, +// and a key and data-dependent substitution. All operations are XORs and additions on 32-bit words. +// The only additional operations are four indexed array data lookups per round. +// Blowfish uses a large number of subkeys. These keys must be precomputed before any data +// encryption or decryption. The P-array consists of 18 32-bit subkeys: P0, P1,...,P17. +// There are also four 32-bit S-boxes with 256 entries each: S0,0, S0,1,...,S0,255; +// S1,0, S1,1,...,S1,255; S2,0, S2,1,...,S2,255; S3,0, S3,1,...,S3,255; +// +// The Electronic Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback modes +// are used: +// +// In ECB mode if the same block is encrypted twice with the same key, the resulting +// ciphertext blocks are the same. +// +// In CBC Mode a ciphertext block is obtained by first xoring the +// plaintext block with the previous ciphertext block, and encrypting the resulting value. +// +// In CFB mode a ciphertext block is obtained by encrypting the previous ciphertext block +// and xoring the resulting value with the plaintext +// +// The previous ciphertext block is usually stored in an Initialization Vector (IV). +// An Initialization Vector of zero is commonly used for the first block, though other +// arrangements are also in use. + +/* +http://www.counterpane.com/vectors.txt +Test vectors by Eric Young. These tests all assume Blowfish with 16 +rounds. + +All data is shown as a hex string with 012345 loading as +data[0]=0x01; +data[1]=0x23; +data[2]=0x45; +ecb test data (taken from the DES validation tests) + +key bytes clear bytes cipher bytes +0000000000000000 0000000000000000 4EF997456198DD78 +FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 51866FD5B85ECB8A +3000000000000000 1000000000000001 7D856F9A613063F2 ??? +1111111111111111 1111111111111111 2466DD878B963C9D +0123456789ABCDEF 1111111111111111 61F9C3802281B096 +1111111111111111 0123456789ABCDEF 7D0CC630AFDA1EC7 +0000000000000000 0000000000000000 4EF997456198DD78 +FEDCBA9876543210 0123456789ABCDEF 0ACEAB0FC6A0A28D +7CA110454A1A6E57 01A1D6D039776742 59C68245EB05282B +0131D9619DC1376E 5CD54CA83DEF57DA B1B8CC0B250F09A0 +07A1133E4A0B2686 0248D43806F67172 1730E5778BEA1DA4 +3849674C2602319E 51454B582DDF440A A25E7856CF2651EB +04B915BA43FEB5B6 42FD443059577FA2 353882B109CE8F1A +0113B970FD34F2CE 059B5E0851CF143A 48F4D0884C379918 +0170F175468FB5E6 0756D8E0774761D2 432193B78951FC98 +43297FAD38E373FE 762514B829BF486A 13F04154D69D1AE5 +07A7137045DA2A16 3BDD119049372802 2EEDDA93FFD39C79 +04689104C2FD3B2F 26955F6835AF609A D887E0393C2DA6E3 +37D06BB516CB7546 164D5E404F275232 5F99D04F5B163969 +1F08260D1AC2465E 6B056E18759F5CCA 4A057A3B24D3977B +584023641ABA6176 004BD6EF09176062 452031C1E4FADA8E +025816164629B007 480D39006EE762F2 7555AE39F59B87BD +49793EBC79B3258F 437540C8698F3CFA 53C55F9CB49FC019 +4FB05E1515AB73A7 072D43A077075292 7A8E7BFA937E89A3 +49E95D6D4CA229BF 02FE55778117F12A CF9C5D7A4986ADB5 +018310DC409B26D6 1D9D5C5018F728C2 D1ABB290658BC778 +1C587F1C13924FEF 305532286D6F295A 55CB3774D13EF201 +0101010101010101 0123456789ABCDEF FA34EC4847B268B2 +1F1F1F1F0E0E0E0E 0123456789ABCDEF A790795108EA3CAE +E0FEE0FEF1FEF1FE 0123456789ABCDEF C39E072D9FAC631D +0000000000000000 FFFFFFFFFFFFFFFF 014933E0CDAFF6E4 +FFFFFFFFFFFFFFFF 0000000000000000 F21E9A77B71C49BC +0123456789ABCDEF 0000000000000000 245946885754369A +FEDCBA9876543210 FFFFFFFFFFFFFFFF 6B5C5A9C5D9E0A5A + +set_key test data +data[8]= FEDCBA9876543210 +c=F9AD597C49DB005E k[ 1]=F0 +c=E91D21C1D961A6D6 k[ 2]=F0E1 +c=E9C2B70A1BC65CF3 k[ 3]=F0E1D2 +c=BE1E639408640F05 k[ 4]=F0E1D2C3 +c=B39E44481BDB1E6E k[ 5]=F0E1D2C3B4 +c=9457AA83B1928C0D k[ 6]=F0E1D2C3B4A5 +c=8BB77032F960629D k[ 7]=F0E1D2C3B4A596 +c=E87A244E2CC85E82 k[ 8]=F0E1D2C3B4A59687 +c=15750E7A4F4EC577 k[ 9]=F0E1D2C3B4A5968778 +c=122BA70B3AB64AE0 k[10]=F0E1D2C3B4A596877869 +c=3A833C9AFFC537F6 k[11]=F0E1D2C3B4A5968778695A +c=9409DA87A90F6BF2 k[12]=F0E1D2C3B4A5968778695A4B +c=884F80625060B8B4 k[13]=F0E1D2C3B4A5968778695A4B3C +c=1F85031C19E11968 k[14]=F0E1D2C3B4A5968778695A4B3C2D +c=79D9373A714CA34F k[15]=F0E1D2C3B4A5968778695A4B3C2D1E ??? +c=93142887EE3BE15C k[16]=F0E1D2C3B4A5968778695A4B3C2D1E0F +c=03429E838CE2D14B k[17]=F0E1D2C3B4A5968778695A4B3C2D1E0F00 +c=A4299E27469FF67B k[18]=F0E1D2C3B4A5968778695A4B3C2D1E0F0011 +c=AFD5AED1C1BC96A8 k[19]=F0E1D2C3B4A5968778695A4B3C2D1E0F001122 +c=10851C0E3858DA9F k[20]=F0E1D2C3B4A5968778695A4B3C2D1E0F00112233 +c=E6F51ED79B9DB21F k[21]=F0E1D2C3B4A5968778695A4B3C2D1E0F0011223344 +c=64A6E14AFD36B46F k[22]=F0E1D2C3B4A5968778695A4B3C2D1E0F001122334455 +c=80C7D7D45A5479AD k[23]=F0E1D2C3B4A5968778695A4B3C2D1E0F00112233445566 +c=05044B62FA52D080 k[24]=F0E1D2C3B4A5968778695A4B3C2D1E0F0011223344556677 + +chaining mode test data +key[16] = 0123456789ABCDEFF0E1D2C3B4A59687 +iv[8] = FEDCBA9876543210 +data[29] = "7654321 Now is the time for " (includes trailing '\0') +data[29] = 37363534333231204E6F77206973207468652074696D6520666F722000 +cbc cipher text +cipher[32]= 6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC +cfb64 cipher text cipher[29]= +E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3 +ofb64 cipher text cipher[29]= +E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA + +*/ + +//--------------------------------------------------------------------------- +// includes for size_t +#include +//--------------------------------------------------------------------------- + + +#ifndef BLOWFISH_H +#define BLOWFISH_H + +//Block Structure +struct SBlock +{ + //Constructors + SBlock(unsigned int l=0, unsigned int r=0) : m_uil(l), m_uir(r) {} + //Copy Constructor + SBlock(const SBlock& roBlock) : m_uil(roBlock.m_uil), m_uir(roBlock.m_uir) {} + SBlock& operator^=(SBlock& b) { m_uil ^= b.m_uil; m_uir ^= b.m_uir; return *this; } + unsigned int m_uil, m_uir; +}; + +class CBlowFish +{ +public: + enum { ECB=0, CBC=1, CFB=2 }; + + //Constructor - Initialize the P and S boxes for a given Key + CBlowFish(unsigned char* ucKey, size_t n, const SBlock& roChain = SBlock(0UL,0UL)); + + //Resetting the chaining block + void ResetChain() { m_oChain = m_oChain0; } + + // Encrypt/Decrypt Buffer in Place + void Encrypt(unsigned char* buf, size_t n, int iMode=ECB); + void Decrypt(unsigned char* buf, size_t n, int iMode=ECB); + + // Encrypt/Decrypt from Input Buffer to Output Buffer + void Encrypt(const unsigned char* in, unsigned char* out, size_t n, int iMode=ECB); + void Decrypt(const unsigned char* in, unsigned char* out, size_t n, int iMode=ECB); + +//Private Functions +private: + unsigned int F(unsigned int ui); + void Encrypt(SBlock&); + void Decrypt(SBlock&); + +private: + //The Initialization Vector, by default {0, 0} + SBlock m_oChain0; + SBlock m_oChain; + unsigned int m_auiP[18]; + unsigned int m_auiS[4][256]; + static const unsigned int scm_auiInitP[18]; + static const unsigned int scm_auiInitS[4][256]; +}; + +//Extract low order byte +inline unsigned char Byte(unsigned int ui) +{ + return (unsigned char)(ui & 0xff); +} + +//Function F +inline unsigned int CBlowFish::F(unsigned int ui) +{ + return ((m_auiS[0][Byte(ui>>24)] + m_auiS[1][Byte(ui>>16)]) ^ m_auiS[2][Byte(ui>>8)]) + m_auiS[3][Byte(ui)]; +} + +#endif // __BLOWFISH_H__ + diff --git a/konversation/src/blowfish/Makefile.am b/konversation/src/blowfish/Makefile.am new file mode 100644 index 0000000..07abe04 --- /dev/null +++ b/konversation/src/blowfish/Makefile.am @@ -0,0 +1,7 @@ +AM_CPPFLAGS = $(all_includes) -I$(srcdir)/../ + +noinst_LTLIBRARIES = libblowfish.la +noinst_HEADERS = b64stuff.h BlowfishCbc.h blowfish.h mc_blowfish.h newblowfish.h oldblowfish1.h oldblowfish2.h + +libblowfish_la_SOURCES = b64stuff.cpp BlowfishCbc.cpp blowfish.cpp mc_blowfish.cpp newblowfish.cpp oldblowfish.cpp +libblowfish_la_LDFLAGS = $(all_libraries) -no-undefined diff --git a/konversation/src/blowfish/README b/konversation/src/blowfish/README new file mode 100644 index 0000000..d949ba0 --- /dev/null +++ b/konversation/src/blowfish/README @@ -0,0 +1,3 @@ +b64stuff.{h,cpp} is public domain +blowfish.{cpp,h} is written by İsmail Dönmez and licensed under GPLv2 +Rest of the code is from Mircryption v1.11.27 ( http://mircryption.sourceforge.net/ ) project and licensed under GPLv2 diff --git a/konversation/src/blowfish/b64stuff.cpp b/konversation/src/blowfish/b64stuff.cpp new file mode 100644 index 0000000..72f0776 --- /dev/null +++ b/konversation/src/blowfish/b64stuff.cpp @@ -0,0 +1,218 @@ +/* + Copyright (C) John Viega + Copyright (C) Matt Messier + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +//--------------------------------------------------------------------------- +#include "b64stuff.h" +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +//static char b64table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +// "abcdefghijklmnopqrstuvwxyz" +// "0123456789+/"; +static char b64table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* Accepts a binary buffer with an associated size. + * Returns a base64-encoded, NULL-terminated string. + */ +unsigned char *spc_base64_encode(unsigned char *input, size_t len, int wrap) { + unsigned char *output, *p; + size_t i = 0, mod = len % 3, toalloc; + + // ATTN: WTF is this allocation function - does it fail sometimes?) + //toalloc = (len / 3) * 4 + (3 - mod) % 3 + 1; + toalloc = (len / 3) * 4 + (3 - mod) % 3 + 1 + 8; + + if (wrap) { + toalloc += len / 57; + if (len % 57) toalloc++; + } + + if (toalloc < len) return 0; + + //p = output = (unsigned char *)malloc(toalloc); + p = output = new unsigned char [toalloc]; + + if (!p) return 0; + + while (i < len - mod) { + *p++ = b64table[input[i++] >> 2]; + *p++ = b64table[((input[i - 1] << 4) | (input[i] >> 4)) & 0x3f]; + *p++ = b64table[((input[i] << 2) | (input[i + 1] >> 6)) & 0x3f]; + *p++ = b64table[input[i + 1] & 0x3f]; + i += 2; + if (wrap && !(i % 57)) *p++ = '\n'; + } + if (!mod) { + if (wrap && i % 57) *p++ = '\n'; + *p = 0; + return output; + } else { + *p++ = b64table[input[i++] >> 2]; + *p++ = b64table[((input[i - 1] << 4) | (input[i] >> 4)) & 0x3f]; + if (mod == 1) { + *p++ = '='; + *p++ = '='; + if (wrap) *p++ = '\n'; + *p = 0; + return output; + } else { + *p++ = b64table[(input[i] << 2) & 0x3f]; + *p++ = '='; + if (wrap) *p++ = '\n'; + *p = 0; + return output; + } + } +} +//--------------------------------------------------------------------------- + + + + +//--------------------------------------------------------------------------- +static char b64revtb[256] = { + -3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*0-15*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16-31*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /*32-47*/ + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, /*48-63*/ + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /*64-79*/ + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /*80-95*/ + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /*96-111*/ + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /*112-127*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128-143*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*144-159*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*160-175*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*176-191*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*192-207*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*208-223*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*224-239*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /*240-255*/ +}; + +static unsigned int raw_base64_decode(unsigned char *in, unsigned char *out, + int strict, int *err) { + unsigned int result = 0; + int x; + unsigned char buf[3], *p = in, pad = 0; + + *err = 0; + while (!pad) { + switch ((x = b64revtb[*p++])) { + case -3: /* NULL TERMINATOR */ + if (((p - 1) - in) % 4) *err = 1; + return result; + case -2: /* PADDING CHARACTER. INVALID HERE */ + if (((p - 1) - in) % 4 < 2) { + *err = 1; + return result; + } else if (((p - 1) - in) % 4 == 2) { + /* Make sure there's appropriate padding */ + if (*p != '=') { + *err = 1; + return result; + } + buf[2] = 0; + pad = 2; + result++; + break; + } else { + pad = 1; + result += 2; + break; + } + return result; + case -1: + if (strict) { + *err = 2; + return result; + } + break; + default: + switch (((p - 1) - in) % 4) { + case 0: + buf[0] = x << 2; + break; + case 1: + buf[0] |= (x >> 4); + buf[1] = x << 4; + break; + case 2: + buf[1] |= (x >> 2); + buf[2] = x << 6; + break; + case 3: + buf[2] |= x; + result += 3; + for (x = 0; x < 3 - pad; x++) *out++ = buf[x]; + break; + } + break; + } + } + for (x = 0; x < 3 - pad; x++) *out++ = buf[x]; + return result; +} + +/* If err is non-zero on exit, then there was an incorrect padding error. We + * allocate enough space for all circumstances, but when there is padding, or + * there are characters outside the character set in the string (which we are + * supposed to ignore), then we end up allocating too much space. You can + * realloc() to the correct length if you wish. + */ + +unsigned char *spc_base64_decode(unsigned char *buf, size_t *len, int strict, int *err) { + unsigned char *outbuf; + +// outbuf = (unsigned char *)malloc(3 * (strlen(buf) / 4 + 1)); + // ATTN: WTF is this allocation function - does it fail sometimes?) + //outbuf = (unsigned char *)malloc(3 * (strlen((char*)buf) / 4 + 1)); + //outbuf = (unsigned char *)malloc(3 * (strlen((char*)buf)+1)); + //outbuf = new unsigned char [3 * (strlen((char*)buf)+1)]; + outbuf = new unsigned char [3 * (strlen((char*)buf) / 4 + 1 + 8)]; + + if (!outbuf) { + *err = -3; + *len = 0; + return 0; + } + *len = raw_base64_decode(buf, outbuf, strict, err); + if (*err) { + //free(outbuf); + delete [] outbuf; + *len = 0; + outbuf = 0; + } + return outbuf; +} +//--------------------------------------------------------------------------- + diff --git a/konversation/src/blowfish/b64stuff.h b/konversation/src/blowfish/b64stuff.h new file mode 100644 index 0000000..292300b --- /dev/null +++ b/konversation/src/blowfish/b64stuff.h @@ -0,0 +1,53 @@ +/* + Copyright (C) John Viega + Copyright (C) Matt Messier + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +//--------------------------------------------------------------------------- +// To prevent multiple includes +#ifndef _b64stuffh +#define _b64stuffh +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +#include +#include +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +unsigned char *spc_base64_encode(unsigned char *input, size_t len, int wrap); +unsigned char *spc_base64_decode(unsigned char *buf, size_t *len, int strict, int *err); +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +#endif +//--------------------------------------------------------------------------- diff --git a/konversation/src/blowfish/blowfish.cpp b/konversation/src/blowfish/blowfish.cpp new file mode 100644 index 0000000..7951202 --- /dev/null +++ b/konversation/src/blowfish/blowfish.cpp @@ -0,0 +1,129 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 İsmail Dönmez +*/ + +#include "blowfish.h" +#include "mc_blowfish.h" +#include "server.h" +#include "channel.h" + +#include +#include + + +namespace Konversation +{ + // Find n'th occurrence of separator in input and return the index + int findOccurrence(const QCString& input, const QCString& separator, int nth) + { + int j=1; + uint i; + + for(i=0; i < input.length(); ++i) + { + if((input.mid(i,1) == separator)) + { + if (j == nth) + return i; + else + ++j; + } + } + return i; + } + + void decrypt(const QString& recipient, QCString& cipher, Server* server) + { + QCString key = server->getKeyForRecipient(recipient); + + if(!key.isEmpty()) + { + int index = findOccurrence(cipher, ":", 2); + QCString backup = cipher.mid(0,index+1); + QCString tmp = cipher.mid(index+1); + char* tmp2; + + if(server->identifyMsgEnabled()) // Workaround braindead Freenode prefixing messages with + + tmp = tmp.mid(1); + + if( !(tmp.mid(0,4) == "+OK ") && !(tmp.mid(0,5) == "mcps ") ) + return; + else + cipher = tmp; + + if(cipher.mid(0,5) == "mcps ") + cipher = cipher.mid(5); + else + cipher = cipher.mid(4); + + QCString ckey( key.length()+2 ); + QCString result( cipher.length()+1 ); + qstrncpy(result.data(), cipher.data(), cipher.length()); + qstrncpy(ckey.data(), key.data(), key.length()+1); + tmp2 = decrypt_string(ckey.data(),result.data()); + const char *pfx="(e) "; + // If it's a CTCP we don't want to have the (e) interfering with the processing + if (tmp2[0] == 1) + pfx = "\x0"; + cipher = backup+pfx+tmp2+' '+'\n'; // FIXME(??) why is there an added space here? + free(tmp2); + } + } + + void decryptTopic(const QString& recipient, QCString& cipher, Server* server) + { + QCString key = server->getKeyForRecipient(recipient); + + if(!key.isEmpty()) + { + int index = findOccurrence(cipher, ":", 2); + QCString backup = cipher.mid(0,index+1); + QCString tmp = cipher.mid(index+1); + char* tmp2; + + if(tmp.mid(0,4) == "+OK ") // FiSH style topic + cipher = tmp.mid(4); + else if(tmp.left(5) == "«m«") + cipher = tmp.mid(5,tmp.length()-10); + else + return; + + QCString result( cipher.length()+1 ); + QCString ckey( key.length()+2 ); + qstrncpy(ckey.data(), key.data(), key.length()+1); + qstrncpy(result.data(), cipher.data(), cipher.length()); + tmp2 = decrypt_string(ckey.data(),result.data()); + cipher = tmp2; + if(cipher.mid(0,2) == "@@") + cipher = cipher.mid(2); + + cipher = backup+"(e) "+cipher; + free(tmp2); + } + } + + bool encrypt(const QString& key, QCString& cipher) + { + if(key.isEmpty()) + return false; + + if (cipher.left(3) == "+p ") + cipher = cipher.mid(3); + else + { + QCString ckey(key.local8Bit()); + + char *tmp = encrypt_string(ckey.data(), cipher.data()); + cipher = QCString("+OK ") + tmp; + free(tmp); + } + return true; + } +} diff --git a/konversation/src/blowfish/blowfish.h b/konversation/src/blowfish/blowfish.h new file mode 100644 index 0000000..0c37317 --- /dev/null +++ b/konversation/src/blowfish/blowfish.h @@ -0,0 +1,30 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 İsmail Dönmez +*/ + +#ifndef BLOWFISH_H +#define BLOWFISH_H + + +class Server; + +class QString; +class QCString; + + +namespace Konversation +{ + + int findOccurrence(const QCString& input, const QCString& separator, int nth); + void decrypt(const QString& recipient, QCString& cipher, Server* server); + void decryptTopic(const QString& recipient, QCString& cipher, Server* server); + bool encrypt(const QString& key, QCString& cipher); +} +#endif diff --git a/konversation/src/blowfish/mc_blowfish.cpp b/konversation/src/blowfish/mc_blowfish.cpp new file mode 100644 index 0000000..0fb8da9 --- /dev/null +++ b/konversation/src/blowfish/mc_blowfish.cpp @@ -0,0 +1,63 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 Ismail Donmez +*/ + +//--------------------------------------------------------------------------- +// mc_blowfish.cpp +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// include header +#include "mc_blowfish.h" +#include "newblowfish.h" +#include "oldblowfish1.h" + +#include +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// Proxies for deciding which algorithm to use based on a key prefix + +// encrypt and decrypt +char *encrypt_string(char *key, char *str) +{ + // Note: Returned string must be freed when done with it! + if (key!=0 && (strncmp(key,"cbc:",4)==0 || strncmp(key,"CBC:",4)==0)) + { + // new method + return encrypt_string_new(key+4,str); + } + + // invoke old ecb method + return encrypt_string_oldecb(key,str); +} + +char *decrypt_string(char *key, char *str) +{ + // Note: Returned string must be freed when done with it! + if (key!=NULL && (strncmp(key,"cbc:",4)==0 || strncmp(key,"CBC:",4)==0)) + { + // new method + if (str[0]=='*') + return decrypt_string_new(key+4,str+1); + // it wasnt in cbc as expected, so use old method and warn user + char *cp=decrypt_string_oldecb(key,str); + char *cp2 = new char[strlen(cp)+15]; + strcpy(cp2,"ERROR_NONCBC:"); + strcat(cp2,cp); + delete cp; + return cp2; + } + // invoke old ecb method + return decrypt_string_oldecb(key,str); +} +//--------------------------------------------------------------------------- diff --git a/konversation/src/blowfish/mc_blowfish.h b/konversation/src/blowfish/mc_blowfish.h new file mode 100644 index 0000000..b1a3537 --- /dev/null +++ b/konversation/src/blowfish/mc_blowfish.h @@ -0,0 +1,34 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 Ismail Donmez +*/ + +// mc_blowfish.h +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// To prevent multiple includes +#ifndef _mcblowfishh +#define _mcblowfishh +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// forward declarations +char *encrypt_string(char *key, char *str); +char *decrypt_string(char *key, char *str); +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// header guard +#endif +//--------------------------------------------------------------------------- diff --git a/konversation/src/blowfish/newblowfish.cpp b/konversation/src/blowfish/newblowfish.cpp new file mode 100644 index 0000000..501c9d1 --- /dev/null +++ b/konversation/src/blowfish/newblowfish.cpp @@ -0,0 +1,208 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 Ismail Donmez +*/ + +// mc_blowfishnew.cpp +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +#include "newblowfish.h" +#include "b64stuff.h" +#include "BlowfishCbc.h" +#include +#include +#include +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +void ChooseIv(char *iv) +{ + // file the 8 byte IV with a nonce + // ATTN: this is not the best nonce IV generator, we'd like to improve it later + + static unsigned int staticcounter=0; + static int didinit=0; + int i; + time_t t1; + int part1,part2; + char *part1p,*part2p; + + // get current time + time(&t1); + + // on first use, initialize random number generator to time + if (didinit==0) + { + srand((long) t1); + didinit=1; + } + + // increment counter + ++staticcounter; + if (staticcounter>=65534L) + staticcounter=0; + + // ok now the IV will be 4 bytes random and 4 bytes time_t + int intsize=sizeof(int); + + // now part1 and part2 of the 8 byte iv + // part1 is a timestamp, number of seconds past since 1970 + part1=(int)t1; + part1p=(char*)(&part1); + // part2 is a random number, from prng initted with time, plus a counter + part2=(int)(rand()+staticcounter); + part2p=(char*)(&part2); + + // now fill IV + for (i=0;i<4;++i) + iv[i]=part1p[i%intsize]; + for (i=0;i<4;++i) + iv[4+i]=part2p[i%intsize]; +} +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// NEW CBCB METHODS +char *encrypt_string_new(char *key, char *str) +{ + char *p; + char *s, *dest,*dest2; + char iv[8]; + int i; + int len; + + // Pad fake string with 8 bytes to make sure there's enough PLUS add 8 bytes for IV + s = new char[strlen(str) + 9+8]; + if ((!key) || (!key[0])) + return s; + // allocate max space we will need for encrypted, base64d + dest = new char[(strlen(str) + 9+8) * 2]; + + // choose a (random or timestamped) IV block, 8 bytes wide and stick it into first 8 bytes of s + ChooseIv(iv); + + // load the iv into start of s + for (i=0;i<8;++i) + s[i]=iv[i]; + // add user string after + strcpy(&s[8], str); + len=8+strlen(str); + + // pad at end of source with 0s + p = s+len; + for (i = 0; i < 8; i++) + *p++ = 0; + + // modify len to be mod%8 + if (len%8!=0) + len+=8-(len%8); + + // encrypt into dest (note len does not change) + CBlowFish oBlowFish((unsigned char*)key, strlen(key)); + oBlowFish.ResetChain(); + oBlowFish.Encrypt((unsigned char*)s,(unsigned char*)dest, len, CBlowFish::CBC); + + // now base 64 it, allocating new dest2 in the process + dest2=(char*)(spc_base64_encode((unsigned char*)dest,len,0)); + if (dest2==0) + { + delete s; + return dest; + } + + // now prefix a * to it while copying to dest and delete s + strcpy(dest,"*"); + strcat(dest,dest2); + delete dest2; + delete s; + + // return the dest (user will free) + return dest; +} + + +// Returned string must be freed when done with it! +char *decrypt_string_new(char *key, char *str) +{ + char *p, *s, *dest; + char *dest2,*dest3; + int i; + int err; + size_t len; + char iv[9]; + + // Pad encoded string with 0 bits in case it's bogus + s = new char[strlen(str) + 12]; + strcpy(s, str); + + if ((!key) || (!key[0])) + return s; + dest = new char[strlen(str) + 12 + 8]; + + // pad with 0s + p = s+strlen(str); + for (i = 0; i < 12; i++) + *p++ = 0; + + // now unbase64 it, allocating new dest2 in the process + len=strlen(str); + dest2=(char*)(spc_base64_decode((unsigned char*)s,&len,0,&err)); + if (dest2==0) + { + delete dest; + return s; + } + if (err) + { + // FOR TESTING: + // printf("ERROR IN BASE 64 decode!\n"); + delete dest; + return s; + } + + // copy unbase64'd to new temp dest3 then delete dest2 + // pad it to be mod%8 (this should not be necesary on decrypt but could be on a truncated transmission); + dest3 = new char[strlen(str) + 12 + 8]; + memcpy(dest3,dest2,len); + if (len%8!=0) + { + int newbytes=8-(len%8); + while (newbytes>0) + { + ++len; + --newbytes; + dest3[len]='\0'; + } + } + delete dest2; + + // decrypt from dest3 (length len) to dest + CBlowFish oBlowFish((unsigned char*)key, strlen(key)); + oBlowFish.ResetChain(); + oBlowFish.Decrypt((unsigned char*)dest3,(unsigned char*)dest, len, CBlowFish::CBC); + // 0 terminate in case it is exactly mod 8 real characters + dest[len]='\0'; + + // now the first block (8bytes) is just the IV so we don't want to return that + strncpy(iv,dest,8); + iv[8]='\0'; + strcpy(dest,&dest[8]); + + // delete s and dest3 + delete s; + delete dest3; + + // return dest + return dest; +} +//--------------------------------------------------------------------------- diff --git a/konversation/src/blowfish/newblowfish.h b/konversation/src/blowfish/newblowfish.h new file mode 100644 index 0000000..16e50c2 --- /dev/null +++ b/konversation/src/blowfish/newblowfish.h @@ -0,0 +1,32 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 Ismail Donmez +*/ + +// mc_blowfishnew.h +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// To prevent multiple includes +#ifndef _newblowfishh +#define _newblowfishh +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// forward declarations +char *encrypt_string_new(char *key, char *str); +char *decrypt_string_new(char *key, char *str); +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// header guard +#endif +//--------------------------------------------------------------------------- diff --git a/konversation/src/blowfish/oldblowfish.cpp b/konversation/src/blowfish/oldblowfish.cpp new file mode 100644 index 0000000..1f274db --- /dev/null +++ b/konversation/src/blowfish/oldblowfish.cpp @@ -0,0 +1,425 @@ +/* + 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. +*/ + +/* + Blowfish algorythms: Bruce Schneier and Jim Conger + Bruce Schneier, 1996, Applied Cryptography, 2nd ed., John Wiley & Sons + Blowfish Eggdrop algorythms: Robey Pointer + + Copyright (C) 1994 Bruce Schneier + Copyright (C) 1996 Jim Conger + Copyright (C) Robey Pointer +*/ + +//--------------------------------------------------------------------------- +#include +#include "oldblowfish1.h" +#include "oldblowfish2.h" +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +#define S(x,i) (SBoxes[i][x.w.byte##i]) +#define bf_F(x) (((S(x,0) + S(x,1)) ^ S(x,2)) + S(x,3)) +#define ROUND(a,b,n) (a.dword ^= bf_F(b) ^ PArray[n]) +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +oldCBlowFish::oldCBlowFish () +{ + PArray = new DWORD [18] ; + SBoxes = new DWORD [4][256] ; +} + +oldCBlowFish::~oldCBlowFish () +{ + delete PArray ; + delete [] SBoxes ; +} + +// the low level (private) encryption function +void oldCBlowFish::Blowfish_encipher (DWORD *xl, DWORD *xr) +{ + union aword Xl, Xr ; + + Xl.dword = *xl ; + Xr.dword = *xr ; + + Xl.dword ^= PArray [0]; + ROUND (Xr, Xl, 1) ; ROUND (Xl, Xr, 2) ; + ROUND (Xr, Xl, 3) ; ROUND (Xl, Xr, 4) ; + ROUND (Xr, Xl, 5) ; ROUND (Xl, Xr, 6) ; + ROUND (Xr, Xl, 7) ; ROUND (Xl, Xr, 8) ; + ROUND (Xr, Xl, 9) ; ROUND (Xl, Xr, 10) ; + ROUND (Xr, Xl, 11) ; ROUND (Xl, Xr, 12) ; + ROUND (Xr, Xl, 13) ; ROUND (Xl, Xr, 14) ; + ROUND (Xr, Xl, 15) ; ROUND (Xl, Xr, 16) ; + Xr.dword ^= PArray [17] ; + + *xr = Xl.dword ; + *xl = Xr.dword ; +} + +// the low level (private) decryption function +void oldCBlowFish::Blowfish_decipher (DWORD *xl, DWORD *xr) +{ + union aword Xl ; + union aword Xr ; + + Xl.dword = *xl ; + Xr.dword = *xr ; + + Xl.dword ^= PArray [17] ; + ROUND (Xr, Xl, 16) ; ROUND (Xl, Xr, 15) ; + ROUND (Xr, Xl, 14) ; ROUND (Xl, Xr, 13) ; + ROUND (Xr, Xl, 12) ; ROUND (Xl, Xr, 11) ; + ROUND (Xr, Xl, 10) ; ROUND (Xl, Xr, 9) ; + ROUND (Xr, Xl, 8) ; ROUND (Xl, Xr, 7) ; + ROUND (Xr, Xl, 6) ; ROUND (Xl, Xr, 5) ; + ROUND (Xr, Xl, 4) ; ROUND (Xl, Xr, 3) ; + ROUND (Xr, Xl, 2) ; ROUND (Xl, Xr, 1) ; + Xr.dword ^= PArray[0]; + + *xl = Xr.dword; + *xr = Xl.dword; +} + + +// constructs the enctryption sieve +void oldCBlowFish::Initialize (BYTE key[], int keybytes) +{ + int i, j ; + DWORD data, datal, datar ; + union aword temp ; + + + // ATTN: new fix for keys > 56, should make it more compatible with FISH + // but fish uses 80 ??? + if (keybytes>MAXKEYBYTES_COMPATMODE) + keybytes=MAXKEYBYTES_COMPATMODE; + + // first fill arrays from data tables + for (i = 0 ; i < 18 ; i++) + PArray [i] = bf_P [i] ; + + for (i = 0 ; i < 4 ; i++) + { + for (j = 0 ; j < 256 ; j++) + SBoxes [i][j] = bf_S [i][j] ; + } + + + j = 0 ; + for (i = 0 ; i < NPASS + 2 ; ++i) + { + temp.dword = 0 ; + temp.w.byte0 = key[j]; + temp.w.byte1 = key[(j+1) % keybytes] ; + temp.w.byte2 = key[(j+2) % keybytes] ; + temp.w.byte3 = key[(j+3) % keybytes] ; + data = temp.dword ; + PArray [i] ^= data ; + j = (j + 4) % keybytes ; + } + + datal = 0 ; + datar = 0 ; + + for (i = 0 ; i < NPASS + 2 ; i += 2) + { + Blowfish_encipher (&datal, &datar) ; + PArray [i] = datal ; + PArray [i + 1] = datar ; + } + + for (i = 0 ; i < 4 ; ++i) + { + for (j = 0 ; j < 256 ; j += 2) + { + Blowfish_encipher (&datal, &datar) ; + SBoxes [i][j] = datal ; + SBoxes [i][j + 1] = datar ; + } + } +} + +// get output length, which must be even MOD 8 +DWORD oldCBlowFish::GetOutputLength (DWORD lInputLong) +{ + DWORD lVal ; + + lVal = lInputLong % 8 ; // find out if uneven number of bytes at the end + if (lVal != 0) + return lInputLong + 8 - lVal ; + else + return lInputLong ; +} + + +// Encode pIntput into pOutput. Input length in lSize. Returned value +// is length of output which will be even MOD 8 bytes. Input buffer and +// output buffer can be the same, but be sure buffer length is even MOD 8. +DWORD oldCBlowFish::Encode (BYTE * pInput, BYTE * pOutput, DWORD lSize) +{ + DWORD lCount, lOutSize, lGoodBytes ; + BYTE *pi, *po ; + int i, j ; + int SameDest = (pInput == pOutput ? 1 : 0) ; + + lOutSize = GetOutputLength (lSize) ; + for (lCount = 0 ; lCount < lOutSize ; lCount += 8) + { + if (SameDest) // if encoded data is being written into input buffer + { + if (lCount < lSize - 7) // if not dealing with uneven bytes at end + { + Blowfish_encipher ((DWORD *) pInput, + (DWORD *) (pInput + 4)) ; + } + else // pad end of data with null bytes to complete encryption + { + po = pInput + lSize ; // point at byte past the end of actual data + j = (int) (lOutSize - lSize) ; // number of bytes to set to null + for (i = 0 ; i < j ; i++) + *po++ = 0 ; + Blowfish_encipher ((DWORD *) pInput, + (DWORD *) (pInput + 4)) ; + } + pInput += 8 ; + } + else // output buffer not equal to input buffer, so must copy + { // input to output buffer prior to encrypting + if (lCount < lSize - 7) // if not dealing with uneven bytes at end + { + pi = pInput ; + po = pOutput ; + for (i = 0 ; i < 8 ; i++) // copy bytes to output + *po++ = *pi++ ; + Blowfish_encipher ((DWORD *) pOutput, // now encrypt them + (DWORD *) (pOutput + 4)) ; + } + else // pad end of data with null bytes to complete encryption + { + lGoodBytes = lSize - lCount ; // number of remaining data bytes + po = pOutput ; + for (i = 0 ; i < (int) lGoodBytes ; i++) + *po++ = *pInput++ ; + for (j = i ; j < 8 ; j++) + *po++ = 0 ; + Blowfish_encipher ((DWORD *) pOutput, + (DWORD *) (pOutput + 4)) ; + } + pInput += 8 ; + pOutput += 8 ; + } + } + return lOutSize ; + } + +// Decode pIntput into pOutput. Input length in lSize. Input buffer and +// output buffer can be the same, but be sure buffer length is even MOD 8. +void oldCBlowFish::Decode (BYTE * pInput, BYTE * pOutput, DWORD lSize) +{ + DWORD lCount ; + BYTE *pi, *po ; + int i ; + int SameDest = (pInput == pOutput ? 1 : 0) ; + + for (lCount = 0 ; lCount < lSize ; lCount += 8) + { + if (SameDest) // if encoded data is being written into input buffer + { + Blowfish_decipher ((DWORD *) pInput, + (DWORD *) (pInput + 4)) ; + pInput += 8 ; + } + else // output buffer not equal to input buffer + { // so copy input to output before decoding + pi = pInput ; + po = pOutput ; + for (i = 0 ; i < 8 ; i++) + *po++ = *pi++ ; + Blowfish_decipher ((DWORD *) pOutput, + (DWORD *) (pOutput + 4)) ; + pInput += 8 ; + pOutput += 8 ; + } + } +} +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// The following code is adapted from the eggdrop bot source: +// by Robey Pointer +// DR - as i understand this, what we have here is a function where you pass +// it a string(passphrase), and it convolutes it into an encrypted version +// (witout using a separate key). and you use this one-way encrypted +// string later, when you ask person for their passphrase. when they give +// you there passphrase, you call this again, and compare the two outputs. +// if the outputs are the same, then the inputs presumably were, and so +// passphrase is judged to match. In this way you can store one-way encrypted +// passphrases in plain files. +// + +#define SALT1 0xdeadd061 +#define SALT2 0x23f6b095 + +// Convert 64-bit encrypted passphrase to text for userfile +char base64[] = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +int base64dec(char c) +{ + // updated 1/20/03 for speed improvement + static char base64unmap[255]; + static bool didinit=false; + int i; + + if (!didinit) + { + // initialize base64unmap + for (i=0;i<255;++i) + base64unmap[i]=0; + for (i=0;i<64;++i) + base64unmap[(int)base64[i]]=i; + didinit=true; + } + + return base64unmap[(int)c]; +} + +void blowfish_encrypt_pass(char *text, char *str) +{ + DWORD left,right; + int n; + char *p; + oldCBlowFish caca; + caca.Initialize((unsigned char*)text,strlen(text)); + left = SALT1; + right = SALT2; + caca.Blowfish_encipher(&left, &right); + p = str; + *p++ = '+'; // + means encrypted pass + n = 32; + while (n > 0) { + *p++ = base64[right & 0x3f]; + right = (right >> 6); + n -= 6; + } + n = 32; + while (n > 0) { + *p++ = base64[left & 0x3f]; + left = (left >> 6); + n -= 6; + } + *p = 0; +} +//--------------------------------------------------------------------------- + + + + + + + + + + + + +//--------------------------------------------------------------------------- +// ORIGINAL COMPATIBLE (ECB) METHODS + +char *encrypt_string_oldecb(char *key, char *str) +{ + DWORD left, right; + unsigned char *p; + char *s, *dest, *d; + int i; + + // Pad fake string with 8 bytes to make sure there's enough + s = new char[strlen(str) + 9]; + strcpy(s, str); + if ((!key) || (!key[0])) + return s; + p = (unsigned char*)s; + dest = new char[(strlen(str) + 9) * 2]; + while (*p) + p++; + for (i = 0; i < 8; i++) + *p++ = 0; + + oldCBlowFish caca; + caca.Initialize((unsigned char*)key,strlen(key)); + p = (unsigned char*)s; + d = dest; + while (*p) { + left = ((*p++) << 24); + left += ((*p++) << 16); + left += ((*p++) << 8); + left += (*p++); + right = ((*p++) << 24); + right += ((*p++) << 16); + right += ((*p++) << 8); + right += (*p++); + caca.Blowfish_encipher(&left, &right); + for (i = 0; i < 6; i++) { + *d++ = base64[right & 0x3f]; + right = (right >> 6); + } + for (i = 0; i < 6; i++) { + *d++ = base64[left & 0x3f]; + left = (left >> 6); + } + } + *d = 0; + delete s; + return dest; +} + + +// Returned string must be freed when done with it! +char *decrypt_string_oldecb(char *key, char *str) +{ + DWORD left, right; + char *p, *s, *dest, *d; + int i; + + // Pad encoded string with 0 bits in case it's bogus + s = new char[strlen(str) + 12]; + strcpy(s, str); + if ((!key) || (!key[0])) + return s; + p = s; + dest = new char[strlen(str) + 12]; + while (*p) + p++; + for (i = 0; i < 12; i++) + *p++ = 0; + oldCBlowFish caca; + caca.Initialize((unsigned char*)key,strlen(key)); + p = s; + d = dest; + while (*p) { + right = 0L; + left = 0L; + for (i = 0; i < 6; i++) + right |= (base64dec(*p++)) << (i * 6); + for (i = 0; i < 6; i++) + left |= (base64dec(*p++)) << (i * 6); + caca.Blowfish_decipher(&left, &right); + for (i = 0; i < 4; i++) + *d++ = (char) ((left & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8)); + for (i = 0; i < 4; i++) + *d++ = (char) ((right & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8)); + } + *d = 0; + delete s; + return dest; +} +//--------------------------------------------------------------------------- diff --git a/konversation/src/blowfish/oldblowfish1.h b/konversation/src/blowfish/oldblowfish1.h new file mode 100644 index 0000000..729e27c --- /dev/null +++ b/konversation/src/blowfish/oldblowfish1.h @@ -0,0 +1,141 @@ +/* + blowfish1.h interface file for mc_blowfish.cpp + _THE BLOWFISH ENCRYPTION ALGORITHM_ + by Bruce Schneier, 1996, Applied Cryptography, 2nd ed., John Wiley & Sons + + Public Domain. + + Copyright (C) 1994 Bruce Schneier + Copyright (C) 1996 Jim Conger +*/ + +//--------------------------------------------------------------------------- +// To prevent multiple includes +#ifndef _oldblowfish1h +#define _oldblowfish1h +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Forward declarations +char *encrypt_string_oldecb(char *key, char *str); +char *decrypt_string_oldecb(char *key, char *str); +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +#define MAXKEYBYTES 56 // 448 bits max +#define NPASS 16 // SBox passes + +#define DWORD unsigned long +#define WORD unsigned short +#define BYTE unsigned char +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// for fish compatibility we use 80 instead of 56 +#define MAXKEYBYTES_COMPATMODE 80 +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +//#include "oldblowfish2.h" +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// choose a byte order for your hardware + +// NEW 7/10/03 trying to be smarter about endian +// first try to be smart about it, and user can define LITTLE_ENDIAN or BIG_ENDIAN from makefile +#ifdef LITTLE_ENDIAN + #define ORDER_DCBA // choosing Intel in this case +#else + #ifdef BIG_ENDIAN + #define ORDER_ABCD + #endif +#endif + +// default to intel if not overridden +#ifndef ORDER_DCBA + #ifndef ORDER_ABCD + #define ORDER_DCBA + #endif +#endif + +#ifdef ORDER_DCBA // DCBA - little endian - intel +// ATTN: THIS IS THE MAJOR CAUSE OF INCOMPATIBILITIES WITH OTHER BLOWFISH IMPLEMENTATIONS +// AS THIS LITTLE ENDIAN MODE IS USED ON THE PC BY THIS BLOWFISH, AND *NOT* IN OTHER BLOWFISHES +// THE FIX I THINK IS SIMPLE, THE bytex VARS ARE USED IN ONLY 1 PLACE IN MC_BLOWFISH.CPP AND YOU +// SHOULD BE ABLE TO MODIFY YOUR BLOWFISH CODE TO USE (4-BYTE#) instead of BYTE# IN ONE LINE OF CODE +// TO FIX THE INCOMPATIBILITY. +// THERE IS ALSO A BASE64 INCOMPATIBILITY THAT YOU NEED TO FIX TO USE OTHER BLOWFISH ALGORITHMS. +// WE ARE WORKING TO MAKE A COLLECTION OF COMPATIBLE ROUTINES IN DIF. LANGUAGES (java, php, perl). +// PLEASE BARE WITH US - WE CHOSE TO USE THESE METHODS TO INSURE BACKWARD COMPATIBILITY WITH EXISTING SCRIPTS + union aword { + DWORD dword; + BYTE byte [4]; + struct { + unsigned int byte3:8; + unsigned int byte2:8; + unsigned int byte1:8; + unsigned int byte0:8; + } w; + }; +#endif + +#ifdef ORDER_ABCD // ABCD - big endian - motorola + union aword { + DWORD dword; + BYTE byte [4]; + struct { + unsigned int byte0:8; + unsigned int byte1:8; + unsigned int byte2:8; + unsigned int byte3:8; + } w; + }; +#endif + +#ifdef ORDER_BADC // BADC - vax + union aword { + DWORD dword; + BYTE byte [4]; + struct { + unsigned int byte1:8; + unsigned int byte0:8; + unsigned int byte3:8; + unsigned int byte2:8; + } w; +}; +#endif +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +class oldCBlowFish +{ +private: + DWORD * PArray ; + DWORD (* SBoxes)[256]; +public: + void Blowfish_encipher (DWORD *xl, DWORD *xr) ; + void Blowfish_decipher (DWORD *xl, DWORD *xr) ; +public: + oldCBlowFish () ; + ~oldCBlowFish () ; + void Initialize (BYTE key[], int keybytes) ; + DWORD GetOutputLength (DWORD lInputLong) ; + DWORD Encode (BYTE * pInput, BYTE * pOutput, DWORD lSize) ; + void Decode (BYTE * pInput, BYTE * pOutput, DWORD lSize) ; +} ; +//--------------------------------------------------------------------------- + + + + + +//--------------------------------------------------------------------------- +#endif +//--------------------------------------------------------------------------- + diff --git a/konversation/src/blowfish/oldblowfish2.h b/konversation/src/blowfish/oldblowfish2.h new file mode 100644 index 0000000..8afbe93 --- /dev/null +++ b/konversation/src/blowfish/oldblowfish2.h @@ -0,0 +1,295 @@ +/* + blowfish1.h interface file for mc_blowfish.cpp + _THE BLOWFISH ENCRYPTION ALGORITHM_ + by Bruce Schneier, 1996, Applied Cryptography, 2nd ed., John Wiley & Sons + + Public Domain. + + Copyright (C) 1994 Bruce Schneier + Copyright (C) 1996 Jim Conger +*/ + +// blowfish.h2 header file containing random number tables +//--------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------- +// To prevent multiple includes +#ifndef _oldblowfish2h +#define _oldblowfish2h +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +static DWORD bf_P[NPASS + 2] = { + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b, +}; +static DWORD bf_S[4][256] = { + {0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a}, + {0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7}, + {0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0}, + {0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}, +}; +//--------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +// header guard +#endif +//--------------------------------------------------------------------------- diff --git a/konversation/src/channel.cpp b/konversation/src/channel.cpp new file mode 100644 index 0000000..38a7e63 --- /dev/null +++ b/konversation/src/channel.cpp @@ -0,0 +1,2960 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2004-2006 Peter Simonsson + Copyright (C) 2006-2008 Eike Hein +*/ + +#include "channel.h" +#include "konversationapplication.h" +#include "server.h" +#include "blowfish.h" +#include "nick.h" +#include "nicklistview.h" +#include "quickbutton.h" +#include "modebutton.h" +#include "ircinput.h" +#include "ircviewbox.h" +#include "ircview.h" +#include +#include +#include "common.h" +#include "topiclabel.h" +#include "channeloptionsdialog.h" +#include "notificationhandler.h" +#include "viewcontainer.h" +#include "linkaddressbook/linkaddressbookui.h" +#include "linkaddressbook/addressbook.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +Channel::Channel(QWidget* parent, QString _name) : ChatWindow(parent) +{ + // init variables + + //HACK I needed the channel name at time of setServer, but setName needs m_server.. + // This effectively assigns the name twice, but none of the other logic has been moved or updated. + name=_name; + m_processingTimer = 0; + m_delayedSortTimer = 0; + m_optionsDialog = NULL; + m_pendingChannelNickLists.clear(); + m_currentIndex = 0; + m_opsToAdd = 0; + nicks = 0; + ops = 0; + completionPosition = 0; + nickChangeDialog = 0; + channelCommand = false; + + m_joined = false; + + quickButtonsChanged = false; + quickButtonsState = false; + + modeButtonsChanged = false; + modeButtonsState = false; + + awayChanged = false; + awayState = false; + + splittersInitialized = false; + topicSplitterHidden = false; + channelSplitterHidden = false; + + // flag for first seen topic + topicAuthorUnknown = true; + + setType(ChatWindow::Channel); + + setChannelEncodingSupported(true); + + // Build some size policies for the widgets + QSizePolicy hfixed = QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + QSizePolicy hmodest = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + QSizePolicy vmodest = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + QSizePolicy vfixed = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + QSizePolicy modest = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + QSizePolicy greedy = QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + + m_vertSplitter = new QSplitter(Qt::Vertical, this); + m_vertSplitter->setOpaqueResize(KGlobalSettings::opaqueResize()); + + + QWidget* topicWidget = new QWidget(m_vertSplitter); + m_vertSplitter->setResizeMode(topicWidget,QSplitter::KeepSize); + + QGridLayout* topicLayout = new QGridLayout(topicWidget, 2, 3, 0, 0); + + m_topicButton = new QToolButton(topicWidget); + m_topicButton->setIconSet(SmallIconSet("edit", 16)); + QToolTip::add(m_topicButton, i18n("Edit Channel Settings")); + connect(m_topicButton, SIGNAL(clicked()), this, SLOT(showOptionsDialog())); + + topicLine = new Konversation::TopicLabel(topicWidget); + QWhatsThis::add(topicLine, i18n("Every channel on IRC has a topic associated with it. This is simply a message that everybody can see.

If you are an operator, or the channel mode 'T' has not been set, then you can change the topic by clicking the Edit Channel Properties button to the left of the topic. You can also view the history of topics there.")); + connect(topicLine, SIGNAL(setStatusBarTempText(const QString&)), this, SIGNAL(setStatusBarTempText(const QString&))); + connect(topicLine, SIGNAL(clearStatusBarTempText()), this, SIGNAL(clearStatusBarTempText())); + connect(topicLine,SIGNAL(popupCommand(int)),this,SLOT(popupChannelCommand(int))); + + topicLayout->addWidget(m_topicButton, 0, 0); + topicLayout->addMultiCellWidget(topicLine, 0, 1, 1, 1); + + // The box holding the channel modes + modeBox = new QHBox(topicWidget); + modeBox->setSizePolicy(hfixed); + modeT = new ModeButton("T",modeBox,0); + modeN = new ModeButton("N",modeBox,1); + modeS = new ModeButton("S",modeBox,2); + modeI = new ModeButton("I",modeBox,3); + modeP = new ModeButton("P",modeBox,4); + modeM = new ModeButton("M",modeBox,5); + modeK = new ModeButton("K",modeBox,6); + modeL = new ModeButton("L",modeBox,7); + + QWhatsThis::add(modeT, i18n("These control the mode of the channel. Only an operator can change these.

The Topic mode means that only the channel operator can change the topic for the channel.")); + QWhatsThis::add(modeN, i18n("These control the mode of the channel. Only an operator can change these.

No messages from outside means that users that are not in the channel cannot send messages that everybody in the channel can see. Almost all channels have this set to prevent nuisance messages.")); + QWhatsThis::add(modeS, i18n("These control the mode of the channel. Only an operator can change these.

A Secret channel will not show up in the channel list, nor will any user be able to see that you are in the channel with the WHOIS command or anything similar. Only the people that are in the same channel will know that you are in this channel, if this mode is set.")); + QWhatsThis::add(modeI, i18n("These control the mode of the channel. Only an operator can change these.

An Invite only channel means that people can only join the channel if they are invited. To invite someone, a channel operator needs to issue the command /invite nick from within the channel.")); + QWhatsThis::add(modeP, i18n("These control the mode of the channel. Only an operator can change these.

A Private channel is shown in a listing of all channels, but the topic is not shown. A user's WHOIS may or may not show them as being in a private channel depending on the IRC server.")); + QWhatsThis::add(modeM, i18n("These control the mode of the channel. Only an operator can change these.

A Moderated channel is one where only operators, half-operators and those with voice can talk.")); + QWhatsThis::add(modeK, i18n("These control the mode of the channel. Only an operator can change these.

A Protected channel requires users to enter a password in order to join.")); + QWhatsThis::add(modeL, i18n("These control the mode of the channel. Only an operator can change these.

A channel that has a user Limit means that only that many users can be in the channel at any one time. Some channels have a bot that sits in the channel and changes this automatically depending on how busy the channel is.")); + + connect(modeT,SIGNAL(clicked(int,bool)),this,SLOT(modeButtonClicked(int,bool))); + connect(modeN,SIGNAL(clicked(int,bool)),this,SLOT(modeButtonClicked(int,bool))); + connect(modeS,SIGNAL(clicked(int,bool)),this,SLOT(modeButtonClicked(int,bool))); + connect(modeI,SIGNAL(clicked(int,bool)),this,SLOT(modeButtonClicked(int,bool))); + connect(modeP,SIGNAL(clicked(int,bool)),this,SLOT(modeButtonClicked(int,bool))); + connect(modeM,SIGNAL(clicked(int,bool)),this,SLOT(modeButtonClicked(int,bool))); + connect(modeK,SIGNAL(clicked(int,bool)),this,SLOT(modeButtonClicked(int,bool))); + connect(modeL,SIGNAL(clicked(int,bool)),this,SLOT(modeButtonClicked(int,bool))); + + limit=new KLineEdit(modeBox); + QToolTip::add(limit, i18n("Maximum users allowed in channel")); + QWhatsThis::add(limit, i18n("This is the channel user limit - the maximum number of users that can be in the channel at a time. If you are an operator, you can set this. The channel mode Topic (button to left) will automatically be set if set this.")); + connect(limit,SIGNAL (returnPressed()),this,SLOT (channelLimitChanged()) ); + connect(limit,SIGNAL (lostFocus()), this, SLOT(channelLimitChanged()) ); + + topicLayout->addWidget(modeBox, 0, 2); + topicLayout->setRowStretch(1, 10); + topicLayout->setColStretch(1, 10); + + showTopic(Preferences::showTopic()); + showModeButtons(Preferences::showModeButtons()); + + // (this) The main Box, holding the channel view/topic and the input line + m_horizSplitter = new QSplitter(m_vertSplitter); + m_horizSplitter->setOpaqueResize( KGlobalSettings::opaqueResize() ); + + // Server will be set later in setServer() + IRCViewBox* ircViewBox = new IRCViewBox(m_horizSplitter, NULL); + setTextView(ircViewBox->ircView()); + connect(textView,SIGNAL(popupCommand(int)),this,SLOT(popupChannelCommand(int))); + connect(topicLine, SIGNAL(currentChannelChanged(const QString&)),textView,SLOT(setCurrentChannel(const QString&))); + + // The box that holds the Nick List and the quick action buttons + nickListButtons = new QVBox(m_horizSplitter); + m_horizSplitter->setResizeMode(nickListButtons,QSplitter::KeepSize); + nickListButtons->setSpacing(spacing()); + + nicknameListView=new NickListView(nickListButtons, this); + nicknameListView->setHScrollBarMode(QScrollView::AlwaysOff); + nicknameListView->setSelectionModeExt(KListView::Extended); + nicknameListView->setAllColumnsShowFocus(true); + nicknameListView->setSorting(1,true); + nicknameListView->addColumn(QString()); + nicknameListView->addColumn(QString()); + nicknameListView->setColumnWidthMode(1,KListView::Maximum); + + nicknameListView->header()->hide(); + + // setResizeMode must be called after all the columns are added + nicknameListView->setResizeMode(KListView::LastColumn); + + // separate LED from Text a little more + nicknameListView->setColumnWidth(0, 10); + nicknameListView->setColumnAlignment(0, Qt::AlignHCenter); + + nicknameListView->installEventFilter(this); + + // initialize buttons grid, will be set up in updateQuickButtons + buttonsGrid=0; + + // The box holding the Nickname button and Channel input + commandLineBox = new QHBox(this); + commandLineBox->setSpacing(spacing()); + + nicknameCombobox = new QComboBox(commandLineBox); + nicknameCombobox->setEditable(true); + nicknameCombobox->insertStringList(Preferences::nicknameList()); + QWhatsThis::add(nicknameCombobox, i18n("This shows your current nick, and any alternatives you have set up. If you select or type in a different nickname, then a request will be sent to the IRC server to change your nick. If the server allows it, the new nickname will be selected. If you type in a new nickname, you need to press 'Enter' at the end.

You can add change the alternative nicknames from the Identities option in the File menu.")); + oldNick = nicknameCombobox->currentText(); + + awayLabel = new QLabel(i18n("(away)"), commandLineBox); + awayLabel->hide(); + blowfishLabel = new QLabel(commandLineBox); + blowfishLabel->hide(); + blowfishLabel->setPixmap(KGlobal::iconLoader()->loadIcon("encrypted", KIcon::Toolbar)); + channelInput = new IRCInput(commandLineBox); + + getTextView()->installEventFilter(channelInput); + topicLine->installEventFilter(channelInput); + channelInput->installEventFilter(this); + + // Set the widgets size policies + m_topicButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + topicLine->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum)); + + commandLineBox->setSizePolicy(vfixed); + + limit->setMaximumSize(40,100); + limit->setSizePolicy(hfixed); + + modeT->setMaximumSize(20,100); + modeT->setSizePolicy(hfixed); + modeN->setMaximumSize(20,100); + modeN->setSizePolicy(hfixed); + modeS->setMaximumSize(20,100); + modeS->setSizePolicy(hfixed); + modeI->setMaximumSize(20,100); + modeI->setSizePolicy(hfixed); + modeP->setMaximumSize(20,100); + modeP->setSizePolicy(hfixed); + modeM->setMaximumSize(20,100); + modeM->setSizePolicy(hfixed); + modeK->setMaximumSize(20,100); + modeK->setSizePolicy(hfixed); + modeL->setMaximumSize(20,100); + modeL->setSizePolicy(hfixed); + + getTextView()->setSizePolicy(greedy); + nicknameListView->setSizePolicy(hmodest); + + connect(channelInput,SIGNAL (submit()),this,SLOT (channelTextEntered()) ); + connect(channelInput,SIGNAL (envelopeCommand()),this,SLOT (channelPassthroughCommand()) ); + connect(channelInput,SIGNAL (nickCompletion()),this,SLOT (completeNick()) ); + connect(channelInput,SIGNAL (endCompletion()),this,SLOT (endCompleteNick()) ); + connect(channelInput,SIGNAL (textPasted(const QString&)),this,SLOT (textPasted(const QString&)) ); + + connect(getTextView(), SIGNAL(textPasted(bool)), channelInput, SLOT(paste(bool))); + connect(getTextView(),SIGNAL (gotFocus()),channelInput,SLOT (setFocus()) ); + connect(getTextView(),SIGNAL (sendFile()),this,SLOT (sendFileMenu()) ); + connect(getTextView(),SIGNAL (autoText(const QString&)),this,SLOT (sendChannelText(const QString&)) ); + + connect(nicknameListView,SIGNAL (popupCommand(int)),this,SLOT (popupCommand(int)) ); + connect(nicknameListView,SIGNAL (doubleClicked(QListViewItem*)),this,SLOT (doubleClickCommand(QListViewItem*)) ); + connect(nicknameListView,SIGNAL (dropped(QDropEvent*,QListViewItem*)),this,SLOT (filesDropped(QDropEvent*)) ); + connect(nicknameCombobox,SIGNAL (activated(int)),this,SLOT(nicknameComboboxChanged())); + + if(nicknameCombobox->lineEdit()) + connect(nicknameCombobox->lineEdit(), SIGNAL (lostFocus()),this,SLOT(nicknameComboboxChanged())); + + nicknameList.setAutoDelete(true); + + setLog(Preferences::log()); + + connect(&userhostTimer,SIGNAL (timeout()),this,SLOT (autoUserhost())); + + // every few seconds try to get more userhosts + userhostTimer.start(10000); + + connect(&m_whoTimer,SIGNAL (timeout()),this,SLOT (autoWho())); + + // every 5 minutes decrease everyone's activity by 1 unit + m_fadeActivityTimer.start(5*60*1000); + + connect(&m_fadeActivityTimer, SIGNAL(timeout()), this, SLOT(fadeActivity())); + + // re-schedule when the settings were changed + connect(Preferences::self(), SIGNAL (autoContinuousWhoChanged()),this,SLOT (scheduleAutoWho())); + + updateAppearance(); + + //FIXME JOHNFLUX + // connect( Konversation::Addressbook::self()->getAddressBook(), SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( slotLoadAddressees() ) ); + // connect( Konversation::Addressbook::self(), SIGNAL(addresseesChanged()), this, SLOT(slotLoadAddressees())); +} + +//FIXME there is some logic in setLogfileName that needs to be split out and called here if the server display name gets changed +void Channel::setServer(Server* server) +{ + if (m_server != server) + connect(server, SIGNAL(connectionStateChanged(Server*, Konversation::ConnectionState)), + SLOT(connectionStateChanged(Server*, Konversation::ConnectionState))); + ChatWindow::setServer(server); + if (server->getKeyForRecipient(getName())) + blowfishLabel->show(); + topicLine->setServer(server); + refreshModeButtons(); + setIdentity(server->getIdentity()); +} + +void Channel::connectionStateChanged(Server* server, Konversation::ConnectionState state) +{ + if (server == m_server) + { + if (state != Konversation::SSConnected) + { + m_joined = false; + + //HACK the way the notification priorities work sucks, this forces the tab text color to gray right now. + if (m_currentTabNotify == Konversation::tnfNone || (!Preferences::tabNotificationsEvents() && m_currentTabNotify == Konversation::tnfControl)) + KonversationApplication::instance()->getMainWindow()->getViewContainer()->unsetViewNotification(this); + } + } +} + +void Channel::setEncryptedOutput(bool e) +{ + if (e) { + blowfishLabel->show(); + //scan the channel topic and decrypt it if necessary + QString topic(m_topicHistory[0].section(' ',2)); + + //prepend two colons to make it appear to be an irc message for decryption, + // \r because it won't decrypt without it, even though the message did not have a \r + // when encrypted. Bring on the QCA! + QCString cipher="::"+topic.utf8()+'\x0d'; + Konversation::decryptTopic(getName(), cipher, m_server); + topic=QString::fromUtf8(cipher.data()+2, cipher.length()-2); + m_topicHistory[0] = m_topicHistory[0].section(' ', 0, 1) + ' ' + topic; + topicLine->setText(topic); + emit topicHistoryChanged(); + } + else + blowfishLabel->hide(); +} + +Channel::~Channel() +{ + kdDebug() << "Channel::~Channel(" << getName() << ")" << endl; + + // Purge nickname list + purgeNicks(); + kdDebug() << "nicks purged" << endl; + + // Unlink this channel from channel list + m_server->removeChannel(this); + kdDebug() << "Channel removed." << endl; + +} + +bool Channel::rejoinable() +{ + if (getServer() && getServer()->isConnected()) + return !m_joined; + + return false; +} + +void Channel::rejoin() +{ + if (rejoinable()) + m_server->sendJoinCommand(getName(), getPassword()); +} + +ChannelNickPtr Channel::getOwnChannelNick() +{ + return m_ownChannelNick; +} + +ChannelNickPtr Channel::getChannelNick(const QString &ircnick) +{ + return m_server->getChannelNick(getName(), ircnick); +} + +void Channel::purgeNicks() +{ + // Purge nickname list + nicknameList.clear(); + + // clear stats counter + nicks=0; + ops=0; +} + +void Channel::showOptionsDialog() +{ + if(!m_optionsDialog) + m_optionsDialog = new Konversation::ChannelOptionsDialog(this); + + m_optionsDialog->refreshModes(); + m_optionsDialog->refreshTopicHistory(); + m_optionsDialog->show(); +} + +void Channel::filesDropped(QDropEvent* e) +{ + QPoint p(nicknameListView->contentsToViewport(e->pos())); + Nick* it = dynamic_cast(nicknameListView->itemAt(p)); + if (!it) return; + QStrList uris; + if (QUriDrag::decode(e,uris)) + m_server->sendURIs(uris, it->getChannelNick()->getNickname()); +} + +void Channel::textPasted(const QString& text) +{ + if(m_server) + { + QStringList multiline=QStringList::split('\n',text); + for(unsigned int index=0;indexclearContextNick(); + channelCommand = false; +} + +// Will be connected to NickListView::popupCommand(int) +void Channel::popupCommand(int id) +{ + QString pattern; + QString cc = Preferences::commandChar(); + QString args; + QString question; + bool raw=false; + QStringList nickList = getSelectedNickList(); + + switch(id) + { + case Konversation::AddressbookEdit: + { + ChannelNickList nickList=getSelectedChannelNicks(); + for(ChannelNickList::ConstIterator it=nickList.begin();it!=nickList.end();++it) + { + if(!(*it)->getNickInfo()->editAddressee()) break;; + } + break; + } + case Konversation::AddressbookNew: + case Konversation::AddressbookDelete: + { + Konversation::Addressbook *addressbook = Konversation::Addressbook::self(); + ChannelNickList nickList=getSelectedChannelNicks(); + //Handle all the selected nicks in one go. Either they all save, or none do. + if(addressbook->getAndCheckTicket()) + { + for(ChannelNickList::ConstIterator it=nickList.begin();it!=nickList.end();++it) + { + if(id == Konversation::AddressbookDelete) + { + KABC::Addressee addr = (*it)->getNickInfo()->getAddressee(); + addressbook->unassociateNick(addr, (*it)->getNickname(), m_server->getServerName(), m_server->getDisplayName()); + } + else + { + //make new addressbook contact + KABC::Addressee addr; + NickInfoPtr nickInfo = (*it)->getNickInfo(); + if(nickInfo->getRealName().isEmpty()) + addr.setGivenName(nickInfo->getNickname()); + else + addr.setGivenName(nickInfo->getRealName()); + addr.setNickName(nickInfo->getNickname()); + addressbook->associateNickAndUnassociateFromEveryoneElse(addr, (*it)->getNickname(), m_server->getServerName(), m_server->getDisplayName()); + } + } + addressbook->saveTicket(); // This will refresh the nicks automatically for us. At least, if it doesn't, it's a bug :) + } + break; + } + case Konversation::AddressbookChange: + { + ChannelNickList nickList=getSelectedChannelNicks(); + for(ChannelNickList::ConstIterator it=nickList.begin();it!=nickList.end();++it) + { + (*it)->getNickInfo()->showLinkAddressbookUI(); + } + break; + } + case Konversation::SendEmail: + { + Konversation::Addressbook::self()->sendEmail(getSelectedChannelNicks()); + break; + } + case Konversation::AddressbookSub: + kdDebug() << "sub called" << endl; + break; + case Konversation::GiveOp: + pattern="MODE %c +o %u"; + raw=true; + break; + case Konversation::TakeOp: + pattern="MODE %c -o %u"; + raw=true; + break; + case Konversation::GiveHalfOp: + pattern="MODE %c +h %u"; + raw=true; + break; + case Konversation::TakeHalfOp: + pattern="MODE %c -h %u"; + raw=true; + break; + case Konversation::GiveVoice: + pattern="MODE %c +v %u"; + raw=true; + break; + case Konversation::TakeVoice: + pattern="MODE %c -v %u"; + raw=true; + break; + case Konversation::Version: + pattern=cc+"CTCP %u VERSION"; + break; + case Konversation::Whois: + pattern="WHOIS %u %u"; + raw=true; + break; + case Konversation::Topic: + m_server->requestTopic(getTextView()->currentChannel()); + break; + case Konversation::Names: + m_server->queue("NAMES " + getTextView()->currentChannel(), Server::LowPriority); + break; + case Konversation::Join: + m_server->queue("JOIN " + getTextView()->currentChannel()); + break; + case Konversation::Ping: + { + unsigned int time_t = QDateTime::currentDateTime().toTime_t(); + pattern=QString(cc+"CTCP %u PING %1").arg(time_t); + } + break; + case Konversation::Kick: + pattern=cc+"KICK %u"; + break; + case Konversation::KickBan: + pattern=cc+"BAN %u\n"+ + cc+"KICK %u"; + break; + case Konversation::BanNick: + pattern=cc+"BAN %u"; + break; + case Konversation::BanHost: + pattern=cc+"BAN -HOST %u"; + break; + case Konversation::BanDomain: + pattern=cc+"BAN -DOMAIN %u"; + break; + case Konversation::BanUserHost: + pattern=cc+"BAN -USERHOST %u"; + break; + case Konversation::BanUserDomain: + pattern=cc+"BAN -USERDOMAIN %u"; + break; + case Konversation::KickBanHost: + pattern=cc+"KICKBAN -HOST %u"; + break; + case Konversation::KickBanDomain: + pattern=cc+"KICKBAN -DOMAIN %u"; + break; + case Konversation::KickBanUserHost: + pattern=cc+"KICKBAN -USERHOST %u"; + break; + case Konversation::KickBanUserDomain: + pattern=cc+"KICKBAN -USERDOMAIN %u"; + break; + case Konversation::OpenQuery: + pattern=cc+"QUERY %u"; + break; + case Konversation::StartDccChat: + pattern=cc+"DCC CHAT %u"; + break; + case Konversation::DccSend: + pattern=cc+"DCC SEND %u"; + break; + case Konversation::IgnoreNick: + if (nickList.size() == 1) + question=i18n("Do you want to ignore %1?").arg(nickList.first()); + else + question = i18n("Do you want to ignore the selected users?"); + if (KMessageBox::warningContinueCancel(this, question, i18n("Ignore"), i18n("Ignore"), "IgnoreNick") == + KMessageBox::Continue) + pattern = cc+"IGNORE -ALL %l"; + break; + case Konversation::UnignoreNick: + { + QStringList selectedIgnoredNicks; + + for (QStringList::Iterator it=nickList.begin(); it!=nickList.end(); ++it) + { + if (Preferences::isIgnored((*it))) + selectedIgnoredNicks.append((*it)); + } + + if (selectedIgnoredNicks.count() == 1) + question=i18n("Do you want to stop ignoring %1?").arg(selectedIgnoredNicks.first()); + else + question = i18n("Do you want to stop ignoring the selected users?"); + if (KMessageBox::warningContinueCancel(this, question, i18n("Unignore"), i18n("Unignore"), "UnignoreNick") == + KMessageBox::Continue) + { + sendChannelText(cc+"UNIGNORE "+selectedIgnoredNicks.join(" ")); + } + break; + } + case Konversation::AddNotify: + { + if (m_server->getServerGroup()) + { + for (QStringList::Iterator it=nickList.begin(); it!=nickList.end(); ++it) + { + if (!Preferences::isNotify(m_server->getServerGroup()->id(), (*it))) + Preferences::addNotify(m_server->getServerGroup()->id(), (*it)); + } + } + break; + } + } // switch + + if (!pattern.isEmpty()) + { + pattern.replace("%c",getName()); + + QString command; + + if (pattern.contains("%l")) + { + QStringList list; + + for (QStringList::Iterator it=nickList.begin(); it!=nickList.end(); ++it) + list.append((*it)); + + command = pattern.replace("%l", list.join(" ")); + + if (raw) + m_server->queue(command); + else + sendChannelText(command); + } + else + { + QStringList patternList = QStringList::split('\n',pattern); + + for (QStringList::Iterator it=nickList.begin(); it!=nickList.end(); ++it) + { + for (unsigned int index = 0; indexqueue(command); + else + sendChannelText(command); + } + } + } + } +} + +// Will be connected to NickListView::doubleClicked() +void Channel::doubleClickCommand(QListViewItem* item) +{ + if(item) + { + nicknameListView->clearSelection(); + nicknameListView->setSelected(item, true); + // TODO: put the quick button code in another function to make reusal more legitimate + quickButtonClicked(Preferences::channelDoubleClickAction()); + } +} + +void Channel::completeNick() +{ + int pos, oldPos; + + channelInput->getCursorPosition(&oldPos,&pos);// oldPos is a dummy here, taking the paragraph parameter + oldPos = channelInput->getOldCursorPosition(); + + QString line=channelInput->text(); + QString newLine; + // Check if completion position is out of range + if(completionPosition >= nicknameList.count()) completionPosition = 0; + + // Check, which completion mode is active + char mode = channelInput->getCompletionMode(); + + if(mode == 'c') + { + line.remove(oldPos, pos - oldPos); + pos = oldPos; + } + + // If the cursor is at beginning of line, insert last completion + if(pos == 0 && !channelInput->lastCompletion().isEmpty()) + { + QString addStart(Preferences::nickCompleteSuffixStart()); + newLine = channelInput->lastCompletion() + addStart; + // New cursor position is behind nickname + pos = newLine.length(); + // Add rest of the line + newLine += line; + } + else + { + // remember old cursor position in input field + channelInput->setOldCursorPosition(pos); + // remember old cursor position locally + oldPos = pos; + // step back to last space or start of line + while(pos && line[pos-1] != ' ') pos--; + // copy search pattern (lowercase) + QString pattern = line.mid(pos, oldPos - pos); + // copy line to newLine-buffer + newLine = line; + + // did we find any pattern? + if(!pattern.isEmpty()) + { + bool complete = false; + QString foundNick; + + // try to find matching nickname in list of names + if(Preferences::nickCompletionMode() == 1 || + Preferences::nickCompletionMode() == 2) + { // Shell like completion + QStringList found; + foundNick = nicknameList.completeNick(pattern, complete, found, + (Preferences::nickCompletionMode() == 2), + Preferences::nickCompletionCaseSensitive()); + + if(!complete && !found.isEmpty()) + { + if(Preferences::nickCompletionMode() == 1) + { + QString nicksFound = found.join(" "); + appendServerMessage(i18n("Completion"), i18n("Possible completions: %1.").arg(nicksFound)); + } + else + { + channelInput->showCompletionList(found); + } + } + } // Cycle completion + else if(Preferences::nickCompletionMode() == 0) + { + if(mode == '\0') { + QPtrListIterator it(nicknameList); + uint timeStamp = 0; + int listPosition = 0; + Nick* nick = 0; + + while(it.current() != 0) + { + nick = it.current(); + + if(nick->getChannelNick()->getNickname().startsWith(pattern, Preferences::nickCompletionCaseSensitive()) && + (nick->getChannelNick()->timeStamp() > timeStamp)) + { + timeStamp = nick->getChannelNick()->timeStamp(); + completionPosition = listPosition; + } + + ++listPosition; + ++it; + } + } + + // remember old nick completion position + unsigned int oldCompletionPosition = completionPosition; + complete = true; + QString prefixCharacter = Preferences::prefixCharacter(); + + do + { + QString lookNick = nicknameList.at(completionPosition)->getChannelNick()->getNickname(); + + if(!prefixCharacter.isEmpty() && lookNick.contains(prefixCharacter)) + { + lookNick = lookNick.section( prefixCharacter,1 ); + } + + if(lookNick.startsWith(pattern, Preferences::nickCompletionCaseSensitive())) + { + foundNick = lookNick; + } + + // increment search position + completionPosition++; + + // wrap around + if(completionPosition == nicknameList.count()) + { + completionPosition = 0; + } + + // the search ends when we either find a suitable nick or we end up at the + // first search position + } while((completionPosition != oldCompletionPosition) && foundNick.isEmpty()); + } + + // did we find a suitable nick? + if(!foundNick.isEmpty()) + { + // set channel nicks completion mode + channelInput->setCompletionMode('c'); + + // remove pattern from line + newLine.remove(pos, pattern.length()); + + // did we find the nick in the middle of the line? + if(pos && complete) + { + channelInput->setLastCompletion(foundNick); + QString addMiddle = Preferences::nickCompleteSuffixMiddle(); + newLine.insert(pos, foundNick + addMiddle); + pos = pos + foundNick.length() + addMiddle.length(); + } + // no, it was at the beginning + else if(complete) + { + channelInput->setLastCompletion(foundNick); + QString addStart = Preferences::nickCompleteSuffixStart(); + newLine.insert(pos, foundNick + addStart); + pos = pos + foundNick.length() + addStart.length(); + } + // the nick wasn't complete + else + { + newLine.insert(pos, foundNick); + pos = pos + foundNick.length(); + } + } + // no pattern found, so restore old cursor position + else pos = oldPos; + } + } + + // Set new text and cursor position + channelInput->setText(newLine); + channelInput->setCursorPosition(0, pos); +} + +// make sure to step back one position when completion ends so the user starts +// with the last complete they made +void Channel::endCompleteNick() +{ + if(completionPosition) completionPosition--; + else completionPosition=nicknameList.count()-1; +} + +void Channel::setName(const QString& newName) +{ + ChatWindow::setName(newName); + setLogfileName(newName.lower()); +} + +bool Channel::autoJoin() +{ + if (!m_server->getServerGroup()) return false; + + Konversation::ChannelList channelList = m_server->getServerGroup()->channelList(); + + if (!channelList.empty()) + return channelList.find(channelSettings()) != channelList.end(); + else + return false; +} + +void Channel::setAutoJoin(bool autojoin) +{ + if (autojoin && !(autoJoin())) + { + Konversation::ChannelSettings before; + + QPtrList channelList = m_server->getChannelList(); + + if (channelList.count() > 1) + { + QPtrListIterator it(channelList); + Channel* channel; + QMap channelMap; + + int index = -1; + int ownIndex = m_server->getViewContainer()->getViewIndex(this); + + while ((channel = it.current()) != 0) + { + ++it; + + index = m_server->getViewContainer()->getViewIndex(channel); + + if (index && index > ownIndex) channelMap.insert(index, channel); + } + + if (channelMap.count()) + { + QMap::Iterator it2; + + for (it2 = channelMap.begin(); it2 != channelMap.end(); ++it2) + { + channel = it2.data(); + + if (channel->autoJoin()) + { + before = channel->channelSettings(); + + break; + } + } + } + } + + if (m_server->getServerGroup()) + m_server->getServerGroup()->addChannel(channelSettings(), before); + } + else + { + if (m_server->getServerGroup()) + m_server->getServerGroup()->removeChannel(channelSettings()); + } +} + + + +QString Channel::getPassword() +{ + QString password; + + for (QStringList::const_iterator it = m_modeList.begin(); it != m_modeList.end(); ++it) + { + if ((*it)[0] == 'k') password = (*it).mid(1); + } + + return password; +} + +const Konversation::ChannelSettings Channel::channelSettings() +{ + Konversation::ChannelSettings channel; + + channel.setName(getName()); + channel.setPassword(getPassword()); + channel.setNotificationsEnabled(notificationsEnabled()); + + return channel; +} + +void Channel::sendFileMenu() +{ + emit sendFile(); +} + +void Channel::channelTextEntered() +{ + QString line = channelInput->text(); + channelInput->setText (""); + + if(line.lower().stripWhiteSpace() == Preferences::commandChar()+"clear") + { + textView->clear(); + } + else if(line.lower().stripWhiteSpace() == Preferences::commandChar()+"cycle") + { + cycleChannel(); + } + else + { + if(!line.isEmpty()) + sendChannelText(line); + } +} + +void Channel::channelPassthroughCommand() +{ + QString commandChar = Preferences::commandChar(); + QString line = channelInput->text(); + + channelInput->setText(""); + + if(!line.isEmpty()) + { + // Prepend commandChar on Ctrl+Enter to bypass outputfilter command recognition + if (line.startsWith(commandChar)) + { + line = commandChar + line; + } + sendChannelText(line); + } +} + +void Channel::sendChannelText(const QString& sendLine) +{ + // create a work copy + QString outputAll(sendLine); + // replace aliases and wildcards + if(m_server->getOutputFilter()->replaceAliases(outputAll)) + { + outputAll = m_server->parseWildcards(outputAll,m_server->getNickname(),getName(),getPassword(), + getSelectedNickList(),QString()); + } + + // Send all strings, one after another + QStringList outList=QStringList::split(QRegExp("[\r\n]+"),outputAll); + for(unsigned int index=0;indexgetOutputFilter()->parse(m_server->getNickname(),output,getName()); + + // Is there something we need to display for ourselves? + if(!result.output.isEmpty()) + { + if(result.type == Konversation::Action) appendAction(m_server->getNickname(), result.output); + else if(result.type == Konversation::Command) appendCommandMessage(result.typeString, result.output); + else if(result.type == Konversation::Program) appendServerMessage(result.typeString, result.output); + else if(result.type == Konversation::PrivateMessage) appendQuery(result.typeString, result.output, true); + else append(m_server->getNickname(), result.output); + } + else if (result.outputList.count()) + { + Q_ASSERT(result.type==Konversation::Message); + for ( QStringList::Iterator it = result.outputList.begin(); it != result.outputList.end(); ++it ) + { + append(m_server->getNickname(), *it); + } + } + // Send anything else to the server + if(!result.toServerList.empty()) + { + m_server->queueList(result.toServerList); + } + else + { + m_server->queue(result.toServer); + } + } // for +} + +void Channel::setNickname(const QString& newNickname) +{ + nicknameCombobox->setCurrentText(newNickname); +} + +QStringList Channel::getSelectedNickList() +{ + QStringList result; + + if (channelCommand) + result.append(textView->getContextNick()); + else + { + Nick* nick=nicknameList.first(); + + while(nick) + { + if(nick->isSelected()) result.append(nick->getChannelNick()->getNickname()); + nick=nicknameList.next(); + } + } + + return result; +} + +ChannelNickList Channel::getSelectedChannelNicks() +{ + ChannelNickList result; + Nick* nick=nicknameList.first(); + + while(nick) + { + if(channelCommand) + { + if(nick->getChannelNick()->getNickname() == textView->getContextNick()) + { + result.append(nick->getChannelNick()); + return result; + } + } + else if(nick->isSelected()) + result.append(nick->getChannelNick()); + + nick=nicknameList.next(); + } + + return result; + +} + +void Channel::channelLimitChanged() +{ + unsigned int lim=limit->text().toUInt(); + + modeButtonClicked(7,lim>0); +} + +void Channel::modeButtonClicked(int id, bool on) +{ + char mode[]={'t','n','s','i','p','m','k','l'}; + QString command("MODE %1 %2%3 %4"); + QString args = getPassword(); + + if (mode[id] == 'k') + { + if (args.isEmpty()) + { + QCString newPassword; + + int result = KPasswordDialog::getPassword(newPassword, i18n("Channel Password")); + + if (result == KPasswordDialog::Accepted && !newPassword.isEmpty()) + args = newPassword; + } + + } + else if(mode[id]=='l') + { + if(limit->text().isEmpty() && on) + { + bool ok=false; + // ask user how many nicks should be the limit + args=KInputDialog::getText(i18n("Nick Limit"), + i18n("Enter the new nick limit:"), + limit->text(), // will be always "" but what the hell ;) + &ok, + this); + // leave this function if user cancels + if(!ok) return; + } + else if(on) + args=limit->text(); + } + // put together the mode command and send it to the server queue + m_server->queue(command.arg(getName()).arg((on) ? "+" : "-").arg(mode[id]).arg(args)); +} + +void Channel::quickButtonClicked(const QString &buttonText) +{ + // parse wildcards (toParse,nickname,channelName,nickList,queryName,parameter) + QString out=m_server->parseWildcards(buttonText,m_server->getNickname(),getName(),getPassword(),getSelectedNickList(),QString()); + + // are there any newlines in the definition? + if(out.find('\n')!=-1) + sendChannelText(out); + // single line without newline needs to be copied into input line + else + channelInput->setText(out); +} + +void Channel::addNickname(ChannelNickPtr channelnick) +{ + + QString nickname = channelnick->loweredNickname(); + + Nick* nick=0; + Nick* lookNick; + QPtrListIterator it(nicknameList); + + while((lookNick = it.current()) != 0) + { + if(lookNick->getChannelNick()->loweredNickname() == nickname) + { + nick = lookNick; + break; + } + + ++it; + } + + if(nick == 0) + { + fastAddNickname(channelnick); + + if(channelnick->isAnyTypeOfOp()) + { + adjustOps(1); + } + + adjustNicks(1); + requestNickListSort(); + } + else + { + Q_ASSERT(false); // We shouldn't be adding someone that is already in the channel. + } +} + +// Use with caution! Does not sort or check for duplicates! +void Channel::fastAddNickname(ChannelNickPtr channelnick) +{ + Q_ASSERT(channelnick); + if(!channelnick) return; + Nick* nick = new Nick(nicknameListView, channelnick); + // nicks get sorted later + nicknameList.append(nick); +} + +void Channel::nickRenamed(const QString &oldNick, const NickInfo& nickInfo) +{ + + /* Did we change our nick name? */ + QString newNick = nickInfo.getNickname(); + + if(newNick == m_server->getNickname()) /* Check newNick because m_server->getNickname() is already updated to new nick */ + { + setNickname(newNick); + appendCommandMessage(i18n("Nick"),i18n("You are now known as %1.").arg(newNick), false, true, true); + } + else + { + /* No, must've been someone else */ + appendCommandMessage(i18n("Nick"),i18n("%1 is now known as %2.").arg(oldNick).arg(newNick),false); + } + + nicknameListView->sort(); + +} + +void Channel::joinNickname(ChannelNickPtr channelNick) +{ + if(channelNick->getNickname() == m_server->getNickname()) + { + m_joined = true; + emit joined(this); + appendCommandMessage(i18n("Join"),i18n("%1 is the channel and %2 is our hostmask", + "You have joined the channel %1 (%2).").arg(getName()).arg(channelNick->getHostmask()),false, false, true); + m_ownChannelNick = channelNick; + connect(m_ownChannelNick, SIGNAL(channelNickChanged()), SLOT(refreshModeButtons())); + refreshModeButtons(); + setActive(true); + + //HACK the way the notification priorities work sucks, this forces the tab text color to ungray right now. + if (m_currentTabNotify == Konversation::tnfNone || !Preferences::tabNotificationsEvents()) + KonversationApplication::instance()->getMainWindow()->getViewContainer()->unsetViewNotification(this); + + KonversationApplication::instance()->notificationHandler()->channelJoin(this,getName()); + } + else + { + QString nick = channelNick->getNickname(); + QString hostname = channelNick->getHostmask(); + appendCommandMessage(i18n("Join"), i18n("%1 is the nick joining and %2 the hostmask of that nick", + "%1 has joined this channel (%2).").arg(nick).arg(hostname),false, false); + addNickname(channelNick); + } +} + +void Channel::removeNick(ChannelNickPtr channelNick, const QString &reason, bool quit) +{ + QString displayReason = reason; + + if(!displayReason.isEmpty()) + { + // if the reason contains text markup characters, play it safe and reset all + if(displayReason.find(QRegExp("[\\0000-\\0037]")) != -1) + displayReason += "\017"; + } + + if(channelNick->getNickname() == m_server->getNickname()) + { + //If in the future we can leave a channel, but not close the window, refreshModeButtons() has to be called. + if (quit) + { + if (displayReason.isEmpty()) + appendCommandMessage(i18n("Quit"), i18n("You have left this server."), false); + else + appendCommandMessage(i18n("Quit"), i18n("%1 adds the reason", "You have left this server (%1).").arg(displayReason), false); + } + else + { + if (displayReason.isEmpty()) + appendCommandMessage(i18n("Part"), i18n("You have left channel %1.").arg(getName()), false); + else + appendCommandMessage(i18n("Part"), i18n("%1 adds the channel and %2 the reason", + "You have left channel %1 (%2).").arg(getName()).arg(displayReason), false); + + } + + delete this; + } + else + { + if (quit) + { + if (displayReason.isEmpty()) + appendCommandMessage(i18n("Quit"), i18n("%1 has left this server.").arg(channelNick->getNickname()), false); + else + appendCommandMessage(i18n("Quit"), i18n("%1 adds the nick and %2 the reason", + "%1 has left this server (%2).").arg(channelNick->getNickname()).arg(displayReason), false); + } + else + { + if (displayReason.isEmpty()) + appendCommandMessage(i18n("Part"), i18n("%1 has left this channel.").arg(channelNick->getNickname()), false); + else + appendCommandMessage(i18n("Part"), i18n("%1 adds the nick and %2 the reason", + "%1 has left this channel (%2).").arg(channelNick->getNickname()).arg(displayReason), false); + } + + if(channelNick->isAnyTypeOfOp()) + { + adjustOps(-1); + } + + adjustNicks(-1); + Nick* nick = getNickByName(channelNick->getNickname()); + + if(nick) + { + nicknameList.removeRef(nick); + } + else + { + kdWarning() << "Channel::removeNick(): Nickname " << channelNick->getNickname() << " not found!"<< endl; + } + } +} + +void Channel::kickNick(ChannelNickPtr channelNick, const QString &kicker, const QString &reason) +{ + QString displayReason = reason; + + if(!displayReason.isEmpty()) + { + // if the reason contains text markup characters, play it safe and reset all + if(displayReason.find(QRegExp("[\\0000-\\0037]")) != -1) + displayReason += "\017"; + } + + if(channelNick->getNickname() == m_server->getNickname()) + { + if(kicker == m_server->getNickname()) + { + if (displayReason.isEmpty()) + appendCommandMessage(i18n("Kick"), i18n("You have kicked yourself from channel %1.").arg(getName())); + else + appendCommandMessage(i18n("Kick"), i18n("%1 adds the channel and %2 the reason", + "You have kicked yourself from channel %1 (%2).").arg(getName()).arg(displayReason)); + } + else + { + if (displayReason.isEmpty()) + { + appendCommandMessage(i18n("Kick"), i18n("%1 adds the channel, %2 adds the kicker", + "You have been kicked from channel %1 by %2.") + .arg(getName()).arg(kicker), true); + } + else + { + appendCommandMessage(i18n("Kick"), i18n("%1 adds the channel, %2 the kicker and %3 the reason", + "You have been kicked from channel %1 by %2 (%3).") + .arg(getName()).arg(kicker).arg(displayReason), true); + } + + KonversationApplication::instance()->notificationHandler()->kick(this,getName(), kicker); + } + + m_joined=false; + setActive(false); + + //HACK the way the notification priorities work sucks, this forces the tab text color to gray right now. + if (m_currentTabNotify == Konversation::tnfNone || (!Preferences::tabNotificationsEvents() && m_currentTabNotify == Konversation::tnfControl)) + KonversationApplication::instance()->getMainWindow()->getViewContainer()->unsetViewNotification(this); + + return; + } + else + { + if(kicker == m_server->getNickname()) + { + if (displayReason.isEmpty()) + appendCommandMessage(i18n("Kick"), i18n("You have kicked %1 from the channel.").arg(channelNick->getNickname())); + else + appendCommandMessage(i18n("Kick"), i18n("%1 adds the kicked nick and %2 the reason", + "You have kicked %1 from the channel (%2).").arg(channelNick->getNickname()).arg(displayReason), true); + } + else + { + if (displayReason.isEmpty()) + { + appendCommandMessage(i18n("Kick"), i18n("%1 adds the kicked nick, %2 adds the kicker", + "%1 has been kicked from the channel by %2.") + .arg(channelNick->getNickname()).arg(kicker), true); + } + else + { + appendCommandMessage(i18n("Kick"), i18n("%1 adds the kicked nick, %2 the kicker and %3 the reason", + "%1 has been kicked from the channel by %2 (%3).") + .arg(channelNick->getNickname()).arg(kicker).arg(displayReason), true); + } + } + + if(channelNick->isAnyTypeOfOp()) + adjustOps(-1); + + adjustNicks(-1); + Nick* nick = getNickByName(channelNick->getNickname()); + + if(nick == 0) + { + kdWarning() << "Channel::kickNick(): Nickname " << channelNick->getNickname() << " not found!"<< endl; + } + else + { + nicknameList.removeRef(nick); + } + } +} + +Nick* Channel::getNickByName(const QString &lookname) +{ + QString lcLookname = lookname.lower(); + QPtrListIterator it(nicknameList); + + while(it.current() != 0) + { + if(it.current()->getChannelNick()->loweredNickname() == lcLookname) + return it.current(); + + ++it; + } + + return 0; +} + +void Channel::adjustNicks(int value) +{ + if((nicks == 0) && (value <= 0)) + { + return; + } + + nicks += value; + + if(nicks < 0) + { + nicks = 0; + } + + emitUpdateInfo(); +} + +void Channel::adjustOps(int value) +{ + if((ops == 0) && (value <= 0)) + { + return; + } + + ops += value; + + if(ops < 0) + { + ops = 0; + } + + emitUpdateInfo(); +} + +void Channel::emitUpdateInfo() +{ + QString info = getName() + " - "; + info += i18n("%n nick", "%n nicks", numberOfNicks()); + info += i18n(" (%n op)", " (%n ops)", numberOfOps()); + + emit updateInfo(info); +} + +void Channel::setTopic(const QString &newTopic) +{ + appendCommandMessage(i18n("Topic"), i18n("The channel topic is \"%1\".").arg(newTopic)); + QString topic = Konversation::removeIrcMarkup(newTopic); + topicLine->setText(topic); + topicAuthorUnknown=true; // if we only get called with a topic, it was a 332, which usually has a 333 next + + // cut off "nickname" and "time_t" portion of the topic before comparing, otherwise the history + // list will fill up with the same entries while the user only requests the topic to be seen. + + if(m_topicHistory.first().section(' ', 2) != newTopic) + { + m_topicHistory.prepend(QString("%1 "+i18n("unknown")+" %2").arg(QDateTime::currentDateTime().toTime_t()).arg(newTopic)); + emit topicHistoryChanged(); + } +} + +void Channel::setTopic(const QString &nickname, const QString &newTopic) // Overloaded +{ + if(nickname == m_server->getNickname()) + { + appendCommandMessage(i18n("Topic"), i18n("You set the channel topic to \"%1\".").arg(newTopic)); + } + else + { + appendCommandMessage(i18n("Topic"), i18n("%1 sets the channel topic to \"%2\".").arg(nickname).arg(newTopic)); + } + + m_topicHistory.prepend(QString("%1 %2 %3").arg(QDateTime::currentDateTime().toTime_t()).arg(nickname).arg(newTopic)); + QString topic = Konversation::removeIrcMarkup(newTopic); + topicLine->setText(topic); + + emit topicHistoryChanged(); +} + +QStringList Channel::getTopicHistory() +{ + return m_topicHistory; +} + +QString Channel::getTopic() +{ + return m_topicHistory[0]; +} + +void Channel::setTopicAuthor(const QString& newAuthor, QDateTime time) +{ + if (time.isNull() || !time.isValid()) + time=QDateTime::currentDateTime(); + + if(topicAuthorUnknown) + { + m_topicHistory[0] = QString("%1").arg(time.toTime_t()) + ' ' + newAuthor + ' ' + m_topicHistory[0].section(' ', 2); + topicAuthorUnknown = false; + + emit topicHistoryChanged(); + } +} + +void Channel::updateMode(const QString& sourceNick, char mode, bool plus, const QString ¶meter) +{ + //Note for future expansion: doing m_server->getChannelNick(getName(), sourceNick); may not return a valid channelNickPtr if the + //mode is updated by the server. + + QString message; + ChannelNickPtr parameterChannelNick=m_server->getChannelNick(getName(), parameter); + + bool fromMe=false; + bool toMe=false; + + // remember if this nick had any type of op. + bool wasAnyOp=false; + if(parameterChannelNick) + wasAnyOp=parameterChannelNick->isAnyTypeOfOp(); + + if(sourceNick.lower()==m_server->loweredNickname()) + fromMe=true; + if(parameter.lower()==m_server->loweredNickname()) + toMe=true; + + switch(mode) + { + case 'q': + if(plus) + { + if(fromMe) + { + if(toMe) + message=i18n("You give channel owner privileges to yourself."); + else + message=i18n("You give channel owner privileges to %1.").arg(parameter); + } + else + { + if(toMe) + message=i18n("%1 gives channel owner privileges to you.").arg(sourceNick); + else + message=i18n("%1 gives channel owner privileges to %2.").arg(sourceNick).arg(parameter); + } + } + else + { + if(fromMe) + { + if(toMe) + message=i18n("You take channel owner privileges from yourself."); + else + message=i18n("You take channel owner privileges from %1.").arg(parameter); + } + else + { + if(toMe) + message=i18n("%1 takes channel owner privileges from you.").arg(sourceNick); + else + message=i18n("%1 takes channel owner privileges from %2.").arg(sourceNick).arg(parameter); + } + } + if(parameterChannelNick) + { + parameterChannelNick->setOwner(plus); + emitUpdateInfo(); + nicknameListView->sort(); + } + break; + + case 'a': + if(plus) + { + if(fromMe) + { + if(toMe) + message=i18n("You give channel admin privileges to yourself."); + else + message=i18n("You give channel admin privileges to %1.").arg(parameter); + } + else + { + if(toMe) + message=i18n("%1 gives channel admin privileges to you.").arg(sourceNick); + else + message=i18n("%1 gives channel admin privileges to %2.").arg(sourceNick).arg(parameter); + } + } + else + { + if(fromMe) + { + if(toMe) + message=i18n("You take channel admin privileges from yourself."); + else + message=i18n("You take channel admin privileges from %1.").arg(parameter); + } + else + { + if(toMe) + message=i18n("%1 takes channel admin privileges from you.").arg(sourceNick); + else + message=i18n("%1 takes channel admin privileges from %2.").arg(sourceNick).arg(parameter); + } + } + if(parameterChannelNick) + { + parameterChannelNick->setOwner(plus); + emitUpdateInfo(); + nicknameListView->sort(); + } + break; + + case 'o': + if(plus) + { + if(fromMe) + { + if(toMe) + message=i18n("You give channel operator privileges to yourself."); + else + message=i18n("You give channel operator privileges to %1.").arg(parameter); + } + else + { + if(toMe) + message=i18n("%1 gives channel operator privileges to you.").arg(sourceNick); + else + message=i18n("%1 gives channel operator privileges to %2.").arg(sourceNick).arg(parameter); + } + } + else + { + if(fromMe) + { + if(toMe) + message=i18n("You take channel operator privileges from yourself."); + else + message=i18n("You take channel operator privileges from %1.").arg(parameter); + } + else + { + if(toMe) + message=i18n("%1 takes channel operator privileges from you.").arg(sourceNick); + else + message=i18n("%1 takes channel operator privileges from %2.").arg(sourceNick).arg(parameter); + } + } + if(parameterChannelNick) + { + parameterChannelNick->setOp(plus); + emitUpdateInfo(); + nicknameListView->sort(); + } + break; + + case 'h': + if(plus) + { + if(fromMe) + { + if(toMe) + message=i18n("You give channel halfop privileges to yourself."); + else + message=i18n("You give channel halfop privileges to %1.").arg(parameter); + } + else + { + if(toMe) + message=i18n("%1 gives channel halfop privileges to you.").arg(sourceNick); + else + message=i18n("%1 gives channel halfop privileges to %2.").arg(sourceNick).arg(parameter); + } + } + else + { + if(fromMe) + { + if(toMe) + message=i18n("You take channel halfop privileges from yourself."); + else + message=i18n("You take channel halfop privileges from %1.").arg(parameter); + } + else + { + if(toMe) + message=i18n("%1 takes channel halfop privileges from you.").arg(sourceNick); + else + message=i18n("%1 takes channel halfop privileges from %2.").arg(sourceNick).arg(parameter); + } + } + if(parameterChannelNick) + { + parameterChannelNick->setHalfOp(plus); + emitUpdateInfo(); + nicknameListView->sort(); + } + break; + + //case 'O': break; + + case 'v': + if(plus) + { + if(fromMe) + { + if(toMe) message=i18n("You give yourself permission to talk."); + else message=i18n("You give %1 permission to talk.").arg(parameter); + } + else + { + if(toMe) message=i18n("%1 gives you permission to talk.").arg(sourceNick); + else message=i18n("%1 gives %2 permission to talk.").arg(sourceNick).arg(parameter); + } + } + else + { + if(fromMe) + { + if(toMe) message=i18n("You take the permission to talk from yourself."); + else message=i18n("You take the permission to talk from %1.").arg(parameter); + } + else + { + if(toMe) message=i18n("%1 takes the permission to talk from you.").arg(sourceNick); + else message=i18n("%1 takes the permission to talk from %2.").arg(sourceNick).arg(parameter); + } + } + if(parameterChannelNick) + { + parameterChannelNick->setVoice(plus); + nicknameListView->sort(); + } + break; + + case 'c': + if(plus) + { + if(fromMe) message=i18n("You set the channel mode to 'no colors allowed'."); + else message=i18n("%1 sets the channel mode to 'no colors allowed'.").arg(sourceNick); + } + else + { + if(fromMe) message=i18n("You set the channel mode to 'allow color codes'."); + else message=i18n("%1 sets the channel mode to 'allow color codes'.").arg(sourceNick); + } + break; + + case 'i': + if(plus) + { + if(fromMe) message=i18n("You set the channel mode to 'invite only'."); + else message=i18n("%1 sets the channel mode to 'invite only'.").arg(sourceNick); + } + else + { + if(fromMe) message=i18n("You remove the 'invite only' mode from the channel."); + else message=i18n("%1 removes the 'invite only' mode from the channel.").arg(sourceNick); + } + modeI->setDown(plus); + break; + + case 'm': + if(plus) + { + if(fromMe) message=i18n("You set the channel mode to 'moderated'."); + else message=i18n("%1 sets the channel mode to 'moderated'.").arg(sourceNick); + } + else + { + if(fromMe) message=i18n("You set the channel mode to 'unmoderated'."); + else message=i18n("%1 sets the channel mode to 'unmoderated'.").arg(sourceNick); + } + modeM->setDown(plus); + break; + + case 'n': + if(plus) + { + if(fromMe) message=i18n("You set the channel mode to 'no messages from outside'."); + else message=i18n("%1 sets the channel mode to 'no messages from outside'.").arg(sourceNick); + } + else + { + if(fromMe) message=i18n("You set the channel mode to 'allow messages from outside'."); + else message=i18n("%1 sets the channel mode to 'allow messages from outside'.").arg(sourceNick); + } + modeN->setDown(plus); + break; + + case 'p': + if(plus) + { + if(fromMe) message=i18n("You set the channel mode to 'private'."); + else message=i18n("%1 sets the channel mode to 'private'.").arg(sourceNick); + } + else + { + if(fromMe) message=i18n("You set the channel mode to 'public'."); + else message=i18n("%1 sets the channel mode to 'public'.").arg(sourceNick); + } + modeP->setDown(plus); + if(plus) modeS->setDown(false); + break; + + case 's': + if(plus) + { + if(fromMe) message=i18n("You set the channel mode to 'secret'."); + else message=i18n("%1 sets the channel mode to 'secret'.").arg(sourceNick); + } + else + { + if(fromMe) message=i18n("You set the channel mode to 'visible'."); + else message=i18n("%1 sets the channel mode to 'visible'.").arg(sourceNick); + } + modeS->setDown(plus); + if(plus) modeP->setDown(false); + break; + + //case 'r': break; + + case 't': + if(plus) + { + if(fromMe) message=i18n("You switch on 'topic protection'."); + else message=i18n("%1 switches on 'topic protection'.").arg(sourceNick); + } + else + { + if(fromMe) message=i18n("You switch off 'topic protection'."); + else message=i18n("%1 switches off 'topic protection'.").arg(sourceNick); + } + modeT->setDown(plus); + break; + + case 'k': + if(plus) + { + if(fromMe) message=i18n("You set the channel key to '%1'.").arg(parameter); + else message=i18n("%1 sets the channel key to '%2'.").arg(sourceNick).arg(parameter); + } + else + { + if(fromMe) message=i18n("You remove the channel key."); + else message=i18n("%1 removes the channel key.").arg(sourceNick); + } + modeK->setDown(plus); + break; + + case 'l': + if(plus) + { + if(fromMe) message=i18n("You set the channel limit to %1 nicks.").arg(parameter); + else message=i18n("%1 sets the channel limit to %2 nicks.").arg(sourceNick).arg(parameter); + } + else + { + if(fromMe) message=i18n("You remove the channel limit."); + else message=i18n("%1 removes the channel limit.").arg(sourceNick); + } + modeL->setDown(plus); + if(plus) limit->setText(parameter); + else limit->clear(); + break; + + case 'b': + if(plus) + { + if(fromMe) message=i18n("You set a ban on %1.").arg(parameter); + else message=i18n("%1 sets a ban on %2.").arg(sourceNick).arg(parameter); + } + else + { + if(fromMe) message=i18n("You remove the ban on %1.").arg(parameter); + else message=i18n("%1 removes the ban on %2.").arg(sourceNick).arg(parameter); + } + break; + + case 'e': + if(plus) + { + if(fromMe) message=i18n("You set a ban exception on %1.").arg(parameter); + else message=i18n("%1 sets a ban exception on %2.").arg(sourceNick).arg(parameter); + } + else + { + if(fromMe) message=i18n("You remove the ban exception on %1.").arg(parameter); + else message=i18n("%1 removes the ban exception on %2.").arg(sourceNick).arg(parameter); + } + break; + + case 'I': + if(plus) + { + if(fromMe) message=i18n("You set invitation mask %1.").arg(parameter); + else message=i18n("%1 sets invitation mask %2.").arg(sourceNick).arg(parameter); + } + else + { + if(fromMe) message=i18n("You remove the invitation mask %1.").arg(parameter); + else message=i18n("%1 removes the invitation mask %2.").arg(sourceNick).arg(parameter); + } + break; + default: + if(plus) + { + if(fromMe) message=i18n("You set channel mode +%1").arg(mode); + else message=i18n("%1 sets channel mode +%2").arg(sourceNick).arg(mode); + } + else + { + if (fromMe) message=i18n("You set channel mode -%1").arg(mode); + else message= i18n("%1 sets channel mode -%2").arg(sourceNick).arg(mode); + } + } + + // check if this nick's anyOp-status has changed and adjust ops accordingly + if(parameterChannelNick) + { + if(wasAnyOp && (!parameterChannelNick->isAnyTypeOfOp())) + adjustOps(-1); + else if((!wasAnyOp) && parameterChannelNick->isAnyTypeOfOp()) + adjustOps(1); + } + + if(!message.isEmpty() && !Preferences::useLiteralModes()) + { + appendCommandMessage(i18n("Mode"),message); + } + + updateModeWidgets(mode,plus,parameter); +} + +void Channel::clearModeList() +{ + QString k; + + // Keep channel password in the backing store, for rejoins. + for (QStringList::const_iterator it = m_modeList.begin(); it != m_modeList.end(); ++it) + { + if ((*it)[0] == 'k') k = (*it); + } + + m_modeList.clear(); + + if (!k.isEmpty()) m_modeList << k; + + modeT->setOn(0); + modeT->setDown(0); + + modeN->setOn(0); + modeN->setDown(0); + + modeS->setOn(0); + modeS->setDown(0); + + modeI->setOn(0); + modeI->setDown(0); + + modeP->setOn(0); + modeP->setDown(0); + + modeM->setOn(0); + modeM->setDown(0); + + modeK->setOn(0); + modeK->setDown(0); + + modeL->setOn(0); + modeL->setDown(0); + + limit->clear(); + + emit modesChanged(); +} + +void Channel::updateModeWidgets(char mode, bool plus, const QString ¶meter) +{ + ModeButton* widget=0; + + if(mode=='t') widget=modeT; + else if(mode=='n') widget=modeN; + else if(mode=='s') widget=modeS; + else if(mode=='i') widget=modeI; + else if(mode=='p') widget=modeP; + else if(mode=='m') widget=modeM; + else if(mode=='k') widget=modeK; + else if(mode=='l') + { + widget=modeL; + if(plus) limit->setText(parameter); + else limit->clear(); + } + + if(widget) widget->setOn(plus); + + if(plus) + { + m_modeList.append(QString(mode + parameter)); + } + else + { + QStringList removable = m_modeList.grep(QRegExp(QString("^%1.*").arg(mode))); + + for(QStringList::iterator it = removable.begin(); it != removable.end(); ++it) + { + m_modeList.remove(m_modeList.find((*it))); + } + } + emit modesChanged(); +} + +void Channel::updateQuickButtons(const QStringList &newButtonList) +{ + // remove quick buttons from memory and GUI + while(buttonList.count()) + { + QuickButton* button=buttonList.at(0); + // remove tool tips as well + QToolTip::remove(button); + buttonList.remove(button); + delete button; + } + + if(buttonsGrid)delete buttonsGrid; + + // the grid that holds the quick action buttons + buttonsGrid = new QGrid(2, nickListButtons); + + // add new quick buttons + for(unsigned int index=0;indexsetText(buttonLabel); + quickButton->setDefinition(buttonText); + + // Add tool tips + QString toolTip=buttonText.replace("&","&"). + replace("<","<"). + replace(">",">"); + + QToolTip::add(quickButton,toolTip); + + quickButton->show(); + } // for + + // set hide() or show() on grid + showQuickButtons(Preferences::showQuickButtons()); +} + +void Channel::showQuickButtons(bool show) +{ + // Qt does not redraw the buttons properly when they are not on screen + // while getting hidden, so we remember the "soon to be" state here. + if(isHidden() || !buttonsGrid) + { + quickButtonsChanged=true; + quickButtonsState=show; + } + else + { + if(show) + buttonsGrid->show(); + else + buttonsGrid->hide(); + } +} + +void Channel::showModeButtons(bool show) +{ + // Qt does not redraw the buttons properly when they are not on screen + // while getting hidden, so we remember the "soon to be" state here. + if(isHidden()) + { + modeButtonsChanged=true; + modeButtonsState=show; + } + else + { + if(show) + { + topicSplitterHidden = false; + modeBox->show(); + modeBox->parentWidget()->show(); + } + else + { + modeBox->hide(); + + if(topicLine->isHidden()) + { + topicSplitterHidden = true; + modeBox->parentWidget()->hide(); + } + } + } +} + +void Channel::indicateAway(bool show) +{ + // Qt does not redraw the label properly when they are not on screen + // while getting hidden, so we remember the "soon to be" state here. + if(isHidden()) + { + awayChanged=true; + awayState=show; + } + else + { + if(show) + awayLabel->show(); + else + awayLabel->hide(); + } +} + +void Channel::showEvent(QShowEvent*) +{ + // If the show quick/mode button settings have changed, apply the changes now + if(quickButtonsChanged) + { + quickButtonsChanged=false; + showQuickButtons(quickButtonsState); + } + + if(modeButtonsChanged) + { + modeButtonsChanged=false; + showModeButtons(modeButtonsState); + } + + if(awayChanged) + { + awayChanged=false; + indicateAway(awayState); + } + + syncSplitters(); +} + +void Channel::syncSplitters() +{ + QValueList vertSizes = Preferences::topicSplitterSizes(); + QValueList horizSizes = Preferences::channelSplitterSizes(); + + if (vertSizes.isEmpty()) + { + vertSizes << m_topicButton->height() << (height() - m_topicButton->height()); + Preferences::setTopicSplitterSizes(vertSizes); + } + + if (horizSizes.isEmpty()) + { + int listWidth = nicknameListView->columnWidth(0) + nicknameListView->columnWidth(1); + horizSizes << (width() - listWidth) << listWidth; + Preferences::setChannelSplitterSizes(horizSizes); + } + + m_vertSplitter->setSizes(vertSizes); + m_horizSplitter->setSizes(horizSizes); + + splittersInitialized = true; +} + +void Channel::updateAppearance() +{ + QColor fg,bg,abg; + + if(Preferences::inputFieldsBackgroundColor()) + { + fg=Preferences::color(Preferences::ChannelMessage); + bg=Preferences::color(Preferences::TextViewBackground); + abg=Preferences::color(Preferences::AlternateBackground); + } + else + { + fg=colorGroup().foreground(); + bg=colorGroup().base(); + abg=KGlobalSettings::alternateBackgroundColor(); + } + + channelInput->unsetPalette(); + channelInput->setPaletteForegroundColor(fg); + channelInput->setPaletteBackgroundColor(bg); + + limit->unsetPalette(); + limit->setPaletteForegroundColor(fg); + limit->setPaletteBackgroundColor(bg); + + getTextView()->unsetPalette(); + + if(Preferences::showBackgroundImage()) + { + getTextView()->setViewBackground(Preferences::color(Preferences::TextViewBackground), + Preferences::backgroundImage()); + } + else + { + getTextView()->setViewBackground(Preferences::color(Preferences::TextViewBackground), + QString()); + } + + if (Preferences::customTextFont()) + { + getTextView()->setFont(Preferences::textFont()); + topicLine->setFont(Preferences::textFont()); + channelInput->setFont(Preferences::textFont()); + nicknameCombobox->setFont(Preferences::textFont()); + limit->setFont(Preferences::textFont()); + } + else + { + getTextView()->setFont(KGlobalSettings::generalFont()); + topicLine->setFont(KGlobalSettings::generalFont()); + channelInput->setFont(KGlobalSettings::generalFont()); + nicknameCombobox->setFont(KGlobalSettings::generalFont()); + limit->setFont(KGlobalSettings::generalFont()); + } + + nicknameListView->resort(); + nicknameListView->unsetPalette(); + nicknameListView->setPaletteForegroundColor(fg); + nicknameListView->setPaletteBackgroundColor(bg); + nicknameListView->setAlternateBackground(abg); + + if (Preferences::customListFont()) + nicknameListView->setFont(Preferences::listFont()); + else + nicknameListView->setFont(KGlobalSettings::generalFont()); + + nicknameListView->refresh(); + + showModeButtons(Preferences::showModeButtons()); + showNicknameList(Preferences::showNickList()); + showNicknameBox(Preferences::showNicknameBox()); + showTopic(Preferences::showTopic()); + setAutoUserhost(Preferences::autoUserhost()); + + updateQuickButtons(Preferences::quickButtonList()); + + ChatWindow::updateAppearance(); +} + +void Channel::nicknameComboboxChanged() +{ + QString newNick=nicknameCombobox->currentText(); + oldNick=m_server->getNickname(); + if(oldNick!=newNick) + { + nicknameCombobox->setCurrentText(oldNick); + changeNickname(newNick); + // return focus to input line + channelInput->setFocus(); + } +} + +void Channel::changeNickname(const QString& newNickname) +{ + if (!newNickname.isEmpty()) + m_server->queue("NICK "+newNickname); +} + +void Channel::resetNickList() +{ + nicknameListView->setUpdatesEnabled(false); + purgeNicks(); +} + +void Channel::addPendingNickList(const QStringList& pendingChannelNickList) +{ + if(pendingChannelNickList.isEmpty()) + return; + + if (!m_processingTimer) + { + m_processingTimer = new QTimer(this); + connect(m_processingTimer, SIGNAL(timeout()), this, SLOT(processPendingNicks())); + } + + m_pendingChannelNickLists.append(pendingChannelNickList); + + if (!m_processingTimer->isActive()) + m_processingTimer->start(0); +} + +void Channel::childAdjustFocus() +{ + channelInput->setFocus(); + refreshModeButtons(); +} + +void Channel::refreshModeButtons() +{ + bool enable = true; + if(getOwnChannelNick()) + { + enable=getOwnChannelNick()->isAnyTypeOfOp(); + } // if not channel nick, then enable is true - fall back to assuming they are op + + //don't disable the mode buttons since you can't then tell if they are enabled or not. + //needs to be fixed somehow + + /* modeT->setEnabled(enable); + modeN->setEnabled(enable); + modeS->setEnabled(enable); + modeI->setEnabled(enable); + modeP->setEnabled(enable); + modeM->setEnabled(enable); + modeK->setEnabled(enable); + modeL->setEnabled(enable);*/ + limit->setEnabled(enable); + + // Tooltips for the ModeButtons + QString opOnly; + if(!enable) opOnly = i18n("You have to be an operator to change this."); + + QToolTip::add(modeT, i18n("Topic can be changed by channel operator only. %1").arg(opOnly)); + QToolTip::add(modeN, i18n("No messages to channel from clients on the outside. %1").arg(opOnly)); + QToolTip::add(modeS, i18n("Secret channel. %1").arg(opOnly)); + QToolTip::add(modeI, i18n("Invite only channel. %1").arg(opOnly)); + QToolTip::add(modeP, i18n("Private channel. %1").arg(opOnly)); + QToolTip::add(modeM, i18n("Moderated channel. %1").arg(opOnly)); + QToolTip::add(modeK, i18n("Protect channel with a password.")); + QToolTip::add(modeL, i18n("Set user limit to channel.")); + +} + +void Channel::cycleChannel() +{ + closeYourself(); + m_server->sendJoinCommand(getName(), getPassword()); +} + +void Channel::autoUserhost() +{ + if(Preferences::autoUserhost() && !Preferences::autoWhoContinuousEnabled()) + { + int limit = 5; + + QString nickString; + QPtrList nickList = getNickList(); + QPtrListIterator it(nickList); + Nick* nick; + + while((nick = it.current()) != 0) + { + if(nick->getChannelNick()->getHostmask().isEmpty()) + { + if(limit--) nickString = nickString + nick->getChannelNick()->getNickname() + ' '; + else break; + } + + ++it; + } + + if(!nickString.isEmpty()) m_server->requestUserhost(nickString); + } +} + +void Channel::setAutoUserhost(bool state) +{ + if(state) + { + // we can't have automatic resizing with three columns; the hostname column is too wide + nicknameListView->setHScrollBarMode(QScrollView::Auto); + + // restart userhost timer + userhostTimer.start(10000); + // if the column was actually gone (just to be sure) ... + if(nicknameListView->columns()==2) + { + // re-add the hostmask column + nicknameListView->addColumn(QString()); + nicknameListView->setColumnWidthMode(2,KListView::Maximum); + nicknameListView->setResizeMode(QListView::NoColumn); + + // re-add already known hostmasks + QListViewItem* item=nicknameListView->itemAtIndex(0); + while(item) + { + Nick* lookNick=getNickByName(item->text(1)); + if(lookNick) item->setText(2,lookNick->getChannelNick()->getHostmask()); + item=item->itemBelow(); + } + } + } + else + { + userhostTimer.stop(); + if(nicknameListView->columns()==3) nicknameListView->removeColumn(2); + nicknameListView->setHScrollBarMode(QScrollView::AlwaysOff); + // make the nick column resize itself automatically to prevent horizontal scrollbar + nicknameListView->setResizeMode(QListView::LastColumn); + } +} + +void Channel::scheduleAutoWho() // slot +{ + if(m_whoTimer.isActive()) + m_whoTimer.stop(); + if(Preferences::autoWhoContinuousEnabled()) + m_whoTimer.start(Preferences::autoWhoContinuousInterval() * 1000, true); +} + +void Channel::autoWho() +{ + // don't use auto /WHO when the number of nicks is too large, or get banned. + if((nicks > Preferences::autoWhoNicksLimit()) || + m_server->getInputFilter()->isWhoRequestUnderProcess(getName())) + { + scheduleAutoWho(); + return; + } + + m_server->requestWho(getName()); +} + +void Channel::fadeActivity() +{ + QPtrListIterator it( nicknameList ); + Nick *nick; + while ( (nick = it.current()) != 0 ) { + ++it; + nick->getChannelNick()->lessActive(); + } +} + +QString Channel::getTextInLine() +{ + return channelInput->text(); +} + +bool Channel::canBeFrontView() +{ + return true; +} + +bool Channel::searchView() +{ + return true; +} + +void Channel::appendInputText(const QString& s, bool fromCursor) +{ + if(!fromCursor) + { + channelInput->append(s); + } + else + { + int para = 0, index = 0; + channelInput->getCursorPosition(¶, &index); + channelInput->insertAt(s, para, index); + channelInput->setCursorPosition(para, index + s.length()); + } +} + +bool Channel::closeYourself(bool confirm) +{ + int result=KMessageBox::Continue; + if (confirm) + result = KMessageBox::warningContinueCancel(this, i18n("Do you want to leave %1?").arg(getName()), + i18n("Leave Channel"), i18n("Leave"), "QuitChannelTab"); + + if (result==KMessageBox::Continue) + { + m_server->closeChannel(getName()); + m_server->removeChannel(this); + Preferences::setSpellChecking(channelInput->checkSpellingEnabled()); + deleteLater(); + return true; + } + return false; +} + +void Channel::serverOnline(bool online) +{ + setActive(online); +} + +//Used to disable functions when not connected, does not necessarily mean the server is offline +void Channel::setActive(bool active) +{ + if (active) + { + getTextView()->setNickAndChannelContextMenusEnabled(true); + nicknameCombobox->setEnabled(true); + } + else + { + purgeNicks(); + getTextView()->setNickAndChannelContextMenusEnabled(false); + nicknameCombobox->setEnabled(false); + topicLine->setText(QString::null); + clearModeList(); + clearBanList(); + } +} + +void Channel::showTopic(bool show) +{ + if(show) + { + topicSplitterHidden = false; + topicLine->show(); + m_topicButton->show(); + topicLine->parentWidget()->show(); + } + else + { + topicLine->hide(); + m_topicButton->hide(); + + if(modeBox->isHidden()) + { + topicSplitterHidden = true; + topicLine->parentWidget()->hide(); + } + } +} + +void Channel::processPendingNicks() +{ + QString nickname = m_pendingChannelNickLists.first()[m_currentIndex]; + + bool admin = false; + bool owner = false; + bool op = false; + bool halfop = false; + bool voice = false; + + // Remove possible mode characters from nickname and store the resulting mode + m_server->mangleNicknameWithModes(nickname, admin, owner, op, halfop, voice); + + // TODO: make these an enumeration in KApplication or somewhere, we can use them as well + unsigned int mode = (admin ? 16 : 0) + + (owner ? 8 : 0) + + (op ? 4 : 0) + + (halfop ? 2 : 0) + + (voice ? 1 : 0); + + // Check if nick is already in the nicklist + if (!getNickByName(nickname)) + { + ChannelNickPtr nick = m_server->addNickToJoinedChannelsList(getName(), nickname); + Q_ASSERT(nick); + nick->setMode(mode); + + fastAddNickname(nick); + + if (nick->isAdmin() || nick->isOwner() || nick->isOp() || nick->isHalfOp()) + m_opsToAdd++; + + m_currentIndex++; + } + else + { + m_pendingChannelNickLists.first().pop_front(); + } + + if (m_pendingChannelNickLists.first().count() <= m_currentIndex) + { + adjustNicks(m_pendingChannelNickLists.first().count()); + adjustOps(m_opsToAdd); + m_pendingChannelNickLists.pop_front(); + m_currentIndex = 0; + m_opsToAdd = 0; + } + + if (m_pendingChannelNickLists.isEmpty()) + { + m_processingTimer->stop(); + nicknameListView->sort(); + sortNickList(); + nicknameListView->setUpdatesEnabled(true); + nicknameListView->triggerUpdate(); + } +} + +void Channel::setChannelEncoding(const QString& encoding) // virtual +{ + Preferences::setChannelEncoding(m_server->getDisplayName(), getName(), encoding); +} + +QString Channel::getChannelEncoding() // virtual +{ + return Preferences::channelEncoding(m_server->getDisplayName(), getName()); +} + +QString Channel::getChannelEncodingDefaultDesc() // virtual +{ + return i18n("Identity Default ( %1 )").arg(getServer()->getIdentity()->getCodecName()); +} + +void Channel::showNicknameBox(bool show) +{ + if(show) + { + nicknameCombobox->show(); + } + else + { + nicknameCombobox->hide(); + } +} + +void Channel::showNicknameList(bool show) +{ + if (show) + { + channelSplitterHidden = false; + nickListButtons->show(); + } + else + { + channelSplitterHidden = true; + nickListButtons->hide(); + } +} + +void Channel::requestNickListSort() +{ + if(!m_delayedSortTimer) + { + m_delayedSortTimer = new QTimer(this); + connect(m_delayedSortTimer, SIGNAL(timeout()), this, SLOT(sortNickList())); + } + + if(!m_delayedSortTimer->isActive()) + { + m_delayedSortTimer->start(1000, true); + } +} + +void Channel::sortNickList() +{ + nicknameList.sort(); + nicknameListView->resort(); + + if(m_delayedSortTimer) + { + m_delayedSortTimer->stop(); + } +} + +void Channel::setIdentity(const IdentityPtr identity) +{ + if (identity) + { + nicknameCombobox->clear(); + nicknameCombobox->insertStringList(identity->getNicknameList()); + } +} + +bool Channel::eventFilter(QObject* watched, QEvent* e) +{ + if((watched == nicknameListView) && (e->type() == QEvent::Resize) && splittersInitialized && isShown()) + { + if (!topicSplitterHidden && !channelSplitterHidden) + { + Preferences::setChannelSplitterSizes(m_horizSplitter->sizes()); + Preferences::setTopicSplitterSizes(m_vertSplitter->sizes()); + } + if (!topicSplitterHidden && channelSplitterHidden) + { + Preferences::setTopicSplitterSizes(m_vertSplitter->sizes()); + } + if (!channelSplitterHidden && topicSplitterHidden) + { + Preferences::setChannelSplitterSizes(m_horizSplitter->sizes()); + } + } + + return ChatWindow::eventFilter(watched, e); +} + +void Channel::addBan(const QString& ban) +{ + for ( QStringList::Iterator it = m_BanList.begin(); it != m_BanList.end(); ++it ) + { + if ((*it).section(' ', 0, 0) == ban.section(' ', 0, 0)) + { + // Ban is already in list. + it = m_BanList.remove(it); + + emit banRemoved(ban.section(' ', 0, 0)); + } + } + + m_BanList.prepend(ban); + + emit banAdded(ban); +} + +void Channel::removeBan(const QString& ban) +{ + for ( QStringList::Iterator it = m_BanList.begin(); it != m_BanList.end(); ++it ) + { + if ((*it).section(' ', 0, 0) == ban) + { + it = m_BanList.remove(it); + + emit banRemoved(ban); + } + } +} + +void Channel::clearBanList() +{ + m_BanList.clear(); + + emit banListCleared(); +} + +void Channel::append(const QString& nickname, const QString& message) +{ + if(nickname != getServer()->getNickname()) { + Nick* nick = getNickByName(nickname); + + if(nick) { + nick->getChannelNick()->setTimeStamp(QDateTime::currentDateTime().toTime_t()); + } + } + + ChatWindow::append(nickname, message); + nickActive(nickname); +} + +void Channel::appendAction(const QString& nickname, const QString& message) +{ + if(nickname != getServer()->getNickname()) { + Nick* nick = getNickByName(nickname); + + if(nick) { + nick->getChannelNick()->setTimeStamp(QDateTime::currentDateTime().toTime_t()); + } + } + + ChatWindow::appendAction(nickname, message); + nickActive(nickname); +} + +void Channel::nickActive(const QString& nickname) //FIXME reported to crash, can't reproduce +{ + ChannelNickPtr nick=getChannelNick(nickname); + //XXX Would be nice to know why it can be null here... + if (nick) { + nick->moreActive(); + sortNickList(); //FIXME: no need to completely resort, we can just see if this particular nick should move + } +} + +// +// NickList +// + +NickList::NickList() : QPtrList() +{ + m_compareMethod = NickList::AlphaNumeric; +} + +void NickList::setCompareMethod(CompareMethod method) +{ + m_compareMethod = method; +} + +//doesn't the following somehow duplicate NickListViewItem::compare()? +int NickList::compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2) +{ + if(m_compareMethod == NickList::TimeStamp) { + int returnValue = static_cast(item2)->getChannelNick()->timeStamp() - static_cast(item1)->getChannelNick()->timeStamp(); + + if(returnValue == 0) { + returnValue = QString::compare(static_cast(item1)->getChannelNick()->loweredNickname(), + static_cast(item2)->getChannelNick()->loweredNickname()); + } + + return returnValue; + } + + return QString::compare(static_cast(item1)->getChannelNick()->loweredNickname(), + static_cast(item2)->getChannelNick()->loweredNickname()); +} + +QString NickList::completeNick(const QString& pattern, bool& complete, QStringList& found, + bool skipNonAlfaNum, bool caseSensitive) +{ + found.clear(); + QString prefix = "^"; + QString newNick; + QString prefixCharacter = Preferences::prefixCharacter(); + NickList foundNicks; + foundNicks.setCompareMethod(NickList::TimeStamp); + + if((pattern.find(QRegExp("^(\\d|\\w)")) != -1) && skipNonAlfaNum) + { + prefix = "^([^\\d\\w]|[\\_]){0,}"; + } + + QRegExp regexp(prefix + QRegExp::escape(pattern)); + regexp.setCaseSensitive(caseSensitive); + QPtrListIterator it(*this); + + while(it.current() != 0) + { + newNick = it.current()->getChannelNick()->getNickname(); + + if(!prefix.isEmpty() && newNick.contains(prefixCharacter)) + { + newNick = newNick.section( prefixCharacter,1 ); + } + + if(newNick.find(regexp) != -1) + { + foundNicks.append(it.current()); + } + + ++it; + } + + foundNicks.sort(); + + QPtrListIterator it2(foundNicks); + + while(it2.current() != 0) + { + found.append(it2.current()->getChannelNick()->getNickname()); + ++it2; + } + + if(found.count() > 1) + { + bool ok = true; + unsigned int patternLength = pattern.length(); + QString firstNick = found[0]; + unsigned int firstNickLength = firstNick.length(); + unsigned int foundCount = found.count(); + + while(ok && ((patternLength) < firstNickLength)) + { + ++patternLength; + QStringList tmp = found.grep(firstNick.left(patternLength), caseSensitive); + + if(tmp.count() != foundCount) + { + ok = false; + --patternLength; + } + } + + complete = false; + return firstNick.left(patternLength); + } + else if(found.count() == 1) + { + complete = true; + return found[0]; + } + + return QString(); +} + +bool NickList::containsNick(const QString& nickname) +{ + QPtrListIterator it(*this); + + while (it.current() != 0) + { + if (it.current()->getChannelNick()->getNickname()==nickname) + return true; + + ++it; + } + + return false; +} + +#include "channel.moc" + +// kate: space-indent on; tab-width 4; indent-width 4; mixed-indent off; replace-tabs on; +// vim: set et sw=4 ts=4 cino=l1,cs,U1: diff --git a/konversation/src/channel.h b/konversation/src/channel.h new file mode 100644 index 0000000..e04d52b --- /dev/null +++ b/konversation/src/channel.h @@ -0,0 +1,375 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2004-2006 Peter Simonsson + Copyright (C) 2006-2008 Eike Hein +*/ + +#ifndef CHANNEL_H +#define CHANNEL_H + +#include "server.h" +#include "chatwindow.h" +#include "channelnick.h" +#include "nick.h" + +#include +#include + + +class QPushButton; +class QCheckBox; +class QLabel; +class QTimer; +class QListViewItem; +class QHBox; +class QStringList; +class QSplitter; +class QGrid; +class QComboBox; +class QDropEvent; +class QToolButton; + +class KLineEdit; + +class NickListView; +class QuickButton; +class ModeButton; +class IRCInput; +class NickChangeDialog; + +namespace Konversation +{ + class TopicLabel; + class ChannelOptionsDialog; +} + +class NickList : public QPtrList +{ + public: + NickList(); + + enum CompareMethod { AlphaNumeric, TimeStamp }; + + QString completeNick(const QString& pattern, bool& complete, QStringList& found, + bool skipNonAlfaNum, bool caseSensitive); + + void setCompareMethod(CompareMethod method); + + bool containsNick(const QString& nickname); + + protected: + virtual int compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2); + + private: + CompareMethod m_compareMethod; +}; + +class Channel : public ChatWindow +{ + Q_OBJECT + + public: + explicit Channel(QWidget* parent, QString name); + ~Channel(); +//META + virtual bool canBeFrontView(); + virtual bool searchView(); + + virtual void append(const QString& nickname,const QString& message); + virtual void appendAction(const QString& nickname,const QString& message); + void nickActive(const QString& nickname); + +//General administrative stuff + public: + void setName(const QString& newName); + QString getPassword(); + + const Konversation::ChannelSettings channelSettings(); + + QString getPassword() const; + + virtual void setServer(Server* newServer); + void setIdentity(const IdentityPtr identity); + + void setEncryptedOutput(bool); + + bool joined() { return m_joined; } + bool rejoinable(); +//Unsure of future placement and/or continued existence of these members + int numberOfNicks() const { return nicks; } + int numberOfOps() const { return ops; } + virtual void setChannelEncoding(const QString& encoding); + virtual QString getChannelEncoding(); + virtual QString getChannelEncodingDefaultDesc(); + virtual bool isInsertSupported() { return true; } + + protected: + // use with caution! does not check for duplicates + void fastAddNickname(ChannelNickPtr channelnick); + void setActive(bool active); + + public slots: + void setNickname(const QString& newNickname); + void scheduleAutoWho(); + void setAutoUserhost(bool state); + void rejoin(); + + protected slots: + void autoUserhost(); + void autoWho(); + void fadeActivity(); + virtual void serverOnline(bool online); + + +//Nicklist + public: + ChannelNickPtr getOwnChannelNick(); + ChannelNickPtr getChannelNick(const QString &ircnick); + + void joinNickname(ChannelNickPtr channelNick); + void removeNick(ChannelNickPtr channelNick, const QString &reason, bool quit); + void kickNick(ChannelNickPtr channelNick, const QString &kicker, const QString &reason); + void addNickname(ChannelNickPtr channelNick); + void nickRenamed(const QString &oldNick, const NickInfo& channelnick); + void resetNickList(); + void addPendingNickList(const QStringList& pendingChannelNickList); + Nick *getNickByName(const QString& lookname); + NickList getNickList() { return nicknameList; } + + void adjustNicks(int value); + void adjustOps(int value); + virtual void emitUpdateInfo(); + + protected slots: + void purgeNicks(); + void processPendingNicks(); + +//Topic + public: + /** Get the current channel topic. + * + * The topic may or may not have the author that set it at the start of the string, + * like: " topic" + * + * The internal variable topicAuthorUnknown stores whether the "" bit is there or not. + * + * */ + QString getTopic(); + /** Get the channel topic history sorted in reverse chronological order. + * + * Each topic may or may not have the author that set it at the start of the string, + * like: " topic" + * + * @return a list of topics this channel used to have, current at the top. + */ + QStringList getTopicHistory(); + + void setTopic(const QString& topic); + void setTopic(const QString& nickname, const QString& topic); + void setTopicAuthor(const QString& author, QDateTime t); + + signals: + void topicHistoryChanged(); + void joined(Channel* channel); + + +//Modes +//TODO: the only representation of the channel limit is held in the GUI + + public: + /// Internal - Empty the modelist + void clearModeList(); + /// Get the list of modes that this channel has - e.g. {+l,+s,-m} + //TODO: does this method return a list of all modes, all modes that have been changed, or all modes that are +? + QStringList getModeList() const { return m_modeList; } + + /** Outputs a message on the channel, and modifies the mode for a ChannelNick. + * @param sourceNick The server or the nick of the person that made the mode change. + * @param mode The mode that is changing one of v,h,o,a for voice halfop op admin + * @param plus True if the mode is being granted, false if it's being taken away. + * @param parameter This depends on what the mode change is. In most cases it is the nickname of the person that is being given voice/op/admin etc. See the code. + */ + void updateMode(const QString& sourceNick, char mode, bool plus, const QString ¶meter); + + signals: + void modesChanged(); + +//Bans + public: + + void addBan(const QString& ban); + void removeBan(const QString& ban); + + void clearBanList(); + QStringList getBanList() const { return m_BanList; } + + signals: + void banAdded(const QString& newban); + void banRemoved(const QString& newban); + void banListCleared(); + +//Generic GUI + public: + virtual bool eventFilter(QObject* watched, QEvent* e); + +//Specific GUI + public: + void updateModeWidgets(char mode, bool plus, const QString ¶meter); + void updateQuickButtons(const QStringList &newButtonList); + + /// Get the contents of the input line. + virtual QString getTextInLine(); + /// Sounds suspiciously like a destructor.. + virtual bool closeYourself(bool askForConfirmation=true); + + bool autoJoin(); + + ChannelNickList getSelectedChannelNicks(); + ///TODO: this looks like a half-arsed overload. + QStringList getSelectedNickList(); + + NickListView* getNickListView() const { return nicknameListView; } + + Konversation::ChannelSettings channelSettings() const; + + signals: + void sendFile(); + + public slots: + void updateAppearance(); + void channelTextEntered(); + void channelPassthroughCommand(); + void sendChannelText(const QString& line); + void showOptionsDialog(); + void showQuickButtons(bool show); + void showModeButtons(bool show); + + void appendInputText(const QString& s, bool fromCursor); + virtual void indicateAway(bool show); + void showTopic(bool show); + void showNicknameBox(bool show); + void showNicknameList(bool show); + + void setAutoJoin(bool autojoin); + + void connectionStateChanged(Server*, Konversation::ConnectionState); + + protected slots: + void completeNick(); ///< I guess this is a GUI function, might be nice to have at DCOP level though --argonel + void endCompleteNick(); + void filesDropped(QDropEvent* e); + void quickButtonClicked(const QString& definition); + void modeButtonClicked(int id,bool on); + void channelLimitChanged(); + + void popupChannelCommand(int id); ///< Connected to IRCView::popupCommand() + void popupCommand(int id); ///< Connected to NickListView::popupCommand() + void doubleClickCommand(QListViewItem*); ///< Connected to NickListView::doubleClicked() + // Dialogs + void changeNickname(const QString& newNickname); + + void textPasted(const QString& text); ///< connected to IRCInput::textPasted() - used to handle large/multiline pastings + + void sendFileMenu(); ///< connected to IRCInput::sendFile() + void nicknameComboboxChanged(); + /// Enable/disable the mode buttons depending on whether you are op or not. + void refreshModeButtons(); + +//only the GUI cares about sorted nicklists + ///Request a delayed nicklist sorting + void requestNickListSort(); + ///Sort the nicklist + void sortNickList(); + + protected: + void showEvent(QShowEvent* event); + void syncSplitters(); + /// Called from ChatWindow adjustFocus + virtual void childAdjustFocus(); + /// Close the channel then come back in + void cycleChannel(); ///< TODO this is definately implemented and hooked incorrectly. + + bool channelCommand;///< True if nick context menu is executed from IRCView + + // to take care of redraw problem if hidden + bool quickButtonsChanged; + bool quickButtonsState; + bool modeButtonsChanged; + bool modeButtonsState; + bool awayChanged; + bool awayState; + bool splittersInitialized; + bool topicSplitterHidden; + bool channelSplitterHidden; + + unsigned int completionPosition; + + QSplitter* m_horizSplitter; + QSplitter* m_vertSplitter; + QWidget* topicWidget; + QToolButton* m_topicButton; + Konversation::TopicLabel* topicLine; + + //TODO: abstract these + QHBox* modeBox; + ModeButton* modeT; + ModeButton* modeN; + ModeButton* modeS; + ModeButton* modeI; + ModeButton* modeP; + ModeButton* modeM; + ModeButton* modeK; + ModeButton* modeL; + + KLineEdit* limit; //TODO: this GUI element is the only storage for the mode + + NickListView* nicknameListView; + QHBox* commandLineBox; + QVBox* nickListButtons; + QGrid* buttonsGrid; + QComboBox* nicknameCombobox; + QString oldNick; ///< GUI + QLabel* awayLabel; + QLabel* blowfishLabel; + IRCInput* channelInput; + + NickChangeDialog* nickChangeDialog; + QPtrList buttonList; + +//Members from here to end are not GUI + bool m_joined; + NickList nicknameList; + QTimer userhostTimer; + + QStringList m_topicHistory; + QStringList m_BanList; + bool topicAuthorUnknown; ///< Stores whether the "" bit is there or not. + + bool m_firstAutoWhoDone; + QTimer m_whoTimer; ///< For continuous auto /WHO + QTimer m_fadeActivityTimer; ///< For the smoothing function used in activity sorting + + QValueList m_pendingChannelNickLists; + int m_opsToAdd; + uint m_currentIndex; + + QTimer* m_processingTimer; + QTimer* m_delayedSortTimer; + + QStringList m_modeList; + ChannelNickPtr m_ownChannelNick; + + bool pendingNicks; ///< are there still nicks to be added by /names reply? + int nicks; ///< How many nicks on the channel + int ops; ///< How many ops on the channel + + Konversation::ChannelOptionsDialog *m_optionsDialog; +}; +#endif diff --git a/konversation/src/channeldialog.cpp b/konversation/src/channeldialog.cpp new file mode 100644 index 0000000..2c07d5f --- /dev/null +++ b/konversation/src/channeldialog.cpp @@ -0,0 +1,82 @@ +/* + 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. + + copyright: (C) 2004 by Peter Simonsson + email: psn@linux.se +*/ + +#include "channeldialog.h" +#include "servergroupsettings.h" + +#include +#include +#include +#include + +#include +#include + + +namespace Konversation +{ + + ChannelDialog::ChannelDialog(const QString& title, QWidget *parent, const char *name) + : KDialogBase(Plain, title, Ok|Cancel, Ok, parent, name) + { + QFrame* mainWidget = plainPage(); + QGridLayout* mainLayout = new QGridLayout(mainWidget, 1, 2, 0, spacingHint()); + + QLabel* channelLbl = new QLabel(i18n("C&hannel:"), mainWidget); + m_channelEdit = new QLineEdit(mainWidget); + m_channelEdit->setMaxLength(50); + channelLbl->setBuddy(m_channelEdit); + + QLabel* passwordLbl = new QLabel(i18n("Pass&word:"), mainWidget); + m_passwordEdit = new QLineEdit(mainWidget); + m_passwordEdit->setEchoMode(QLineEdit::Password); + passwordLbl->setBuddy(m_passwordEdit); + + mainLayout->addWidget(channelLbl, 0, 0); + mainLayout->addWidget(m_channelEdit, 0, 1); + mainLayout->addWidget(passwordLbl, 1, 0); + mainLayout->addWidget(m_passwordEdit, 1, 1); + + m_channelEdit->setFocus(); + } + + ChannelDialog::~ChannelDialog() + { + } + + void ChannelDialog::setChannelSettings(const ChannelSettings& channel) + { + m_channelEdit->setText(channel.name()); + m_passwordEdit->setText(channel.password()); + } + + ChannelSettings ChannelDialog::channelSettings() + { + ChannelSettings channel; + channel.setName(m_channelEdit->text()); + channel.setPassword(m_passwordEdit->text()); + + return channel; + } + + void ChannelDialog::slotOk() + { + if (m_channelEdit->text().isEmpty()) + { + KMessageBox::error(this, i18n("The channel name is required.")); + } + else + { + accept(); + } + } +} + +#include "channeldialog.moc" diff --git a/konversation/src/channeldialog.h b/konversation/src/channeldialog.h new file mode 100644 index 0000000..7af0195 --- /dev/null +++ b/konversation/src/channeldialog.h @@ -0,0 +1,46 @@ +/* + 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. +*/ + +/* + copyright: (C) 2004 by Peter Simonsson + email: psn@linux.se +*/ +#ifndef KONVERSATIONCHANNELDIALOG_H +#define KONVERSATIONCHANNELDIALOG_H + +#include + + +class QLineEdit; + +namespace Konversation +{ + + class ChannelSettings; + + class ChannelDialog : public KDialogBase + { + Q_OBJECT + + public: + explicit ChannelDialog(const QString& title, QWidget *parent = 0, const char *name = 0); + ~ChannelDialog(); + + void setChannelSettings(const ChannelSettings& channel); + ChannelSettings channelSettings(); + + protected slots: + void slotOk(); + + private: + QLineEdit* m_channelEdit; + QLineEdit* m_passwordEdit; + + }; + +} +#endif diff --git a/konversation/src/channellistpanel.cpp b/konversation/src/channellistpanel.cpp new file mode 100644 index 0000000..3b20d57 --- /dev/null +++ b/konversation/src/channellistpanel.cpp @@ -0,0 +1,597 @@ +/* + 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. +*/ + +/* + Shows the list of channels + begin: Die Apr 29 2003 + copyright: (C) 2003 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include "channellistpanel.h" +#include "channel.h" +#include "channellistviewitem.h" +#include "server.h" +#include "common.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +ChannelListPanel::ChannelListPanel(QWidget* parent) : ChatWindow(parent) +{ + setType(ChatWindow::ChannelList); + setName(i18n("Channel List")); + + m_oldSortColumn = 0; + + setNumChannels(0); + setNumUsers(0); + setVisibleChannels(0); + setVisibleUsers(0); + + setMinUsers(0); + setMaxUsers(0); + + setChannelTarget(true); + setTopicTarget(false); + setRegExp(false); + + filterTextChanged(QString()); + + QHGroupBox* filterGroup=new QHGroupBox(i18n("Filter Settings"),this); + QGrid* mainGrid=new QGrid(2,Qt::Vertical,filterGroup); + mainGrid->setSpacing(spacing()); + + QLabel* minLabel=new QLabel(i18n("Minimum users:"),mainGrid); + QLabel* maxLabel=new QLabel(i18n("Maximum users:"),mainGrid); + QSpinBox* minUsersSpin=new QSpinBox(0, 9999, 1, mainGrid,"min_users_spin"); + QWhatsThis::add(minUsersSpin, i18n("You can limit the channel list to those channels with a minimum number of users here. Choosing 0 disables this criterion.")); + QSpinBox* maxUsersSpin=new QSpinBox(0, 9999, 1, mainGrid,"max_users_spin"); + QWhatsThis::add(maxUsersSpin, i18n("You can limit the channel list to those channels with a maximum number of users here. Choosing 0 disables this criterion.")); + minUsersSpin->setValue(getMinUsers()); + maxUsersSpin->setValue(getMaxUsers()); + minLabel->setBuddy(minUsersSpin); + maxLabel->setBuddy(maxUsersSpin); + + QLabel* patternLabel=new QLabel(i18n("Filter pattern:"),mainGrid); + new QLabel(i18n("Filter target:"),mainGrid); + + filterInput=new KLineEdit(mainGrid,"channel_list_filter_input"); + QWhatsThis::add(filterInput, i18n("Enter a filter string here.")); + filterInput->setText(getFilterText()); + + patternLabel->setBuddy(filterInput); + + QHBox* targetBox=new QHBox(mainGrid); + targetBox->setSpacing(spacing()); + + channelFilter=new QCheckBox(i18n("Channel"),targetBox,"filter_target_channel_check"); + topicFilter=new QCheckBox(i18n("Topic"),targetBox,"filter_target_topic_check"); + regexpCheck=new QCheckBox(i18n("Regular expression"),targetBox,"regexp_check"); + applyFilter=new QPushButton(i18n("Apply Filter"),targetBox,"apply_filter_button"); + QWhatsThis::add(applyFilter, i18n("Click here to retrieve the list of channels from the server and apply the filter.")); + + channelFilter->setChecked(getChannelTarget()); + topicFilter->setChecked(getTopicTarget()); + regexpCheck->setChecked(getRegExp()); + + targetBox->setStretchFactor(topicFilter,10); + + channelListView=new KListView(this,"channel_list_view"); + QWhatsThis::add(channelListView, i18n("The filtered list of channels is displayed here. Notice that if you do not use regular expressions, Konversation lists any channel whose name contains the filter string you entered. The channel name does not have to start with the string you entered.\n\nSelect a channel you want to join by clicking on it. Right click on the channel to get a list of all web addresses mentioned in the channel's topic.")); + channelListView->addColumn(i18n("Channel Name")); + channelListView->addColumn(i18n("Users")); + channelListView->addColumn(i18n("Channel Topic")); + channelListView->setAllColumnsShowFocus(true); + channelListView->setResizeMode( KListView::LastColumn ); + channelListView->setSortColumn(-1); //Disable sorting + + QHBox* statsBox=new QHBox(this); + statsBox->setSpacing(spacing()); + + QLabel* channelsLabel=new QLabel(QString(),statsBox); + QLabel* usersLabel=new QLabel(QString(),statsBox); + + statsBox->setStretchFactor(usersLabel,10); + + QHBox* actionBox=new QHBox(this); + actionBox->setSpacing(spacing()); + + refreshListButton=new QPushButton(i18n("Refresh List"),actionBox,"refresh_list_button"); + QPushButton* saveListButton=new QPushButton(i18n("Save List..."),actionBox,"save_list_button"); + joinChannelButton=new QPushButton(i18n("Join Channel"),actionBox,"join_channel_button"); + QWhatsThis::add(joinChannelButton, i18n("Click here to join the channel. A new tab is created for the channel.")); + + connect(&updateTimer,SIGNAL (timeout()),this,SLOT (updateDisplay())); + + // double click on channel entry joins the channel + connect(channelListView,SIGNAL (doubleClicked(QListViewItem*)), + this,SLOT (joinChannelClicked()) ); + + connect(channelListView,SIGNAL (contextMenu (KListView*, QListViewItem*, const QPoint&) ), + this, SLOT (contextMenu (KListView*, QListViewItem*, const QPoint&)) ); + + connect(minUsersSpin,SIGNAL (valueChanged(int)),this,SLOT(setMinUsers(int)) ); + connect(maxUsersSpin,SIGNAL (valueChanged(int)),this,SLOT(setMaxUsers(int)) ); + connect(this,SIGNAL (adjustMinValue(int)),minUsersSpin,SLOT (setValue(int)) ); + connect(this,SIGNAL (adjustMaxValue(int)),maxUsersSpin,SLOT (setValue(int)) ); + + connect(filterInput,SIGNAL (textChanged(const QString&)),this,SLOT (filterTextChanged(const QString&)) ); + connect(filterInput,SIGNAL (returnPressed()),this,SLOT (applyFilterClicked()) ); + + connect(channelFilter,SIGNAL (clicked()),this,SLOT (channelTargetClicked()) ); + connect(topicFilter,SIGNAL (clicked()),this,SLOT (topicTargetClicked()) ); + connect(regexpCheck,SIGNAL (clicked()),this,SLOT (regExpClicked()) ); + + connect(applyFilter,SIGNAL (clicked()),this,SLOT (applyFilterClicked()) ); + + connect(refreshListButton,SIGNAL (clicked()),this,SLOT (refreshList()) ); + connect(saveListButton,SIGNAL (clicked()),this,SLOT (saveList()) ); + connect(joinChannelButton,SIGNAL (clicked()),this,SLOT (joinChannelClicked()) ); + + connect(this,SIGNAL (updateNumUsers(const QString&)),usersLabel,SLOT (setText(const QString&)) ); + connect(this,SIGNAL (updateNumChannels(const QString&)),channelsLabel,SLOT (setText(const QString&)) ); + + updateUsersChannels(); +} + +ChannelListPanel::~ChannelListPanel() +{ +} + +void ChannelListPanel::refreshList() +{ + channelListView->clear(); + + setNumChannels(0); + setNumUsers(0); + setVisibleChannels(0); + setVisibleUsers(0); + + updateUsersChannels(); + + /* No good idea: If the server is "temporary loaded" they stay disabled :-( + applyFilter->setEnabled(false); + refreshListButton->setEnabled(false); */ + + emit refreshChannelList(); +} + +void ChannelListPanel::saveList() +{ + // Ask user for file name + QString fileName=KFileDialog::getSaveFileName( + QString(), + QString(), + this, + i18n("Save Channel List")); + + if(!fileName.isEmpty()) + { + // first find the longest channel name and nick number for clean table layouting + unsigned int maxChannelWidth=0; + unsigned int maxNicksWidth=0; + + QListViewItem* item = channelListView->firstChild(); + while(item) + { + if(item->isVisible()) + { + if(item->text(0).length()>maxChannelWidth) + { + maxChannelWidth = item->text(0).length(); + } + + if(item->text(1).length()>maxNicksWidth) + { + maxNicksWidth = item->text(1).length(); + } + } + + item = item->nextSibling(); + } + + // now save the list to disk + QFile listFile(fileName); + listFile.open(IO_WriteOnly); + // wrap the file into a stream + QTextStream stream(&listFile); + + QString header(i18n("Konversation Channel List: %1 - %2\n\n") + .arg(m_server->getServerName()) + .arg(QDateTime::currentDateTime().toString())); + + // send header to stream + stream << header; + + item = channelListView->firstChild(); + + while(item) + { + if(item->isVisible()) + { + QString channelName; + channelName.fill(' ',maxChannelWidth); + channelName.replace(0,item->text(0).length(),item->text(0)); + + QString nicksPad; + nicksPad.fill(' ',maxNicksWidth); + QString nicksNum(nicksPad+item->text(1)); + nicksNum=nicksNum.right(maxNicksWidth); + + QString line(channelName+' '+nicksNum+' '+item->text(2)+'\n'); + + // send final line to stream + stream << line; + } + + item = item->nextSibling(); + } + + listFile.close(); + } +} + +void ChannelListPanel::joinChannelClicked() +{ + QListViewItem* item=channelListView->selectedItem(); + if(item) + { + emit joinChannel(item->text(0)); + } +} + +void ChannelListPanel::addToChannelList(const QString& channel,int users,const QString& topic) +{ + pendingChannels.append(channel + ' ' + QString::number(users) + + ' ' + Konversation::removeIrcMarkup(topic)); + + // set internal numbers of channels and users, display will be updated by a timer + setNumChannels(getNumChannels()+1); + setNumUsers(getNumUsers()+users); + + if(!updateTimer.isActive()) + { + updateTimer.start(10); + + if(channelListView->sortColumn() != -1) + m_oldSortColumn = channelListView->sortColumn(); + + channelListView->setSortColumn(-1); //Disable sorting + } +} + +void ChannelListPanel::updateDisplay() +{ + if(!pendingChannels.isEmpty()) + { + // fetch next channel line + QString channelLine = pendingChannels.first(); + // split it up into the single parts we need + QString channel = channelLine.section(' ',0,0); + QString users = channelLine.section(' ',1,1); + QString topic = channelLine.section(' ',2); + ChannelListViewItem* item = new ChannelListViewItem(channelListView, channel, users, topic); + applyFilterToItem(item); + pendingChannels.pop_front(); + } + + if(pendingChannels.isEmpty()) + { + updateTimer.stop(); + updateUsersChannels(); + channelListView->setSortColumn(m_oldSortColumn); //Disable sorting + applyFilter->setEnabled(true); + refreshListButton->setEnabled(true); + } +} + +void ChannelListPanel::filterTextChanged(const QString& newText) +{ + filterText=newText; +} + +int ChannelListPanel::getNumChannels() +{ + return numChannels; +} + +int ChannelListPanel::getNumUsers() +{ + return numUsers; +} + +void ChannelListPanel::setNumChannels(int num) +{ + numChannels=num; +} + +void ChannelListPanel::setNumUsers(int num) +{ + numUsers=num; +} + +int ChannelListPanel::getVisibleChannels() +{ + return visibleChannels; +} + +int ChannelListPanel::getVisibleUsers() +{ + return visibleUsers; +} + +void ChannelListPanel::setVisibleChannels(int num) +{ + visibleChannels=num; +} + +void ChannelListPanel::setVisibleUsers(int num) +{ + visibleUsers=num; +} + +int ChannelListPanel::getMinUsers() +{ + return minUsers; +} + +int ChannelListPanel::getMaxUsers() +{ + return maxUsers; +} + +bool ChannelListPanel::getChannelTarget() +{ + return channelTarget; +} + +bool ChannelListPanel::getTopicTarget() +{ + return topicTarget; +} + +bool ChannelListPanel::getRegExp() +{ + return regExp; +} + +const QString& ChannelListPanel::getFilterText() +{ + return filterText; +} + +void ChannelListPanel::setMinUsers(int num) +{ + minUsers=num; +} + +void ChannelListPanel::setMaxUsers(int num) +{ + maxUsers=num; +} + +void ChannelListPanel::setChannelTarget(bool state) +{ + channelTarget=state; +} + +void ChannelListPanel::setTopicTarget(bool state) +{ + topicTarget=state; +} + +void ChannelListPanel::setRegExp(bool state) +{ + regExp=state; +} + +void ChannelListPanel::channelTargetClicked() +{ + setChannelTarget(channelFilter->state()==2); +} + +void ChannelListPanel::topicTargetClicked() +{ + setTopicTarget(topicFilter->state()==2); +} + +void ChannelListPanel::regExpClicked() +{ + setRegExp(regexpCheck->state()==2); +} + +void ChannelListPanel::applyFilterToItem(QListViewItem* item) +{ + bool visible=true; + + if(getMinUsers() || getMaxUsers()) + { + if(item->text(1).toInt()=getMinUsers() && + item->text(1).toInt()>getMaxUsers())) + visible=false; + } + + if(!getFilterText().isEmpty()) + { + if(getChannelTarget()) + { + if(item->text(0).find(QRegExp(getFilterText(),false,!getRegExp()))==-1) visible=false; + } + + if(getTopicTarget()) + { + if(item->text(2).find(QRegExp(getFilterText(),false,!getRegExp()))==-1) visible=false; + } + } + + item->setVisible(visible); + if(visible) + { + setVisibleUsers(getVisibleUsers()+item->text(1).toInt()); + setVisibleChannels(getVisibleChannels()+1); + } +} + +void ChannelListPanel::applyFilterClicked() +{ + if(!getNumChannels()) + { + refreshList(); + return; + } + else + { + QListViewItem* item = channelListView->firstChild(); + + setVisibleChannels(0); + setVisibleUsers(0); + + while(item) + { + applyFilterToItem(item); + item = item->nextSibling(); + } + + updateUsersChannels(); + } +} + +void ChannelListPanel::updateUsersChannels() +{ + emit updateNumChannels(i18n("Channels: %1 (%2 shown)").arg(getNumChannels()).arg(getVisibleChannels())); + emit updateNumUsers(i18n("Non-unique users: %1 (%2 shown)").arg(getNumUsers()).arg(getVisibleUsers())); +} + +bool ChannelListPanel::closeYourself() +{ + // make the server delete us so server can reset the pointer to us + m_server->closeChannelListPanel(); + return true; +} + +void ChannelListPanel::childAdjustFocus() +{ +} + +void ChannelListPanel::contextMenu (KListView* /* l */, QListViewItem* i, const QPoint& p) +{ + if(!i) return; + + KPopupMenu* showURLmenu = new KPopupMenu(this); + showURLmenu->insertTitle( i18n("Open URL") ); + QString filteredLine(i->text(2)); + + QRegExp pattern("((http://|https://|ftp://|nntp://|news://|gopher://|www\\.|ftp\\.)" + // IP Address + "([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}|" + // Decimal IP address + "[0-9]{1,12}|" + // Standard host name + "[a-z0-9][\\.@%a-z0-9_-]+\\.[a-z]{2,}" + // Port number, path to document + ")(:[0-9]{1,5})?(/[^)>\"'\\s]*)?|" + // eDonkey2000 links need special treatment + "ed2k://\\|([^|]+\\|){4})"); + + pattern.setCaseSensitive(false); + + int pos=0; + while(static_cast(pos) < filteredLine.length()) + { + if(pattern.search(filteredLine,pos)!=-1) + { + // Remember where we found the url + pos=pattern.pos(); + + // Extract url + QString url=pattern.capturedTexts()[0]; + QString href(url); + + // clean up href for browser + if(href.startsWith("www.")) href="http://"+href; + else if(href.startsWith("ftp.")) href="ftp://"+href; + + // Replace all spaces with %20 in href + href.replace(' ', "%20"); + href.replace('&', "&&"); + + // next search begins right after the link + pos+=url.length(); + + // tell the program that we have found a new url + showURLmenu->insertItem(href); + } + else + { + pos++; + } + } + + if (showURLmenu->count()==1) + { + showURLmenu->insertItem(i18n("<>"),5); + showURLmenu->setItemEnabled(5,false); + } + + int selected = showURLmenu->exec(p); + if (selected!=-1) + { + QMenuItem* item = showURLmenu->findItem( selected ); + new KRun(KURL(item->text().replace("&&","&"))); + } + + delete showURLmenu; +} + +void ChannelListPanel::appendInputText(const QString& text, bool fromCursor) +{ + Q_UNUSED(fromCursor); + filterInput->setText(filterInput->text() + text); +} + +//Used to disable functions when not connected +void ChannelListPanel::serverOnline(bool online) +{ + refreshListButton->setEnabled(online); + applyFilter->setEnabled(online); + joinChannelButton->setEnabled(online); +} + +void ChannelListPanel::emitUpdateInfo() +{ + QString info; + info = i18n("Channel List for %1").arg(m_server->getDisplayName()); + emit updateInfo(info); +} + +void ChannelListPanel::setFilter(const QString& filter) +{ + filterInput->setText(filter); +} + +#include "channellistpanel.moc" diff --git a/konversation/src/channellistpanel.h b/konversation/src/channellistpanel.h new file mode 100644 index 0000000..fa51ddf --- /dev/null +++ b/konversation/src/channellistpanel.h @@ -0,0 +1,147 @@ +/* + 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. +*/ + +/* + Shows the list of channels + begin: Die Apr 29 2003 + copyright: (C) 2003 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#ifndef CHANNELLISTPANEL_H +#define CHANNELLISTPANEL_H + +#include "chatwindow.h" + +#include + + +class QCheckBox; +class QStringList; +class QTimer; +class QListView; +class QListViewItem; +class QPushButton; + +class KListView; +class KLineEdit; +class ChannelListViewItem; + +class ChannelListPanel : public ChatWindow +{ + Q_OBJECT + + public: + explicit ChannelListPanel(QWidget* parent); + ~ChannelListPanel(); + + virtual bool closeYourself(); + virtual void emitUpdateInfo(); + + signals: + void refreshChannelList(); + void joinChannel(const QString& channelName); + void adjustMinValue(int num); + void adjustMaxValue(int num); + void updateNumUsers(const QString& num); + void updateNumChannels(const QString& num); + + public slots: + void addToChannelList(const QString& channel,int users,const QString& topic); + + virtual void appendInputText(const QString&, bool fromCursor); + void setFilter(const QString& filter); + + void applyFilterClicked(); + + protected slots: + void refreshList(); + void updateDisplay(); // will be called by a timer to update regularly + void saveList(); + void joinChannelClicked(); + + void setMinUsers(int num); + void setMaxUsers(int num); + + void filterTextChanged(const QString& newText); + void channelTargetClicked(); + void topicTargetClicked(); + void regExpClicked(); + + void contextMenu (KListView* l, QListViewItem* i, const QPoint& p); + + //Used to disable functions when not connected + virtual void serverOnline(bool online); + + protected: + + /** Called from ChatWindow adjustFocus */ + virtual void childAdjustFocus(); + + virtual bool isInsertCharacterSupported() { return true; } + + int getNumChannels(); + int getNumUsers(); + int getVisibleChannels(); + int getVisibleUsers(); + + void setNumChannels(int num); + void setNumUsers(int num); + void setVisibleChannels(int num); + void setVisibleUsers(int num); + + void setChannelTarget(bool state); + bool getChannelTarget(); + + void setTopicTarget(bool state); + bool getTopicTarget(); + + void setRegExp(bool state); + bool getRegExp(); + + int getMinUsers(); + int getMaxUsers(); + + const QString& getFilterText(); + void applyFilterToItem(QListViewItem* item); + + void updateUsersChannels(); + + int numChannels; + int numUsers; + int visibleChannels; + int visibleUsers; + + int minUsers; + int maxUsers; + + bool channelTarget; + bool topicTarget; + + bool regExp; + + // store channels to be inserted in ListView here first + QStringList pendingChannels; + QTimer updateTimer; + + QCheckBox* channelFilter; + QCheckBox* topicFilter; + QCheckBox* regexpCheck; + + QPushButton* applyFilter; + QPushButton* refreshListButton; + QPushButton* joinChannelButton; + + KListView* channelListView; + + KLineEdit* filterInput; + + QString filterText; + + int m_oldSortColumn; +}; +#endif diff --git a/konversation/src/channellistviewitem.cpp b/konversation/src/channellistviewitem.cpp new file mode 100644 index 0000000..fad3eab --- /dev/null +++ b/konversation/src/channellistviewitem.cpp @@ -0,0 +1,40 @@ +/* + 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. +*/ + +/* + item in the channel list + begin: Die Apr 29 2003 + copyright: (C) 2003 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include "channellistviewitem.h" + + +ChannelListViewItem::ChannelListViewItem(KListView* parent, const QString& channel, const QString& users, const QString& topic) +: KListViewItem(parent,channel,users,topic) +{ +} + +ChannelListViewItem::~ChannelListViewItem() +{ +} + +int ChannelListViewItem::compare(QListViewItem* item, int col, bool ascending) const +{ + if(col==1) + { + bool ok; + int i=text(col).toInt(&ok); + if(ok) + { + int j=item->text(col).toInt(&ok); + if(ok) return (ij) ? 1 : 0; + } + } + return KListViewItem::compare(item,col,ascending); +} diff --git a/konversation/src/channellistviewitem.h b/konversation/src/channellistviewitem.h new file mode 100644 index 0000000..28d9437 --- /dev/null +++ b/konversation/src/channellistviewitem.h @@ -0,0 +1,31 @@ +/* + 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. +*/ + +/* + item in the channel list + begin: Die Apr 29 2003 + copyright: (C) 2003 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#ifndef CHANNELLISTVIEWITEM_H +#define CHANNELLISTVIEWITEM_H + +#include + +#include + + +class ChannelListViewItem : public KListViewItem +{ + public: + ChannelListViewItem(KListView* parent, const QString& channel, const QString& users, const QString& topic); + ~ChannelListViewItem(); + + int compare(QListViewItem* item, int col, bool ascending) const; +}; +#endif diff --git a/konversation/src/channelnick.cpp b/konversation/src/channelnick.cpp new file mode 100644 index 0000000..8640acd --- /dev/null +++ b/konversation/src/channelnick.cpp @@ -0,0 +1,259 @@ +/* + 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. +*/ + +/* + begin: Wed Aug 04 2004 + copyright: (C) 2002,2003,2004 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +/* An instance of ChannelNick is made for each nick in each channel. + So for a person in multiple channels, they will have one NickInfo, and multiple ChannelNicks. + It contains a pointer to the NickInfo, and the mode of that person in the channel. +*/ + +#include "channelnick.h" +#include "channel.h" +#include "server.h" + +#include + + +ChannelNick::ChannelNick(const NickInfoPtr& nickInfo, const bool& isop, const bool& isadmin, + const bool& isowner, const bool& ishalfop, const bool& hasvoice) +: KShared() +{ + this->nickInfo = nickInfo; + this->isop = isop; + this->isadmin = isadmin; + this->isowner = isowner; + this->ishalfop = ishalfop; + this->hasvoice = hasvoice; + m_timeStamp = 0; + m_recentActivity = 0; +} + +ChannelNick::~ChannelNick() +{ +} + +bool ChannelNick::isOp() const +{ + return isop; +} + +bool ChannelNick::isAdmin() const +{ + return isadmin; +} + +bool ChannelNick::isOwner() const +{ + return isowner; +} + +bool ChannelNick::isHalfOp() const +{ + return ishalfop; +} + +bool ChannelNick::hasVoice() const +{ + return hasvoice; +} + +bool ChannelNick::isAnyTypeOfOp() const +{ + return isop || isadmin || isowner || ishalfop; +} + +NickInfoPtr ChannelNick::getNickInfo() const +{ + return nickInfo; +} + +/** @param mode 'v' to set voice, 'a' to set admin, 'h' to set halfop, 'o' to set op. + * @param state what to set the mode to. + */ +bool ChannelNick::setMode(char mode, bool state) +{ + switch (mode) + { + case 'q': + return setOwner(state); + case 'a': + return setAdmin(state); + case 'o': + return setOp(state); + case 'h': + return setHalfOp(state); + case 'v': + return setVoice(state); + default: + kdDebug() << "Mode '" << mode << "' not recognised in setModeForChannelNick"; + return false; + } +} + +/** Used still for passing modes from inputfilter to Server. Should be removed. + */ +bool ChannelNick::setMode(int mode) +{ + bool voice = mode%2; + mode >>= 1; + bool halfop = mode %2; + mode >>= 1; + bool op = mode %2; + mode >>= 1; + bool owner = mode %2; + mode >>= 1; + bool admin = mode %2; + return setMode(admin, owner, op, halfop, voice); +} + +bool ChannelNick::setMode(bool admin,bool owner,bool op,bool halfop,bool voice) +{ + if(isadmin==admin && isowner==owner && isop==op && ishalfop==halfop && hasvoice==voice) + return false; + isadmin=admin; + isowner=owner; + isop=op; + ishalfop=halfop; + hasvoice=voice; + nickInfo->getServer()->emitChannelNickChanged(this); + emit channelNickChanged(); + return true; +} + +/** set the voice for the nick, and update + * @returns Whether it needed to be changed. False for no change. + */ +bool ChannelNick::setVoice(bool state) +{ + if(hasvoice==state) return false; + hasvoice=state; + nickInfo->getServer()->emitChannelNickChanged(this); + emit channelNickChanged(); + return true; +} + +bool ChannelNick::setOwner(bool state) +{ + if(isowner==state) return false; + isowner=state; + nickInfo->getServer()->emitChannelNickChanged(this); + emit channelNickChanged(); + return true; +} + +bool ChannelNick::setAdmin(bool state) +{ + if(isadmin==state) return false; + isadmin=state; + nickInfo->getServer()->emitChannelNickChanged(this); + emit channelNickChanged(); + return true; +} + +bool ChannelNick::setHalfOp(bool state) +{ + if(ishalfop==state) return false; + ishalfop=state; + nickInfo->getServer()->emitChannelNickChanged(this); + emit channelNickChanged(); + return true; +} + +bool ChannelNick::setOp(bool state) +{ + if(isop==state) return false; + isop=state; + nickInfo->getServer()->emitChannelNickChanged(this); + emit channelNickChanged(); + return true; +} + +//Purely provided for convience because they are used so often. +//Just calls nickInfo->getNickname() etc +QString ChannelNick::getNickname() const +{ + if ( this ) + return nickInfo->getNickname(); + else + return QString(); +} + +QString ChannelNick::getHostmask() const +{ + if ( this ) + return nickInfo->getHostmask(); + else + return QString(); +} + +QString ChannelNick::tooltip() +{ + // if(addressee.isEmpty()) return QString(); + KABC::Addressee addressee = nickInfo->getAddressee(); + QString strTooltip; + QTextStream tooltip( &strTooltip, IO_WriteOnly ); + + tooltip << ""; + + tooltip << ""; + + nickInfo->tooltipTableData(tooltip); + + QStringList modes; + if(isOp()) modes << i18n("Operator"); + if(isAdmin()) modes << i18n("Admin"); + if(isOwner()) modes << i18n("Owner"); + if(isHalfOp()) modes << i18n("Half-operator"); + if(hasVoice()) modes << i18n("Has voice"); + //Don't show anything if the user is just a normal user + //if(modes.empty()) modes << i18n("A normal user"); + if(!modes.empty()) + { + tooltip << ""; + } + tooltip << "
" << i18n("Mode") << ": " << modes.join(", ") << "
"; + //kdDebug() << strTooltip << endl; + //if(!dirty) return QString(); + return strTooltip; +} + +QString ChannelNick::loweredNickname() const +{ + return nickInfo->loweredNickname(); +} + +uint ChannelNick::timeStamp() const +{ + return m_timeStamp; +} + +uint ChannelNick::recentActivity() const +{ + return m_recentActivity; +} + +void ChannelNick::moreActive() +{ + m_recentActivity++; +} + +void ChannelNick::lessActive() +{ + m_recentActivity--; +} + +void ChannelNick::setTimeStamp(uint stamp) +{ + m_timeStamp = stamp; +} + +#include "channelnick.moc" diff --git a/konversation/src/channelnick.h b/konversation/src/channelnick.h new file mode 100644 index 0000000..a7c5bbc --- /dev/null +++ b/konversation/src/channelnick.h @@ -0,0 +1,95 @@ +/* + 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. +*/ + +/* + channelnick.h - There is an instance of this for each nick in each channel. So for a person in multiple channels, they will have one NickInfo, and multiple ChannelNicks. + begin: Wed Aug 04 2004 + copyright: (C) 2002,2003,2004 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#ifndef CHANNEL_NICK_H +#define CHANNEL_NICK_H + +#include "nickinfo.h" + +#include + + +class ChannelNick : public QObject, public KShared +{ + Q_OBJECT + + public: + ChannelNick(const NickInfoPtr& nickInfo, const bool& isop, const bool& isadmin, + const bool& isowner, const bool& ishalfop, const bool& hasvoice); + ~ChannelNick(); + bool isOp() const; + bool isAdmin() const; + bool isOwner() const; + bool isHalfOp() const; + + /** Return true if the may have any privillages at all + * @return true if isOp() || isAdmin() || isOwner() || isHalfOp() + */ + bool isAnyTypeOfOp() const; + bool hasVoice() const; + uint timeStamp() const; + uint recentActivity() const; + void moreActive(); + + bool setVoice(bool state); + bool setOp(bool state); + bool setHalfOp(bool state); + bool setAdmin(bool state); + bool setOwner(bool state); + bool setMode(char mode, bool plus); + bool setMode(int mode); + bool setMode(bool admin,bool owner,bool op,bool halfop,bool voice); + void setTimeStamp(uint stamp); + + NickInfoPtr getNickInfo() const; + //Purely provided for convenience because they are used so often. + //Just calls nickInfo->getNickname() etc + QString getNickname() const; + QString loweredNickname() const; + QString getHostmask() const; + QString tooltip(); + private: + NickInfoPtr nickInfo; + bool isop; + bool isadmin; + bool isowner; + bool ishalfop; + bool hasvoice; + uint m_timeStamp; + uint m_recentActivity; + + signals: + void channelNickChanged(); + + public slots: + void lessActive(); +}; + +/** A ChannelNickPtr is a pointer to a ChannelNick. Since it is a KSharedPtr, + * the ChannelNick object is automatically destroyed when all references are destroyed. + */ +typedef KSharedPtr ChannelNickPtr; + +/** A ChannelNickMap is a list of ChannelNick pointers, indexed and sorted by + * lowercase nickname. + */ +typedef QMap ChannelNickMap; + +typedef QValueList ChannelNickList; + +/** A ChannelMembershipMap is a list of ChannelNickMap pointers, indexed and + * sorted by lowercase channel name. + */ +typedef QMap ChannelMembershipMap; +#endif /* CHANNEL_NICK_H */ diff --git a/konversation/src/channeloptionsdialog.cpp b/konversation/src/channeloptionsdialog.cpp new file mode 100644 index 0000000..e10f950 --- /dev/null +++ b/konversation/src/channeloptionsdialog.cpp @@ -0,0 +1,537 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005-2007 Peter Simonsson + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006-2007 Eike Hein +*/ + +#include "channeloptionsdialog.h" +#include "konversationapplication.h" +#include "channeloptionsui.h" +#include "channel.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace Konversation +{ + + ChannelOptionsDialog::ChannelOptionsDialog(Channel *channel) + : KDialogBase(channel, "channelOptions", false, i18n("Channel Settings for %1").arg(channel->getName()), Ok|Cancel, Ok) + { + Q_ASSERT(channel); + m_widget = new ChannelOptionsUI(this); + setMainWidget(m_widget); + + m_widget->otherModesList->setRenameable(0, false); + m_widget->otherModesList->setRenameable(1, true); + m_widget->otherModesList->hide(); + + // don't allow sorting. most recent topic is always first + m_widget->topicHistoryList->setSortColumn(-1); + m_widget->clearButton->setIconSet(SmallIconSet("locationbar_erase")); + m_widget->banList->setDefaultRenameAction(QListView::Accept); + m_widget->banListSearchLine->setListView(m_widget->banList); + // hide column where the complete topic will be put in for convenience + m_widget->topicHistoryList->hideColumn(2); + // do not allow the user to resize the hidden column back into view + m_widget->topicHistoryList->header()->setResizeEnabled(false,2); + + m_channel = channel; + m_editingTopic = false; + + connect(m_widget->topicHistoryList, SIGNAL(clicked(QListViewItem*)), this, SLOT(topicHistoryItemClicked(QListViewItem*))); + connect(m_widget->topicHistoryList, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(topicHistoryItemClicked(QListViewItem*))); + connect(m_widget->toggleAdvancedModes, SIGNAL(clicked()), this, SLOT(toggleAdvancedModes())); + connect(m_widget->topicEdit, SIGNAL(modificationChanged(bool)), this, SLOT(topicBeingEdited(bool))); + + connect(m_channel, SIGNAL(topicHistoryChanged()), this, SLOT(refreshTopicHistory())); + + connect(m_channel, SIGNAL(modesChanged()), this, SLOT(refreshModes())); + connect(m_channel->getOwnChannelNick(), SIGNAL(channelNickChanged()), this, SLOT(refreshEnableModes())); + + connect(this, SIGNAL(cancelClicked()), this, SLOT(cancelClicked())); + connect(this, SIGNAL(okClicked()), this, SLOT(changeOptions())); + connect(this, SIGNAL(okClicked()), this, SLOT(okClicked())); + + connect(m_channel, SIGNAL(banAdded(const QString&)), this, SLOT(addBan(const QString&))); + connect(m_channel, SIGNAL(banRemoved(const QString&)), this, SLOT(removeBan(const QString&))); + connect(m_channel, SIGNAL(banListCleared()), m_widget->banList, SLOT(clear())); + + connect(m_widget->addBan, SIGNAL(clicked()), this, SLOT(addBanClicked())); + connect(m_widget->removeBan, SIGNAL(clicked()), this, SLOT(removeBanClicked())); + connect(m_widget->banList, SIGNAL(itemRenamed (QListViewItem*)), this, SLOT(banEdited(QListViewItem*))); + connect(m_widget->banList, SIGNAL(itemRenamed (QListViewItem*, int, const QString&)), this, SLOT(banEdited(QListViewItem*))); + + refreshTopicHistory(); + refreshBanList(); + refreshAllowedChannelModes(); + refreshModes(); + } + + ChannelOptionsDialog::~ChannelOptionsDialog() + { + } + + void ChannelOptionsDialog::changeOptions() + { + QString newTopic = topic(), oldTopic=m_channel->getTopicHistory().first().section(' ', 2); + + if(newTopic != oldTopic) + { + // Pass a ^A so we can determine if we want to clear the channel topic. + if (newTopic.isEmpty()) + { + if (!oldTopic.isEmpty()) + m_channel->sendChannelText(Preferences::commandChar() + "TOPIC " + m_channel->getName() + " \x01"); + } + else + m_channel->sendChannelText(Preferences::commandChar() + "TOPIC " + m_channel->getName() + ' ' + newTopic); + } + + QStringList newModeList = modes(); + QStringList currentModeList = m_channel->getModeList(); + QStringList rmModes; + QStringList addModes; + QStringList tmp; + QString modeString; + bool plus; + QString command("MODE %1 %2%3 %4"); + + for(QStringList::iterator it = newModeList.begin(); it != newModeList.end(); ++it) + { + modeString = (*it).mid(1); + plus = ((*it)[0] == '+'); + tmp = currentModeList.grep(QRegExp('^' + modeString)); + + if(tmp.isEmpty() && plus) + { + m_channel->getServer()->queue(command.arg(m_channel->getName()).arg("+").arg(modeString[0]).arg(modeString.mid(1))); + } + else if(!tmp.isEmpty() && !plus) + { + //FIXME: Bahamuth requires the key parameter for -k, but ircd breaks on -l with limit number. + //Hence two versions of this. + if (modeString[0] == 'k') + m_channel->getServer()->queue(command.arg(m_channel->getName()).arg("-").arg(modeString[0]).arg(modeString.mid(1))); + else + m_channel->getServer()->queue(command.arg(m_channel->getName()).arg("-").arg(modeString[0]).arg("")); + } + } + hide(); + } + + void ChannelOptionsDialog::toggleAdvancedModes() + { + bool ison = m_widget->toggleAdvancedModes->isOn(); + m_widget->otherModesList->setShown(ison); + if(ison) + { + m_widget->toggleAdvancedModes->setText(i18n("&Hide Advanced Modes <<")); + } + else + { + m_widget->toggleAdvancedModes->setText(i18n("&Show Advanced Modes >>")); + } + } + + void ChannelOptionsDialog::topicBeingEdited(bool state) + { + m_editingTopic = state; + } + + QString ChannelOptionsDialog::topic() + { + return m_widget->topicEdit->text().replace("\n"," "); + } + + void ChannelOptionsDialog::refreshTopicHistory() + { + QStringList history = m_channel->getTopicHistory(); + m_widget->topicHistoryList->clear(); + + for(QStringList::const_iterator it = history.fromLast(); it != history.end(); --it) + { + QDateTime date; + date.setTime_t((*it).section(' ', 0 ,0).toUInt()); + new KListViewItem(m_widget->topicHistoryList, (*it).section(' ', 1, 1), date.toString(Qt::LocalDate), (*it).section(' ', 2)); + } + + // update topic preview + topicHistoryItemClicked(m_widget->topicHistoryList->selectedItem()); + // don't destroy the user's edit box if they started editing + if(!m_editingTopic) + m_widget->topicEdit->setText(history.first().section(' ', 2)); + } + + void ChannelOptionsDialog::topicHistoryItemClicked(QListViewItem* item) + { + // if they didn't click on anything, item is null + if(item) + // update topic preview + m_widget->topicPreview->setText(item->text(2)); + else + // clear topic preview + m_widget->topicPreview->setText(""); + } + + void ChannelOptionsDialog::refreshEnableModes() + { + bool enable = m_channel->getOwnChannelNick()->isAnyTypeOfOp(); + m_widget->otherModesList->setEnabled(enable); + m_widget->topicEdit->setReadOnly(!enable && m_widget->topicModeChBox->isChecked()); + + m_widget->topicModeChBox->setEnabled(enable); + m_widget->messageModeChBox->setEnabled(enable); + m_widget->userLimitChBox->setEnabled(enable); + m_widget->userLimitEdit->setEnabled(enable); + m_widget->inviteModeChBox->setEnabled(enable); + m_widget->moderatedModeChBox->setEnabled(enable); + m_widget->secretModeChBox->setEnabled(enable); + m_widget->keyModeChBox->setEnabled(enable); + m_widget->keyModeEdit->setEnabled(enable); + + m_widget->banList->setItemsRenameable(enable); + m_widget->addBan->setEnabled(enable); + m_widget->removeBan->setEnabled(enable); + } + + void ChannelOptionsDialog::refreshAllowedChannelModes() + { + QString modeString = m_channel->getServer()->allowedChannelModes(); + // These modes are handled in a special way: ntimslkbeI + modeString.remove('t'); + modeString.remove('n'); + modeString.remove('l'); + modeString.remove('i'); + modeString.remove('m'); + modeString.remove('s'); + modeString.remove('k'); + modeString.remove('b'); + modeString.remove('e'); + modeString.remove('I'); + modeString.remove('O'); + modeString.remove('o'); + modeString.remove('v'); + + for(unsigned int i = 0; i < modeString.length(); i++) + { + new QCheckListItem(m_widget->otherModesList, QString(modeString[i]), QCheckListItem::CheckBox); + } + } + + void ChannelOptionsDialog::refreshModes() + { + QStringList modes = m_channel->getModeList(); + + m_widget->topicModeChBox->setChecked(false); + m_widget->messageModeChBox->setChecked(false); + m_widget->userLimitChBox->setChecked(false); + m_widget->userLimitEdit->setValue(0); + m_widget->inviteModeChBox->setChecked(false); + m_widget->moderatedModeChBox->setChecked(false); + m_widget->secretModeChBox->setChecked(false); + m_widget->keyModeChBox->setChecked(false); + m_widget->keyModeEdit->setText(""); + + QListViewItem* item = m_widget->otherModesList->firstChild(); + + while(item) + { + static_cast(item)->setOn(false); + item = item->nextSibling(); + } + + char mode; + + for(QStringList::const_iterator it = modes.begin(); it != modes.end(); ++it) + { + mode = (*it)[0]; + + switch(mode) + { + case 't': + m_widget->topicModeChBox->setChecked(true); + break; + case 'n': + m_widget->messageModeChBox->setChecked(true); + break; + case 'l': + m_widget->userLimitChBox->setChecked(true); + m_widget->userLimitEdit->setValue((*it).mid(1).toInt()); + break; + case 'i': + m_widget->inviteModeChBox->setChecked(true); + break; + case 'm': + m_widget->moderatedModeChBox->setChecked(true); + break; + case 's': + m_widget->secretModeChBox->setChecked(true); + break; + case 'k': + m_widget->keyModeChBox->setChecked(true); + m_widget->keyModeEdit->setText((*it).mid(1)); + break; + default: + { + bool found = false; + item = m_widget->otherModesList->firstChild(); + QString modeString; + modeString = mode; + + while(item && !found) + { + if(item->text(0) == modeString) + { + found = true; + static_cast(item)->setOn(true); + item->setText(1, (*it).mid(1)); + } + else + { + item = item->nextSibling(); + } + } + + break; + } + } + } + + refreshEnableModes(); + } + + QStringList ChannelOptionsDialog::modes() + { + QStringList modes; + QString mode; + + mode = (m_widget->topicModeChBox->isChecked() ? "+" : "-"); + mode += 't'; + modes.append(mode); + mode = (m_widget->messageModeChBox->isChecked() ? "+" : "-"); + mode += 'n'; + modes.append(mode); + mode = (m_widget->userLimitChBox->isChecked() ? "+" : "-"); + mode += 'l' + QString::number( m_widget->userLimitEdit->value() ); + modes.append(mode); + mode = (m_widget->inviteModeChBox->isChecked() ? "+" : "-"); + mode += 'i'; + modes.append(mode); + mode = (m_widget->moderatedModeChBox->isChecked() ? "+" : "-"); + mode += 'm'; + modes.append(mode); + mode = (m_widget->secretModeChBox->isChecked() ? "+" : "-"); + mode += 's'; + modes.append(mode); + + if (m_widget->keyModeChBox->isChecked() && !m_widget->keyModeEdit->text().isEmpty()) + { + mode = '+'; + mode += 'k' + m_widget->keyModeEdit->text(); + modes.append(mode); + } + else if (!m_widget->keyModeChBox->isChecked()) + { + mode = '-'; + mode += 'k' + m_widget->keyModeEdit->text(); + modes.append(mode); + } + + QListViewItem* item = m_widget->otherModesList->firstChild(); + + while(item) + { + mode = (static_cast(item)->isOn() ? "+" : "-"); + mode += item->text(0) + item->text(1); + modes.append(mode); + item = item->nextSibling(); + } + + return modes; + } + + // Ban List tab related functions + + void ChannelOptionsDialog::refreshBanList() + { + QStringList banlist = m_channel->getBanList(); + m_widget->banList->clear(); + + for (QStringList::const_iterator it = banlist.fromLast(); it != banlist.end(); --it) + addBan((*it)); + } + + void ChannelOptionsDialog::addBan(const QString& newban) + { + new BanListViewItem(m_widget->banList, newban.section(' ', 0, 0), newban.section(' ', 1, 1).section('!', 0, 0), newban.section(' ', 2 ,2).toUInt()); + } + + void ChannelOptionsDialog::removeBan(const QString& ban) + { + delete m_widget->banList->findItem(ban, 0); + } + + void ChannelOptionsDialog::banEdited(QListViewItem *edited) + { + if (edited == m_NewBan) + { + if (!m_NewBan->text(0).isEmpty()) + { + m_channel->getServer()->requestBan(QStringList(m_NewBan->text(0)), m_channel->getName(), QString()); + } + + // We will delete the item and let the addBan slot handle + // readding the item because for some odd reason using + // startRename causes further attempts to rename the item + // using 2 mouse clicks to fail in odd ways. + delete edited; + + return; + } + + BanListViewItem *new_edited = dynamic_cast (edited); + if (new_edited == NULL) return; // Should not happen. + + if (new_edited->getOldValue() != new_edited->text(0)) + { + m_channel->getServer()->requestUnban(new_edited->getOldValue(), m_channel->getName()); + + if (!new_edited->text(0).isEmpty()) + { + m_channel->getServer()->requestBan(QStringList(new_edited->text(0)), m_channel->getName(), QString()); + } + + // We delete the existing item because it's possible the server may + // Modify the ban causing us not to catch it. If that happens we'll be + // stuck with a stale item and a new item with the modified hostmask. + delete new_edited; + } + } + + void ChannelOptionsDialog::addBanClicked() + { + m_NewBan = new BanListViewItem(m_widget->banList, true); + + m_NewBan->setRenameEnabled(0,true); + m_NewBan->startRename(0); + } + + void ChannelOptionsDialog::removeBanClicked() + { + if (m_widget->banList->currentItem()) + m_channel->getServer()->requestUnban(m_widget->banList->currentItem()->text(0), m_channel->getName()); + } + + void ChannelOptionsDialog::cancelClicked() + { + if (m_widget->banList->renameLineEdit()->isShown()) + { + QKeyEvent e(QEvent::KeyPress, Qt::Key_Escape, 27, Qt::NoButton); + + KApplication::sendEvent(m_widget->banList->renameLineEdit(), &e); + } + + topicBeingEdited(false); + hide(); + } + + void ChannelOptionsDialog::okClicked() + { + if (m_widget->banList->renameLineEdit()->isShown()) + { + QKeyEvent e(QEvent::KeyPress, Qt::Key_Return, 13, Qt::NoButton); + + KApplication::sendEvent(m_widget->banList->renameLineEdit(), &e); + } + } + + // This is our implementation of BanListViewItem + + BanListViewItem::BanListViewItem(QListView *parent) + : KListViewItem(parent) + { + m_isNewBan = 0; + } + + BanListViewItem::BanListViewItem(QListView *parent, bool isNew) + : KListViewItem(parent) + { + m_isNewBan = isNew; + } + + BanListViewItem::BanListViewItem (QListView *parent, const QString& label1, const QString& label2, + uint timestamp) : KListViewItem(parent, label1, label2) + { + m_isNewBan = 0; + m_timestamp.setTime_t(timestamp); + } + + BanListViewItem::BanListViewItem (QListView *parent, bool isNew, const QString& label1, const QString& label2, + uint timestamp) : KListViewItem(parent, label1, label2) + { + m_isNewBan = isNew; + m_timestamp.setTime_t(timestamp); + } + + QString BanListViewItem::text(int column) const + { + if (column == 2) + return KGlobal::locale()->formatDateTime(m_timestamp, true, true); + + return KListViewItem::text(column); + } + + int BanListViewItem::compare(QListViewItem *i, int col, bool ascending) const + { + if (col == 2) + { + BanListViewItem* item = static_cast(i); + + if (m_timestamp == item->timestamp()) + return 0; + else if (m_timestamp < item->timestamp()) + return -1; + else + return 1; + } + + return KListViewItem::compare(i, col, ascending); + } + + void BanListViewItem::startRename( int col ) + { + m_oldValue = text(col); + + KListViewItem::startRename(col); + } + + void BanListViewItem::cancelRename( int col ) + { + if (text(col).isEmpty() && m_isNewBan) + delete this; + else + KListViewItem::cancelRename(col); + } +} + +#include "channeloptionsdialog.moc" diff --git a/konversation/src/channeloptionsdialog.h b/konversation/src/channeloptionsdialog.h new file mode 100644 index 0000000..b947fee --- /dev/null +++ b/konversation/src/channeloptionsdialog.h @@ -0,0 +1,102 @@ +/* + This program is free software; you can redistribute it and/or modifydvancedModes + 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. +*/ + +/* + copyright: (C) 2004 by Peter Simonsson + email: psn@linux.se +*/ +#ifndef KONVERSATIONCHANNELOPTIONSDIALOG_H +#define KONVERSATIONCHANNELOPTIONSDIALOG_H + +#include "channel.h" + +#include + +#include +#include + + +namespace Konversation +{ + class ChannelOptionsUI; + + class ChannelOptionsDialog : public KDialogBase + { + Q_OBJECT + public: + explicit ChannelOptionsDialog(Channel *channel); + ~ChannelOptionsDialog(); + + QString topic(); + QStringList modes(); + + + public slots: + void refreshTopicHistory(); + void refreshAllowedChannelModes(); + void refreshModes(); + void refreshEnableModes(); + void toggleAdvancedModes(); + + void refreshBanList(); + void addBan(const QString& newban); + void addBanClicked(); + void removeBan(const QString& ban); + void removeBanClicked(); + void banEdited(QListViewItem *edited); + + void changeOptions(); + + + protected slots: + void topicHistoryItemClicked(QListViewItem* item); + void topicBeingEdited(bool state); + + void cancelClicked(); + void okClicked(); + + + protected: + bool m_editingTopic; + QListViewItem *m_NewBan; + + + private: + ChannelOptionsUI* m_widget; + Channel *m_channel; + }; + + + // This is needed to overcome two deficiencies in KListViewItem + // First there is no signal emitted when a rename is canceled + // Second there is no way to get the old value of an item after a rename + class BanListViewItem : public KListViewItem + { + public: + explicit BanListViewItem( QListView *parent ); + BanListViewItem(QListView *parent, bool isNew); + BanListViewItem(QListView *parent, const QString& label1, const QString& label2 = QString(), uint timestamp = 0); + BanListViewItem (QListView *parent, bool isNew, const QString& label1, const QString& label2 = QString(), uint timestamp = 0); + + QString getOldValue() { return m_oldValue; } + QDateTime timestamp() { return m_timestamp; } + + virtual QString text(int column) const; + virtual int compare(QListViewItem *i, int col, bool ascending) const; + virtual void startRename(int col); + + + protected: + virtual void cancelRename(int col); + + QString m_oldValue; + bool m_isNewBan; + QDateTime m_timestamp; + }; + +} +#endif diff --git a/konversation/src/channeloptionsui.ui b/konversation/src/channeloptionsui.ui new file mode 100644 index 0000000..2c2f062 --- /dev/null +++ b/konversation/src/channeloptionsui.ui @@ -0,0 +1,559 @@ + +Konversation::ChannelOptionsUI +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. + +Peter Simonsson + + + Konversation::ChannelOptionsUI + + + + 0 + 0 + 502 + 421 + + + + + unnamed + + + 0 + + + + channelTabWidget + + + + topicTab + + + Topi&c + + + + unnamed + + + + splitter4 + + + Vertical + + + + + Nickname + + + true + + + true + + + + + Date + + + true + + + true + + + + + Topic + + + true + + + true + + + + topicHistoryList + + + + 7 + 7 + 0 + 1 + + + + Single + + + true + + + true + + + false + + + AllColumns + + + true + + + false + + + + + topicPreview + + + true + + + WidgetOrigin + + + true + + + + + + topicEdit + + + + 7 + 7 + 0 + 2 + + + + PlainText + + + + + + + modesPage + + + Mo&des + + + + unnamed + + + + topicModeChBox + + + &Topic can only be changed by channel operators + + + <qt>These control the <em>mode</em> of the channel. Only an operator can change these.<p>The <b>T</b>opic mode means that only the channel operator can change the topic for the channel.</qt> + + + + + messageModeChBox + + + &No messages from outside the channel + + + <qt>These control the <em>mode</em> of the channel. Only an operator can change these.<p><b>N</b>o messages from outside means that users that are not in the channel cannot send messages that everybody in the channel can see. Almost all channels have this set to prevent nuisance messages.</qt> + + + + + secretModeChBox + + + &Secret channel, the channel is not listed in the channel list + + + <qt>These control the <em>mode</em> of the channel. Only an operator can change these.<p>A <b>S</b>ecret channel will not show up in the channel list, nor will any user be able to see that you are in the channel with the <em>WHOIS</em> command or anything similar. Only the people that are in the same channel will know that you are in this channel, if this mode is set.</qt> + + + + + inviteModeChBox + + + Only &invited are allowed to join the channel + + + <qt>These control the <em>mode</em> of the channel. Only an operator can change these.<p>An <b>I</b>nvite only channel means that people can only join the channel if they are invited. To invite someone, a channel operator needs to issue the command<em>/invite nick</em> from within the channel.</qt> + + + + + moderatedModeChBox + + + &Moderated channel, only people with voice can write to the channel + + + <qt>These control the <em>mode</em> of the channel. Only an operator can change these.<p>A <b>M</b>oderated channel is one where only operators, half-operators and those with voice can talk.</qt> + + + + + layout11 + + + + unnamed + + + + keyModeChBox + + + Channel &password: + + + <qt>These control the <em>mode</em> of the channel. Only an operator can change these.<p>A <b>P</b>rotected channel requires users to enter a password in order to join.</qt> + + + + + userLimitEdit + + + false + + + 0 + + + <qt>These control the <em>mode</em> of the channel. Only an operator can change these.<p>A channel that has a user <b>L</b>imit means that only that many users can be in the channel at any one time. Some channels have a bot that sits in the channel and changes this automatically depending on how busy the channel is.</qt> + + + + + userLimitChBox + + + User &limit: + + + <qt>These control the <em>mode</em> of the channel. Only an operator can change these.<p>A channel that has a user <b>L</b>imit means that only that many users can be in the channel at any one time. Some channels have a bot that sits in the channel and changes this automatically depending on how busy the channel is.</qt> + + + + + spacer10 + + + Horizontal + + + Expanding + + + + 211 + 20 + + + + + + keyModeEdit + + + false + + + <qt>These control the <em>mode</em> of the channel. Only an operator can change these.<p>A <b>P</b>rotected channel requires users to enter a password in order to join.</qt> + + + + + + + layout2 + + + + unnamed + + + + toggleAdvancedModes + + + Show &Advanced Modes >> + + + Alt+A, Backspace, Tab, Backspace + + + true + + + + + spacer3 + + + Horizontal + + + Expanding + + + + 301 + 31 + + + + + + + + + Mode + + + true + + + true + + + + + Parameter + + + true + + + true + + + + otherModesList + + + Single + + + true + + + LastColumn + + + Accept + + + false + + + true + + + + + spacer4 + + + Vertical + + + Expanding + + + + 20 + 16 + + + + + + + + TabPage + + + &Ban List + + + + unnamed + + + + removeBan + + + + 5 + 5 + 0 + 0 + + + + &Remove Ban + + + + + addBan + + + + 5 + 5 + 0 + 0 + + + + &Add Ban + + + + + + Hostmask + + + true + + + true + + + + + Set By + + + true + + + true + + + + + Time Set + + + true + + + true + + + + banList + + + true + + + true + + + + + clearButton + + + + 4 + 4 + 0 + 0 + + + + + + + + + textLabel2 + + + + 4 + 5 + 0 + 0 + + + + Search: + + + + + banListSearchLine + + + + + + + + + + + + keyModeChBox + toggled(bool) + keyModeEdit + setEnabled(bool) + + + userLimitChBox + toggled(bool) + userLimitEdit + setEnabled(bool) + + + clearButton + clicked() + banListSearchLine + clear() + + + + + + klistview.h + ktextedit.h + ktextedit.h + knuminput.h + knuminput.h + klineedit.h + klistview.h + klistview.h + klistviewsearchline.h + + diff --git a/konversation/src/chatwindow.cpp b/konversation/src/chatwindow.cpp new file mode 100644 index 0000000..b3a024b --- /dev/null +++ b/konversation/src/chatwindow.cpp @@ -0,0 +1,526 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2006-2008 Eike Hein +*/ + +#include "chatwindow.h" +#include "channel.h" +#include "ircview.h" +#include "server.h" +#include "konversationapplication.h" +#include "logfilereader.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +ChatWindow::ChatWindow(QWidget* parent) : QVBox(parent) +{ + setName("ChatWindowObject"); + setTextView(0); + parentWidget=parent; + firstLog=true; + m_server=0; + m_notificationsEnabled = true; + m_channelEncodingSupported = false; + m_currentTabNotify = Konversation::tnfNone; + + setMargin(margin()); + setSpacing(spacing()); + + // The font size of the KTabWidget container may be inappropriately + // small due to the "Tab bar" font size setting. + setFont(KGlobalSettings::generalFont()); +} + +ChatWindow::~ChatWindow() +{ + emit closing(this); + m_server=0; +} + +void ChatWindow::updateAppearance() +{ + // The font size of the KTabWidget container may be inappropriately + // small due to the "Tab bar" font size setting. + setFont(KGlobalSettings::generalFont()); + + if (textView) + { + if (Preferences::showIRCViewScrollBar()) + textView->setVScrollBarMode(QScrollView::AlwaysOn); + else + textView->setVScrollBarMode(QScrollView::AlwaysOff); + } +} + +void ChatWindow::setName(const QString& newName) +{ + name=newName; + emit nameChanged(this,newName); +} + +QString ChatWindow::getName() +{ + return name; +} + +void ChatWindow::setType(WindowType newType) +{ + type=newType; +} + +ChatWindow::WindowType ChatWindow::getType() +{ + return type; +} + +void ChatWindow::setServer(Server* newServer) +{ + if (!newServer) + { + kdDebug("ChatWindow::setServer(0)!") << endl; + } + else + { + m_server=newServer; + connect(m_server,SIGNAL (serverOnline(bool)),this,SLOT (serverOnline(bool)) ); + + // check if we need to set up the signals + if(getType() != ChannelList) + { + if(textView) textView->setServer(newServer); + else kdDebug() << "ChatWindow::setServer(): textView==0!" << endl; + } + + emit serverOnline(m_server->isConnected()); + } +} + +Server* ChatWindow::getServer() +{ + return m_server; +} + +void ChatWindow::serverOnline(bool /* state */) +{ + //emit online(this,state); +} + +void ChatWindow::setTextView(IRCView* newView) +{ + textView = newView; + + if(!textView) + { + return; + } + + if(Preferences::showIRCViewScrollBar()) + { + textView->setVScrollBarMode(QScrollView::Auto); + } + else + { + textView->setVScrollBarMode(QScrollView::AlwaysOff); + } + + textView->setChatWin(this); + connect(textView,SIGNAL(textToLog(const QString&)), this,SLOT(logText(const QString&))); + connect(textView,SIGNAL(setStatusBarTempText(const QString&)), this, SIGNAL(setStatusBarTempText(const QString&))); + connect(textView,SIGNAL(clearStatusBarTempText()), this, SIGNAL(clearStatusBarTempText())); +} + +void ChatWindow::appendRaw(const QString& message, bool suppressTimestamps) +{ + if(!textView) return; + textView->appendRaw(message, suppressTimestamps); +} + +void ChatWindow::append(const QString& nickname,const QString& message) +{ + if(!textView) return ; + textView->append(nickname,message); +} + +void ChatWindow::appendQuery(const QString& nickname,const QString& message, bool inChannel) +{ + if(!textView) return ; + textView->appendQuery(nickname,message, inChannel); +} + +void ChatWindow::appendAction(const QString& nickname, const QString& message) +{ + if(!textView) return; + + if (getType() == Query || getType() == DccChat) + textView->appendQueryAction(nickname, message); + else + textView->appendChannelAction(nickname, message); +} + +void ChatWindow::appendServerMessage(const QString& type,const QString& message, bool parseURL) +{ + if(!textView) return ; + textView->appendServerMessage(type,message, parseURL); +} + +void ChatWindow::appendCommandMessage(const QString& command,const QString& message, bool important, bool parseURL, bool self) +{ + if(!textView) return ; + textView->appendCommandMessage(command,message,important, parseURL, self); +} + +void ChatWindow::appendBacklogMessage(const QString& firstColumn,const QString& message) +{ + if(!textView) return ; + textView->appendBacklogMessage(firstColumn,message); +} + +void ChatWindow::cdIntoLogPath() +{ + QDir logPath=QDir::home(); + // Try to "cd" into the logfile path + if(!logPath.cd(Preferences::logfilePath(),true)) + { + // Only create log path if logging is enabled + if(log) + { + // Try to create the logfile path and "cd" into it again + logPath.mkdir(Preferences::logfilePath(),true); + logPath.cd(Preferences::logfilePath(),true); + } + } + + // add the logfile name to the path + logfile.setName(logPath.path()+'/'+logName); +} + +void ChatWindow::setLogfileName(const QString& name) +{ + // Only change name of logfile if the window was new. + if(firstLog) + { + // status panels get special treatment here, since they have no server at the beginning + if (getType() == Status || getType() == DccChat) + { + logName = name + ".log"; + } + else if (m_server) + { + // make sure that no path delimiters are in the name + logName = QString(m_server->getDisplayName().lower()).append('_').append(name).append(".log").replace('/','_'); + } + + // load backlog to show + if(Preferences::showBacklog()) + { + // "cd" into log path or create path, if it's not there + cdIntoLogPath(); + // Show last log lines. This idea was stole ... um ... inspired by PMP :) + // Don't do this for the server status windows, though + if((getType() != Status) && logfile.open(IO_ReadOnly)) + { + unsigned long filePosition; + + QString backlogLine; + QTextStream backlog(&logfile); + backlog.setEncoding(QTextStream::UnicodeUTF8); + + QStringList firstColumns; + QStringList messages; + int offset = 0; + unsigned int lastPacketHeadPosition = backlog.device()->size(); + const unsigned int packetSize = 4096; + while(messages.count() < (unsigned int)Preferences::backlogLines() && backlog.device()->size() > packetSize * offset) + { + QStringList firstColumnsInPacket; + QStringList messagesInPacket; + + // packetSize * offset < size <= packetSize * ( offset + 1 ) + + // Check if the log is bigger than packetSize * ( offset + 1 ) + if(backlog.device()->size() > packetSize * ( offset + 1 )) + { + // Set file pointer to the packet size above the offset + backlog.device()->at(backlog.device()->size() - packetSize * ( offset + 1 )); + // Skip first line, since it may be incomplete + backlog.readLine(); + } + else + { + // Set file pointer to the head + backlog.device()->reset(); + } + + unsigned int currentPacketHeadPosition = backlog.device()->at(); + + // Loop until end of file reached + while(!backlog.atEnd() && backlog.device()->at() < lastPacketHeadPosition) + { + // remember actual file position to check for deadlocks + filePosition = backlog.device()->at(); + backlogLine = backlog.readLine(); + + // check for deadlocks + if(backlog.device()->at() == filePosition) backlog.device()->at(filePosition + 1); + + // if a tab character is present in the line + if(backlogLine.find('\t') != -1) + { + // extract first column from log + QString backlogFirst = backlogLine.left(backlogLine.find('\t')); + // cut first column from line + backlogLine = backlogLine.mid(backlogLine.find('\t') + 1); + // Logfile is in utf8 so we don't need to do encoding stuff here + // append backlog with time and first column to text view + firstColumnsInPacket << backlogFirst; + messagesInPacket << backlogLine; + } + } // while + + // remember the position not to read the same lines again + lastPacketHeadPosition = currentPacketHeadPosition; + ++offset; + + firstColumns = firstColumnsInPacket + firstColumns; + messages = messagesInPacket + messages; + } + backlog.unsetDevice(); + logfile.close(); + + // trim + int surplus = messages.count() - Preferences::backlogLines(); + // "surplus" can be a minus value. (when the backlog is too short) + if(surplus > 0) + { + for(int i = 0 ; i < surplus ; ++i) + { + firstColumns.pop_front(); + messages.pop_front(); + } + } + + QStringList::Iterator itFirstColumn = firstColumns.begin(); + QStringList::Iterator itMessage = messages.begin(); + for( ; itFirstColumn != firstColumns.end() ; ++itFirstColumn, ++itMessage ) + appendBacklogMessage(*itFirstColumn, *itMessage); + } + } // if(Preferences::showBacklog()) + } +} + +void ChatWindow::logText(const QString& text) +{ + if(log) + { + // "cd" into log path or create path, if it's not there + cdIntoLogPath(); + + if(logfile.open(IO_WriteOnly | IO_Append)) + { + // wrap the file into a stream + QTextStream logStream(&logfile); + // write log in utf8 to help i18n + logStream.setEncoding(QTextStream::UnicodeUTF8); + + if(firstLog) + { + QString intro(i18n("\n*** Logfile started\n*** on %1\n\n").arg(QDateTime::currentDateTime().toString())); + logStream << intro; + firstLog=false; + } + + QTime time=QTime::currentTime(); + QString logLine(QString("[%1] [%2] %3\n").arg(QDate::currentDate(Qt::LocalTime).toString()). + arg(time.toString("hh:mm:ss")).arg(text)); + + logStream << logLine; + + // detach stream from file + logStream.unsetDevice(); + + // close file + logfile.close(); + } + else kdWarning() << "ChatWindow::logText(): open(IO_Append) for " << logfile.name() << " failed!" << endl; + } +} + +void ChatWindow::setChannelEncodingSupported(bool enabled) +{ + m_channelEncodingSupported = enabled; +} + +bool ChatWindow::isChannelEncodingSupported() const +{ + return m_channelEncodingSupported; +} + +int ChatWindow::spacing() +{ + if(Preferences::useSpacing()) + return Preferences::spacing(); + else + return KDialog::spacingHint(); +} + +int ChatWindow::margin() +{ + if(Preferences::useSpacing()) + return Preferences::margin(); + else + return 0; +} + +// Accessors +IRCView* ChatWindow::getTextView() const +{ + return textView; +} + +void ChatWindow::setLog(bool activate) +{ + log=activate; +} + +// reimplement this in all panels that have user input +QString ChatWindow::getTextInLine() +{ + return QString(); +} + +bool ChatWindow::canBeFrontView() +{ + return false; +} + +bool ChatWindow::searchView() +{ + return false; +} + +// reimplement this in all panels that have user input +void ChatWindow::indicateAway(bool) +{ +} + +// reimplement this in all panels that have user input +void ChatWindow::appendInputText(const QString&, bool) +{ +} + +// reimplement this if your window needs special close treatment +bool ChatWindow::closeYourself(bool /* askForConfirmation */) +{ + deleteLater(); + + return true; +} + +bool ChatWindow::eventFilter(QObject* watched, QEvent* e) +{ + if(e->type() == QEvent::KeyPress) + { + QKeyEvent* ke = static_cast(e); + + bool scrollMod = (Preferences::useMultiRowInputBox() ? false : (ke->state() == Qt::ShiftButton)); + + if(ke->key() == Qt::Key_Up && scrollMod) + { + if(textView) + { + QScrollBar* sbar = textView->verticalScrollBar(); + sbar->setValue(sbar->value() - sbar->lineStep()); + } + + return true; + } + else if(ke->key() == Qt::Key_Down && scrollMod) + { + if(textView) + { + QScrollBar* sbar = textView->verticalScrollBar(); + sbar->setValue(sbar->value() + sbar->lineStep()); + } + + return true; + } + else if(ke->key() == Qt::Key_Prior) + { + if(textView) + { + QScrollBar* sbar = textView->verticalScrollBar(); + sbar->setValue(sbar->value() - sbar->pageStep()); + } + + return true; + } + else if(ke->key() == Qt::Key_Next) + { + if(textView) + { + QScrollBar* sbar = textView->verticalScrollBar(); + sbar->setValue(sbar->value() + sbar->pageStep()); + } + + return true; + } + + } + + return QVBox::eventFilter(watched, e); +} + +void ChatWindow::adjustFocus() +{ + childAdjustFocus(); +} + +void ChatWindow::emitUpdateInfo() +{ + QString info = getName(); + emit updateInfo(info); +} + +QColor ChatWindow::highlightColor() +{ + return getTextView()->highlightColor(); +} + +void ChatWindow::activateTabNotification(Konversation::TabNotifyType type) +{ + if (!notificationsEnabled()) + return; + + if(type > m_currentTabNotify) + return; + + m_currentTabNotify = type; + + emit updateTabNotification(this,type); +} + +void ChatWindow::resetTabNotification() +{ + m_currentTabNotify = Konversation::tnfNone; +} + +#include "chatwindow.moc" diff --git a/konversation/src/chatwindow.h b/konversation/src/chatwindow.h new file mode 100644 index 0000000..55c0efc --- /dev/null +++ b/konversation/src/chatwindow.h @@ -0,0 +1,205 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2006-2008 Eike Hein +*/ + +#ifndef CHATWINDOW_H +#define CHATWINDOW_H + +#include "identity.h" +#include "common.h" + +#include +#include + + +class IRCView; +class Server; +class KonversationMainWindow; + +class ChatWindow : public QVBox +{ + Q_OBJECT + + public: + explicit ChatWindow(QWidget* parent); + ~ChatWindow(); + + enum WindowType + { + Status=0, + Channel, + Query, + DccChat, + DccTransferPanel, + RawLog, + Notice, + SNotice, + ChannelList, + Konsole, + UrlCatcher, + NicksOnline, + LogFileReader + }; + + /** This should be called and set with a non-null server as soon + * as possibly after ChatWindow is created. + * @param newServer The server to set it to. + */ + virtual void setServer(Server* newServer); + /** This should be called if setServer is not called - e.g. + * in the case of konsolepanel. This should be set as soon + * as possible after creation. + */ + + /** Get the server this is linked to. + * @return The server it is associated with, or null if none. + */ + Server* getServer(); + void setTextView(IRCView* newView); + IRCView* getTextView() const; + void setLog(bool activate); + + QString getName(); + + void setType(WindowType newType); + WindowType getType(); + + virtual void append(const QString& nickname,const QString& message); + virtual void appendRaw(const QString& message, bool suppressTimestamps=false); + virtual void appendQuery(const QString& nickname,const QString& message, bool inChannel = false); + virtual void appendAction(const QString& nickname,const QString& message); + virtual void appendServerMessage(const QString& type,const QString& message, bool parseURL = true); + virtual void appendCommandMessage(const QString& command, const QString& message, bool important = true, + bool parseURL = true, bool self = false); + virtual void appendBacklogMessage(const QString& firstColumn,const QString& message); + + QWidget* parentWidget; + + virtual QString getTextInLine(); + /** Clean up and close this tab. Return false if you want to cancel the close. */ + virtual bool closeYourself(bool askForConfirmation = true); + /** Reimplement this to return true in all classes that /can/ become front view. + */ + virtual bool canBeFrontView(); + + /** Reimplement this to return true in all classes that you can search in - i.e. use "Edit->Find Text" in. + */ + virtual bool searchView(); + + virtual bool notificationsEnabled() { return m_notificationsEnabled; } + + virtual bool eventFilter(QObject* watched, QEvent* e); + + QString logFileName() { return logfile.name(); } + + virtual void setChannelEncoding(const QString& /* encoding */) {} + virtual QString getChannelEncoding() { return QString(); } + virtual QString getChannelEncodingDefaultDesc() { return QString(); } + bool isChannelEncodingSupported() const; + + /** Force updateInfo(info) to be emitted. + * Useful for when this tab has just gained focus + */ + virtual void emitUpdateInfo(); + + /** child classes have to override this and return true if they want the + * "insert character" item on the menu to be enabled. + */ + virtual bool isInsertSupported() { return false; } + + /** child classes have to override this and return true if they want the + * "irc color" item on the menu to be enabled. + */ + virtual bool areIRCColorsSupported() {return false; } + + Konversation::TabNotifyType currentTabNotification() { return m_currentTabNotify; } + QColor highlightColor(); + + signals: + void nameChanged(ChatWindow* view, const QString& newName); + //void online(ChatWindow* myself, bool state); + /** Emit this signal when you want to change the status bar text for this tab. + * It is ignored if this tab isn't focused. + */ + void updateInfo(const QString &info); + void updateTabNotification(ChatWindow* chatWin, const Konversation::TabNotifyType& type); + + void setStatusBarTempText(const QString&); + void clearStatusBarTempText(); + + void closing(ChatWindow* myself); + + public slots: + void updateAppearance(); + + void logText(const QString& text); + + /** + * This is called when a chat window gains focus. + * It enables and disables the appropriate menu items, + * then calls childAdjustFocus. + * You can call this manually to focus this tab. + */ + void adjustFocus(); + + virtual void appendInputText(const QString&, bool fromCursor); + virtual void indicateAway(bool away); + + + virtual void setNotificationsEnabled(bool enable) { m_notificationsEnabled = enable; } + void activateTabNotification(Konversation::TabNotifyType type); + void resetTabNotification(); + + protected slots: + ///Used to disable functions when not connected + virtual void serverOnline(bool online); + + protected: + + /** Some children may handle the name themselves, and not want this public. + * Increase the visibility in the subclass if you want outsiders to call this. + * The name is the string that is shown in the tab. + * @param newName The name to show in the tab + */ + virtual void setName(const QString& newName); + + /** Called from adjustFocus */ + virtual void childAdjustFocus() = 0; + + void setLogfileName(const QString& name); + void setChannelEncodingSupported(bool enabled); + void cdIntoLogPath(); + + int spacing(); + int margin(); + + bool log; + bool firstLog; + QString name; + QString logName; + + QFont font; + + IRCView* textView; + /** A pointer to the server this chatwindow is part of. + * Not always non-null - e.g. for konsolepanel + */ + Server* m_server; + QFile logfile; + WindowType type; + + bool m_notificationsEnabled; + + bool m_channelEncodingSupported; + + Konversation::TabNotifyType m_currentTabNotify; +}; +#endif diff --git a/konversation/src/chatwindowappearance_preferences.ui b/konversation/src/chatwindowappearance_preferences.ui new file mode 100644 index 0000000..5a90533 --- /dev/null +++ b/konversation/src/chatwindowappearance_preferences.ui @@ -0,0 +1,378 @@ + +ChatWindowAppearance_Config +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. + + + ChatWindowAppearance_Config + + + + 0 + 0 + 401 + 502 + + + + + unnamed + + + 0 + + + + kcfg_Timestamping + + + Enable &Timestamps + + + true + + + + unnamed + + + + kcfg_ShowDate + + + Sho&w dates + + + + + textLabel1 + + + &Format: + + + kcfg_TimestampFormat + + + + + kcfg_TimestampFormat + + + true + + + + + spacer127 + + + Horizontal + + + Expanding + + + + 191 + 20 + + + + + + + + kcfg_ShowBacklog + + + Show &Backlog + + + true + + + + unnamed + + + + textLabel1_2 + + + &Lines: + + + kcfg_BacklogLines + + + + + kcfg_BacklogLines + + + 100 + + + 10 + + + + + spacer3 + + + Horizontal + + + Expanding + + + + 251 + 20 + + + + + + + + groupBox2 + + + &Layout + + + + unnamed + + + + kcfg_ShowTopic + + + &Show channel topic + + + + + kcfg_ShowModeButtons + + + Show channel &mode buttons + + + + + kcfg_ShowIRCViewScrollBar + + + Show sc&rollbar + + + + + + + + kcfg_ShowNicknameBox + + + Show bo&x to change own nickname + + + + + kcfg_ShowQuickButtons + + + false + + + Show &quick buttons + + + + + spacer10 + + + Horizontal + + + Fixed + + + + 16 + 20 + + + + + + kcfg_ShowRealNames + + + false + + + Show real names in nickname list + + + + + spacer9 + + + Horizontal + + + Fixed + + + + 16 + 20 + + + + + + kcfg_ShowNickList + + + Show channel &nick list and quick buttons + + + + + kcfg_AutoUserhost + + + false + + + Show hostmas&ks in nickname list + + + + + spacer9_2 + + + Horizontal + + + Fixed + + + + 16 + 20 + + + + + + + + kcfg_ShowBackgroundImage + + + Enable Back&ground Image + + + true + + + + unnamed + + + + textLabel4 + + + P&ath: + + + kcfg_BackgroundImage + + + + + kcfg_BackgroundImage + + + + + + + spacer90 + + + Vertical + + + Expanding + + + + 20 + 20 + + + + + + + + + + kcfg_ShowNickList + toggled(bool) + kcfg_AutoUserhost + setEnabled(bool) + + + kcfg_ShowNickList + toggled(bool) + kcfg_ShowQuickButtons + setEnabled(bool) + + + kcfg_ShowNickList + toggled(bool) + kcfg_ShowRealNames + setEnabled(bool) + + + + kcfg_TimestampFormat + kcfg_ShowDate + kcfg_BacklogLines + kcfg_ShowTopic + kcfg_ShowModeButtons + kcfg_ShowNickList + kcfg_AutoUserhost + kcfg_ShowRealNames + kcfg_ShowQuickButtons + kcfg_ShowNicknameBox + kcfg_ShowIRCViewScrollBar + kcfg_BackgroundImage + kcfg_ShowBackgroundImage + kcfg_Timestamping + kcfg_ShowBacklog + + + + knuminput.h + kurlrequester.h + klineedit.h + kpushbutton.h + + diff --git a/konversation/src/chatwindowbehaviour_preferences.ui b/konversation/src/chatwindowbehaviour_preferences.ui new file mode 100644 index 0000000..b142b1e --- /dev/null +++ b/konversation/src/chatwindowbehaviour_preferences.ui @@ -0,0 +1,374 @@ + +ChatwindowBehaviour_Config + + + ChatwindowBehaviour_Config + + + + 0 + 0 + 458 + 461 + + + + + unnamed + + + 0 + + + + groupBox3 + + + General + + + + unnamed + + + + kcfg_Beep + + + Enable s&ystem bell on incoming ASCII BEL + + + Sounds the system bell when you receive an ASCII BEL (0x07) control character + + + + + kcfg_HideUnimportantEvents + + + Hide &Join/Part/Nick events + + + + + kcfg_DisableExpansion + + + Disable variable (e.g. %C, %B, %G...) e&xpansion + + + Do not expand variables when sending text to the server. A variable starts with '%'; for example, %B will expand to the characters needed to make a text bold. + + + + + kcfg_RedirectServerAndAppMsgToStatusPane + + + &Redirect status messages to the server status window + + + + + textLabel1 + + + Scroll&back limit: + + + kcfg_ScrollbackMax + + + How many lines to keep in buffers, 0 = unlimited + + + + + spacer1_2 + + + Horizontal + + + Expanding + + + + 410 + 20 + + + + + + kcfg_UseLiteralModes + + + &Use raw modes for mode changes + + + Keep channel mode string as a combination of characters instead of translating them into human readable words. E.g. '*** Channel modes: no messages from outside' will become '*** Channel modes: n' + + + + + kcfg_ScrollbackMax + + + lines + + + Unlimited + + + 2000 + + + How many lines to keep in buffers, 0 = unlimited + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 230 + 20 + + + + + + + + groupBox3_2 + + + Marker Lines + + + + unnamed + + + + kcfg_MarkerLineInAllViews + + + Show manually inserted lines in all chat windows + + + + + kcfg_AutomaticRememberLine + + + Mark the last position in a chat window when it is hidden + + + + + + Inserts a remember line into the chat window when you switch to another chat window or minimize the application. + + + + + kcfg_AutomaticRememberLineOnlyOnTextChange + + + false + + + Move the line only when new text is about to be shown + + + + + spacer9 + + + Horizontal + + + Fixed + + + + 16 + 20 + + + + + + + + kcfg_AutoWhoContinuousEnabled + + + Enable Automatic User Information Look Up (/WHO) + + + true + + + false + + + + unnamed + + + + spacer3 + + + Horizontal + + + Expanding + + + + 170 + 20 + + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 190 + 20 + + + + + + textLabel2 + + + Max. number of users in a channel: + + + kcfg_AutoWhoNicksLimit + + + + + kcfg_AutoWhoNicksLimit + + + nicks + + + 1000 + + + 0 + + + 300 + + + + + kcfg_AutoWhoContinuousInterval + + + false + + + + + + seconds + + + 1000 + + + 30 + + + + + whoIntervalLbl + + + Update interval: + + + kcfg_AutoWhoContinuousInterval + + + + + + + spacer6 + + + Vertical + + + Expanding + + + + 41 + 20 + + + + + + + + kcfg_AutoWhoContinuousEnabled + toggled(bool) + kcfg_AutoWhoContinuousInterval + setEnabled(bool) + + + kcfg_AutomaticRememberLine + toggled(bool) + kcfg_AutomaticRememberLineOnlyOnTextChange + setEnabled(bool) + + + + kcfg_Beep + kcfg_HideUnimportantEvents + kcfg_DisableExpansion + kcfg_RedirectServerAndAppMsgToStatusPane + kcfg_UseLiteralModes + kcfg_ScrollbackMax + kcfg_AutomaticRememberLine + kcfg_AutomaticRememberLineOnlyOnTextChange + kcfg_MarkerLineInAllViews + kcfg_AutoWhoNicksLimit + kcfg_AutoWhoContinuousInterval + kcfg_AutoWhoContinuousEnabled + kcfg_AutoWhoContinuousEnabled + + + + diff --git a/konversation/src/colorsappearance_preferences.ui b/konversation/src/colorsappearance_preferences.ui new file mode 100644 index 0000000..e089ade --- /dev/null +++ b/konversation/src/colorsappearance_preferences.ui @@ -0,0 +1,1395 @@ + +ColorsAppearance_Config +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. +İsmail Dönmez + + + ColorsAppearance_Config + + + + 0 + 0 + 457 + 512 + + + + + unnamed + + + 0 + + + + groupBox1 + + + + 7 + 5 + 0 + 0 + + + + Custom Colors + + + + unnamed + + + + kcfg_InputFieldsBackgroundColor + + + &Use custom colors for input box, nickname list and tab list + + + + + kcfg_TimeColor + + + + + + + + kcfg_AlternateBackgroundColor + + + + + + + + kcfg_QueryMessageColor + + + + + + + + kcfg_CommandMessageColor + + + + + + + + kcfg_BacklogMessageColor + + + + + + + + kcfg_TextViewBackgroundColor + + + + + + + + kcfg_ServerMessageColor + + + + + + + + kcfg_HyperlinkColor + + + + + + + + kcfg_ChannelMessageColor + + + + + + + + kcfg_ActionMessageColor + + + + + + + + spacer185 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + spacer186 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + spacer187 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + spacer188 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + spacer189 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + spacer190 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + spacer191 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + spacer192 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + spacer193 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + spacer194 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + textLabel3 + + + &Background: + + + kcfg_TextViewBackgroundColor + + + + + textLabel2_2 + + + &Server message: + + + kcfg_ServerMessageColor + + + + + textLabel1_2 + + + H&yperlink: + + + kcfg_HyperlinkColor + + + + + textLabel2 + + + Channel &message: + + + kcfg_ChannelMessageColor + + + + + textLabel1 + + + Actio&n: + + + kcfg_ActionMessageColor + + + + + textLabel4 + + + Bac&klog: + + + kcfg_BacklogMessageColor + + + + + textLabel5 + + + Comman&d message: + + + kcfg_CommandMessageColor + + + + + textLabel1_8 + + + &Query message: + + + kcfg_QueryMessageColor + + + + + textLabel1_9 + + + &Timestamp: + + + kcfg_TimeColor + + + + + textLabel1_10 + + + A&lternate background: + + + kcfg_AlternateBackgroundColor + + + + + + + kcfg_UseColoredNicks + + + true + + + Colored Nicks + + + true + + + + unnamed + + + + textLabel9 + + + + 0 + 5 + 0 + 0 + + + + 5: + + + + + kcfg_NickColor4 + + + + + + + + textLabel8 + + + + 0 + 5 + 0 + 0 + + + + 4: + + + + + kcfg_NickColor5 + + + + + + + + textLabel7 + + + + 0 + 5 + 0 + 0 + + + + 3: + + + + + kcfg_NickColor2 + + + + + + + + kcfg_NickColor3 + + + + + + + + textLabel6 + + + + 0 + 5 + 0 + 0 + + + + 2: + + + + + spacer196 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + spacer197 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + spacer197_2 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + spacer196_2 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + kcfg_NickColor0 + + + + + + + + textLabel4_2 + + + + 0 + 5 + 0 + 0 + + + + 0: + + + + + kcfg_NickColor1 + + + + + + + + textLabel5_2 + + + + 0 + 5 + 0 + 0 + + + + 1: + + + + + spacer197_3 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + spacer196_3 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + kcfg_NickColor7 + + + + + + + + kcfg_NickColor6 + + + + + + + + textLabel11 + + + + 0 + 5 + 0 + 0 + + + + 7: + + + + + textLabel10 + + + + 0 + 5 + 0 + 0 + + + + 6: + + + + + layout18 + + + + unnamed + + + + textLabel1_3 + + + &Own nick color: + + + kcfg_NickColor8 + + + + + kcfg_NickColor8 + + + + + + + + spacer204 + + + Horizontal + + + Expanding + + + + 271 + 20 + + + + + + + + + + kcfg_AllowColorCodes + + + true + + + &Allow Colored Text in IRC Messages + + + true + + + By enabling this option, color codes added to IRC messages will be displayed in your chat window as colored text. You can add color codes to your messages, by selecting Insert -> IRC Color + + + + unnamed + + + + textLabel12_2 + + + + 0 + 5 + 0 + 0 + + + + 1: + + + + + textLabel12_3 + + + + 0 + 5 + 0 + 0 + + + + 2: + + + + + textLabel12_4 + + + + 0 + 5 + 0 + 0 + + + + 3: + + + + + kcfg_IrcColorCode3 + + + + + + + + kcfg_IrcColorCode2 + + + + + + + + kcfg_IrcColorCode0 + + + + + + + + kcfg_IrcColorCode1 + + + + + + + + textLabel12_14 + + + + 0 + 5 + 0 + 0 + + + + 0: + + + + + textLabel12_8 + + + 7: + + + + + textLabel12_7 + + + 6: + + + + + textLabel12_6 + + + 5: + + + + + textLabel12_5 + + + 4: + + + + + kcfg_IrcColorCode5 + + + + + + + + kcfg_IrcColorCode4 + + + + + + + + kcfg_IrcColorCode7 + + + + + + + + kcfg_IrcColorCode6 + + + + + + + + spacer211_4 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + spacer211_3 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + spacer211_2 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + spacer211 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + spacer211_3_2 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + spacer211_5 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + spacer211_2_2 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + spacer211_4_2 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + kcfg_IrcColorCode11 + + + + + + + + textLabel12_12 + + + 11: + + + + + kcfg_IrcColorCode9 + + + + + + + + kcfg_IrcColorCode10 + + + + + + + + kcfg_IrcColorCode8 + + + + + + + + textLabel12_10 + + + 9: + + + + + textLabel12_9 + + + 8: + + + + + textLabel12_11 + + + 10: + + + + + spacer211_6 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + spacer211_2_3 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + spacer211_3_3 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + spacer211_4_3 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + kcfg_IrcColorCode15 + + + + + + + + textLabel12_13 + + + 12: + + + + + kcfg_IrcColorCode13 + + + + + + + + textLabel12_16 + + + 15: + + + + + kcfg_IrcColorCode12 + + + + + + + + kcfg_IrcColorCode14 + + + + + + + + textLabel12_15 + + + 14: + + + + + textLabel12 + + + 13: + + + + + + + spacer227 + + + Vertical + + + Expanding + + + + 20 + 0 + + + + + + + kcfg_ActionMessageColor + kcfg_ChannelMessageColor + kcfg_HyperlinkColor + kcfg_ServerMessageColor + kcfg_TextViewBackgroundColor + kcfg_BacklogMessageColor + kcfg_CommandMessageColor + kcfg_QueryMessageColor + kcfg_TimeColor + kcfg_AlternateBackgroundColor + kcfg_InputFieldsBackgroundColor + kcfg_UseColoredNicks + kcfg_NickColor0 + kcfg_NickColor1 + kcfg_NickColor2 + kcfg_NickColor3 + kcfg_NickColor4 + kcfg_NickColor5 + kcfg_NickColor6 + kcfg_NickColor7 + kcfg_NickColor8 + kcfg_AllowColorCodes + kcfg_IrcColorCode0 + kcfg_IrcColorCode1 + kcfg_IrcColorCode2 + kcfg_IrcColorCode3 + kcfg_IrcColorCode4 + kcfg_IrcColorCode5 + kcfg_IrcColorCode6 + kcfg_IrcColorCode7 + kcfg_IrcColorCode8 + kcfg_IrcColorCode9 + kcfg_IrcColorCode10 + kcfg_IrcColorCode11 + kcfg_IrcColorCode12 + kcfg_IrcColorCode13 + kcfg_IrcColorCode14 + kcfg_IrcColorCode15 + + + + + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + + + + kcfg_InputFieldsBackgroundColor + toggled(bool) + kcfg_AlternateBackgroundColor + setEnabled(bool) + + + diff --git a/konversation/src/commit.h b/konversation/src/commit.h new file mode 100644 index 0000000..cc8815a --- /dev/null +++ b/konversation/src/commit.h @@ -0,0 +1,4 @@ +// This COMMIT number is added to version string to be used as "patch level" +#ifndef COMMIT +#define COMMIT 3300 +#endif diff --git a/konversation/src/common.cpp b/konversation/src/common.cpp new file mode 100644 index 0000000..afd6c97 --- /dev/null +++ b/konversation/src/common.cpp @@ -0,0 +1,196 @@ +/* + 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. +*/ + +/* + Copyright (C) 2004 Peter Simonsson + Copyright (C) 2006-2008 Eike Hein +*/ + +#include "common.h" +#include "konversationapplication.h" +#include "config/preferences.h" + +#include +#include +#include +#include +#include +#include +#include + + +namespace Konversation +{ + + #include "guess_ja.cpp" + #include "unicode.cpp" + + static QRegExp colorRegExp("((\003([0-9]|0[0-9]|1[0-5])(,([0-9]|0[0-9]|1[0-5])|)|\017)|\x02|\x09|\x13|\x16|\x1f)"); + static QRegExp urlPattern("((www\\.(?!\\.)|(fish|irc|(f|sf|ht)tp(|s))://)(\\.?[\\d\\w/,\\':~\\?=;#@\\-\\+\\%\\*\\{\\}\\!\\(\\)]|&)+)|" + "([-.\\d\\w]+@[-.\\d\\w]{2,}\\.[\\w]{2,})"); + static QRegExp tdlPattern("(.*)\\.(\\w+),$"); + + QString removeIrcMarkup(const QString& text) + { + QString escaped = text; + // Escape text decoration + escaped.remove(colorRegExp); + + // Remove Mirc's 0x03 characters too, they show up as rectangles + escaped.remove(QChar(0x03)); + + return escaped; + } + + QString tagURLs(const QString& text, const QString& fromNick, bool useCustomColor) + { + // QTime timer; + // timer.start(); + + QString filteredLine = text; + QString linkColor = Preferences::color(Preferences::Hyperlink).name(); + QString link; + QString insertText; + int pos = 0; + int urlLen = 0; + QString href; + + if(useCustomColor) + { + link = "%2"; + } + else + { + link = "%2"; + } + + if(filteredLine.contains("#")) + { + QRegExp chanExp("(^|\\s|^\"|\\s\"|,|'|\\(|\\:|!|@|%|\\+)(#[^,\\s;\\)\\:\\/\\(\\<\\>]*[^.,\\s;\\)\\:\\/\\(\"\''\\<\\>])"); + while((pos = chanExp.search(filteredLine, pos)) >= 0) + { + href = chanExp.cap(2); + urlLen = href.length(); + pos += chanExp.cap(1).length(); + + // HACK:Use space as a placeholder for \ as Qt tries to be clever and does a replace to / in urls in QTextEdit + insertText = link.arg(QString(href).replace('\\', " "), href); + filteredLine.replace(pos, urlLen, insertText); + pos += insertText.length(); + } + } + + pos = 0; + urlLen = 0; + + urlPattern.setCaseSensitive(false); + QString protocol; + + if(useCustomColor) + { + link = "%3"; + } + else + { + link = "%3"; + } + + while((pos = urlPattern.search(filteredLine, pos)) >= 0) + { + QString append; + + // check if the matched text is already replaced as a channel + if ( filteredLine.findRev( " filteredLine.findRev( "", pos ) ) + { + ++pos; + continue; + } + + protocol=""; + urlLen = urlPattern.matchedLength(); + href = filteredLine.mid( pos, urlLen ); + + // Don't consider trailing comma part of link. + if (href.right(1) == ",") + { + href.truncate(href.length()-1); + append = ','; + } + + // Don't consider trailing semicolon part of link. + if (href.right(1) == ";") + { + href.truncate(href.length()-1); + append = ';'; + } + + // Don't consider trailing closing parenthesis part of link when + // there's an opening parenthesis preceding the beginning of the + // URL or there is no opening parenthesis in the URL at all. + if (href.right(1) == ")" && (filteredLine.mid(pos-1,1) == "(" || !href.contains("("))) + { + href.truncate(href.length()-1); + append.prepend(")"); + } + + // Qt doesn't support (?<=pattern) so we do it here + if((pos > 0) && filteredLine[pos-1].isLetterOrNumber()) + { + pos++; + continue; + } + + if (urlPattern.cap(1).startsWith("www.", false)) + protocol = "http://"; + else if (urlPattern.cap(1).isEmpty()) + protocol = "mailto:"; + + // Use \x0b as a placeholder for & so we can readd them after changing all & in the normal text to & + // HACK Replace % with \x03 in the url to keep Qt from doing stupid things + insertText = link.arg(protocol, QString(href).replace('&', "\x0b").replace('%', "\x03"), href) + append; + filteredLine.replace(pos, urlLen, insertText); + pos += insertText.length(); + KonversationApplication::instance()->storeUrl(fromNick, href); + } + + // Change & to & to prevent html entities to do strange things to the text + filteredLine.replace('&', "&"); + filteredLine.replace("\x0b", "&"); + + // kdDebug() << "Took (msecs) : " << timer.elapsed() << " for " << filteredLine << endl; + + return filteredLine; + } + + //TODO: there's room for optimization as pahlibar said. (strm) + + // the below two functions were taken from kopeteonlinestatus.cpp. + QBitmap overlayMasks( const QBitmap *under, const QBitmap *over ) + { + if ( !under && !over ) return QBitmap(); + if ( !under ) return *over; + if ( !over ) return *under; + + QBitmap result = *under; + bitBlt( &result, 0, 0, over, 0, 0, over->width(), over->height(), Qt::OrROP ); + return result; + } + + QPixmap overlayPixmaps( const QPixmap &under, const QPixmap &over ) + { + if ( over.isNull() ) return under; + + QImage imResult; imResult=under; + QImage imOver; imOver=over; + QPixmap result; + + bitBlt(&imResult,0,0,&imOver,0,0,imOver.width(),imOver.height(),0); + result=imResult; + return result; + } + +} diff --git a/konversation/src/common.h b/konversation/src/common.h new file mode 100644 index 0000000..fe5fa6d --- /dev/null +++ b/konversation/src/common.h @@ -0,0 +1,56 @@ +/* + 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. +*/ + +/* + Copyright (C) 2004 Peter Simonsson + Copyright (C) 2006-2008 Eike Hein +*/ + +#ifndef COMMON_H +#define COMMON_H + +class QCString; +class QString; +class QBitmap; +class QPixmap; + +namespace Konversation +{ + QString removeIrcMarkup(const QString& text); + QString tagURLs(const QString& text, const QString& fromNick, bool useCustomColor = true); + QBitmap overlayMasks( const QBitmap *under, const QBitmap *over ); + QPixmap overlayPixmaps(const QPixmap &under, const QPixmap &over); + bool isUtf8(const QCString& text); + + enum TabNotifyType + { + tnfNick, + tnfHighlight, + tnfPrivate, + tnfNormal, + tnfSystem, + tnfControl, + tnfNone + }; + + enum ConnectionState + { + SSNeverConnected, + SSDeliberatelyDisconnected, + SSInvoluntarilyDisconnected, + SSConnecting, + SSConnected + }; + + enum ConnectionFlag + { + SilentlyReuseConnection, + PromptToReuseConnection, + CreateNewConnection + }; +} +#endif diff --git a/konversation/src/config/Makefile.am b/konversation/src/config/Makefile.am new file mode 100644 index 0000000..23e37bb --- /dev/null +++ b/konversation/src/config/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = -I.. -I$(srcdir)/.. $(all_includes) +METASOURCES = AUTO + +noinst_LTLIBRARIES = libkonversationconfig.la +libkonversationconfig_la_SOURCES = preferences_base.kcfgc preferences.cpp +libkonversationconfig_la_LDFLAGS = $(all_libraries) -no-undefined + +kde_kcfg_DATA = konversation.kcfg diff --git a/konversation/src/config/konversation.kcfg b/konversation/src/config/konversation.kcfg new file mode 100644 index 0000000..9346e18 --- /dev/null +++ b/konversation/src/config/konversation.kcfg @@ -0,0 +1,996 @@ + + + qfont.h + qsize.h + kdialog.h + kuser.h + kglobalsettings.h + + + + + true + + + + + true + + + + + + + + + + + + + + KGlobalSettings::generalFont() + + + + + KGlobalSettings::generalFont() + + + + + KGlobalSettings::generalFont() + + + + + false + + + + + false + + + + + false + + + + + true + + + + + false + + + + + hh:mm + + + + + true + + + + + 10 + + + + + true + + + + + false + + + + + + false + + + + + false + + + + + false + + + + + false + + + + + KDialog::spacingHint() + + + + + KDialog::marginHint() + + + + + false + + + + + 2 + 0 + + + + + + + + + + + + + + + + #ffffff + #000000 + #000080 + #008000 + #ff0000 + #a52a2a + #800080 + #ff8000 + #808000 + #00ff00 + #008080 + #00ffff + #0000ff + #ffc0cb + #a0a0a0 + #c0c0c0 + + + true + + + + + + #E90E7F + #8E55E9 + #B30E0E + #18B33C + #58ADB3 + #9E54B3 + #B39875 + #3176B3 + #000001 + + + true + + + + + true + + + + + true + + + + + true + + + + + false + + + + + false + + + + + true + + + + + true + + + + + + false + Enable if you want all the IRC input lines to check your spelling as you type + + + false + + + + + false + Enabling this will cause the input box to grow vertically when it fills up. + + + / + + + + + + + + + + false + + + + + false + + + + + false + + + + + true + + + + + false + + + + false + + + + false + + + + + + + + + + + + + + + QSize(400, 200) + + + + + + + + + + 100 + + + + + 1000 + + + + + 200 + + + + + true + + + + + 90 + + + + + false + + + + + /QUERY %u%n + + + + + /QUERY %u%n + + + + + false + + + + + false + + + + + + + + + + 180 + + + + + false + + + + + false + + + + + 10 + 10 + + + + + false + + + + + true + + + + + false + + + + + + + + false + + + + + false + + + + + true + + + + + + + false + + + + + false + + + + + false + + + + + false + + + + + false + + + + + KGlobalSettings::generalFont() + + + + + false + + + + + 3000 + + + + + 0 + + + + + false + + + + + 30 + + + + + 50 + + + + + 0 + + + + + #ffffff + + + + + + + + + + true + + + + + + + 20 + + + + + true + + + + + false + + + + + + + false + + + + + true + + + + + #FF0000 + + + + + false + + + + + #ff0000 + + + + + + + + + + + + + + + + + + + 2 + + + + + : + + + + + + + + + + + + + + + false + + + + + + + 8192 + + + + + 1 + + + + + 0.0.0.0 + + + + + true + + + + + 1026 + + + + + 7000 + + + + + true + + + + + 1026 + + + + + 7000 + + + + + false + + + + + false + + + + + true + + + + + false + + + + + true + + + + + true + + + + + 180 + + + + + false + + + eth0 + + + false + + + 16,90,80,150,70,90,120,80,70,120 + + + + + + + KUser(KUser::UseRealUserID).homeDir()+"/logs" + + + + + KUser(KUser::UseRealUserID).homeDir()+"/dccrecv" + + + + + + + true + + + + + true + + + + + false + + + + + + + + + + Bottom + + + false + + + true + + + false + + + + + false + + + + + false + + + + + true + + + + + 10 + + + + + 0 + + + + + true + + + + + false + + + + + true + + + + + false + + + + + + + false + + + + + firefox '%u' + + + + + + + default + + + + + false + + + + Default + + + + + + + + + + + + + + + + + + + + + + + + + + + ActionMessage + BacklogMessage + ChannelMessage + CommandMessage + QueryMessage + ServerMessage + Time + Action + TextViewBackground + AlternateBackground + Hyperlink + + + #0000ff + #aaaaaa + #000000 + #960096 + #000000 + #91640a + #709070 + #0000ff + #ffffff + #EDF4F9 + #0000ff + + + + + true + + + + + false + + + + + true + + + + + #C3C300 + + + + + true + + + + + #008000 + + + + + true + + + + + #800000 + + + + + false + + + + + #008000 + + + + + true + + + + + #FF0000 + + + + + true + + + + + #FF0000 + + + + + false + + + + + + + qpohv- + + + + + + + QValueList< QValueList<int> > defaultRate; + QValueList< QValueList<int> >::iterator defaultRateInitIter; + + defaultRateInitIter = defaultRate.append(QValueList<int>()); + (*defaultRateInitIter).append( 15 ); + (*defaultRateInitIter).append( 60 ); + (*defaultRateInitIter).append( 0 ); + + defaultRateInitIter = defaultRate.append(QValueList<int>()); + (*defaultRateInitIter).append( 40 ); + (*defaultRateInitIter).append( 60 ); + (*defaultRateInitIter).append( 0 ); + + defaultRateInitIter = defaultRate.append(QValueList<int>()); + (*defaultRateInitIter).append( 1 ); + (*defaultRateInitIter).append( 1 ); + (*defaultRateInitIter).append( 0 ); + + if (0) //kconfig_compiler generates invalid code for int lists + + defaultRate[0] + defaultRate[1] + defaultRate[2] + + + false + + + diff --git a/konversation/src/config/preferences.cpp b/konversation/src/config/preferences.cpp new file mode 100644 index 0000000..9910256 --- /dev/null +++ b/konversation/src/config/preferences.cpp @@ -0,0 +1,605 @@ +/* + This program is free software; you can redistribute it and/or self()->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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2005 Ismail Donmez + Copyright (C) 2005 Peter Simonsson + Copyright (C) 2005 John Tapsell + Copyright (C) 2005-2008 Eike Hein +*/ + +#include "config/preferences.h" +#include "identity.h" +#include "ignore.h" +#include "highlight.h" +#include "commit.h" +#include "version.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +Preferences *Preferences::mSelf = 0; +static KStaticDeleter staticPreferencesDeleter; + +Preferences *Preferences::self() +{ + if ( !mSelf ) { + staticPreferencesDeleter.setObject( mSelf, new Preferences() ); + mSelf->readConfig(); + } + + return mSelf; +} + + +Preferences::Preferences() +{ + mSelf = this; + // create default identity + mIdentity=new Identity(); + mIdentity->setName(i18n("Default Identity")); + addIdentity(mIdentity); + mIgnoreList.setAutoDelete(true); + + KUser user(KUser::UseRealUserID); + mIdentity->setIdent(user.loginName()); + mIdentity->setRealName(user.fullName()); + + QStringList nickList; + nickList.append(user.loginName()); + nickList.append(user.loginName() + '_'); + nickList.append(user.loginName() + "__"); + mIdentity->setNicknameList(nickList); + + Konversation::ServerGroupSettingsPtr serverGroup = new Konversation::ServerGroupSettings; + serverGroup->setName("Ubuntu IRC"); + Konversation::ServerSettings server; + server.setHost("irc.ubuntu.com"); + server.setPort(8001); + serverGroup->addServer(server); + serverGroup->setIdentityId(mIdentity->id()); + Konversation::ChannelSettings channel; + channel.setName("#kubuntu"); + serverGroup->addChannel(channel); + serverGroup->setExpanded(false); + addServerGroup(serverGroup); + setQuickButtonList(defaultQuickButtonList()); + setAutoreplaceList(defaultAutoreplaceList()); +} + +Preferences::~Preferences() +{ + mIdentityList.clear(); + + if ( mSelf == this ) + staticPreferencesDeleter.setObject( mSelf, 0, false ); +} +const Konversation::ServerGroupList Preferences::serverGroupList() +{ + return self()->mServerGroupList; +} + +const QStringList Preferences::defaultQuickButtonList() +{ + return QStringList() << "Op,/OP %u%n" + << "DeOp,/DEOP %u%n" + << "WhoIs,/WHOIS %s,%%u%n" + << "Version,/CTCP %s,%%u VERSION%n" + << "Kick,/KICK %u%n" + << "Ban,/BAN %u%n" + << "Part,/PART %c Leaving...%n" + << "Quit,/QUIT Leaving...%n"; +} + +const QStringList Preferences::quickButtonList() +{ + return self()->mQuickButtonList; +} + +void Preferences::setQuickButtonList(const QStringList newList) +{ + self()->mQuickButtonList=newList; +} + +void Preferences::clearQuickButtonList() +{ + self()->mQuickButtonList.clear(); +} + +// --------------------------- AutoReplace --------------------------- + +const QStringList Preferences::defaultAutoreplaceList() +{ + return QStringList() << "1,o,\\[\\[([^\\s]+)\\]\\],http://en.wikipedia.org/wiki/Special:Search?go=Go&search=%1" + << "1,o,([Dd][Bb][Uu][Gg]:)(\\w+),http://bugs.debian.org/%2" + << "1,o,(BUG:|bug:)([0-9]+),http://bugs.kde.org/show_bug.cgi?id=%2"; +} + +const QStringList Preferences::autoreplaceList() +{ + return self()->mAutoreplaceList; +} + +void Preferences::setAutoreplaceList(const QStringList newList) +{ + self()->mAutoreplaceList=newList; +} + +void Preferences::clearAutoreplaceList() +{ + self()->mAutoreplaceList.clear(); +} + +// --------------------------- AutoReplace --------------------------- + +void Preferences::setServerGroupList(const Konversation::ServerGroupList& list) +{ + self()->mServerGroupList.clear(); + self()->mServerGroupList = list; + + Konversation::ServerGroupList::iterator it; +} + +void Preferences::addServerGroup(Konversation::ServerGroupSettingsPtr serverGroup) +{ + self()->mServerGroupList.append(serverGroup); +} + +const Konversation::ServerGroupSettingsPtr Preferences::serverGroupById(int id) +{ + if (!self()->mServerGroupList.count()) + { + return 0; + } + + Konversation::ServerGroupList::iterator it; + + for (it = self()->mServerGroupList.begin(); it != self()->mServerGroupList.end(); ++it) + { + if ((*it)->id() == id) + { + return (*it); + } + } + + return 0; +} + +const Konversation::ServerGroupSettingsPtr Preferences::serverGroupByServer(const QString& server) +{ + if (!self()->mServerGroupList.count()) + { + return 0; + } + + Konversation::ServerGroupList::iterator it; + + for (it = self()->mServerGroupList.begin(); it != self()->mServerGroupList.end(); ++it) + { + for (uint i = 0; i != (*it)->serverList().count(); i++) + { + if ((*it)->serverByIndex(i).host().lower() == server) + { + return (*it); + } + } + } + + return 0; +} + +int Preferences::serverGroupIdByName(const QString& serverGroup) +{ + Konversation::ServerGroupList::iterator it; + + for (it = self()->mServerGroupList.begin(); it != self()->mServerGroupList.end(); ++it) + { + if((*it)->name().lower() == serverGroup.lower()) + { + return (*it)->id(); + } + } + + return -1; +} + +bool Preferences::isServerGroup(const QString& server) +{ + Konversation::ServerGroupList::iterator it; + + for(it = self()->mServerGroupList.begin(); it != self()->mServerGroupList.end(); ++it) + { + if((*it)->name().lower() == server.lower()) + { + return true; + } + } + + return false; +} + +void Preferences::removeServerGroup(int id) +{ + if (!self()->mServerGroupList.count()) + { + return; + } + + Konversation::ServerGroupList::iterator it; + + for (it = self()->mServerGroupList.begin(); it != self()->mServerGroupList.end(); ++it) + { + if ((*it)->id() == id) + { + self()->mServerGroupList.remove(it); + + return; + } + } +} + + +const QPtrList Preferences::highlightList() +{ + return self()->mHighlightList; +} + +void Preferences::setHighlightList(QPtrList newList) +{ + self()->mHighlightList.clear(); + self()->mHighlightList=newList; +} + +void Preferences::addHighlight(const QString& newHighlight, +bool regExp, +const QColor &newColor, +const QString& sound, +const QString& autoText) +{ + self()->mHighlightList.append(new Highlight(newHighlight,regExp,newColor,KURL(sound),autoText)); +} + +void Preferences::setIgnoreList(QPtrList newList) +{ + self()->mIgnoreList.clear(); + self()->mIgnoreList=newList; +} + +void Preferences::addIgnore(const QString &newIgnore) +{ + QStringList ignore = QStringList::split(',',newIgnore); + removeIgnore(ignore[0]); + self()->mIgnoreList.append(new Ignore(ignore[0],ignore[1].toInt())); +} + +bool Preferences::removeIgnore(const QString &oldIgnore) +{ + QPtrListIterator ignoreList( self()->mIgnoreList ); + + while (ignoreList.current()) + { + if (ignoreList.current()->getName().lower()==oldIgnore.lower()) + { + self()->mIgnoreList.remove(ignoreList.current()); + return true; + } + ++ignoreList; + } + + return false; +} + +bool Preferences::isIgnored(const QString &nickname) +{ + QPtrListIterator ignoreList( self()->mIgnoreList ); + + while (ignoreList.current()) + { + if (ignoreList.current()->getName().section('!',0,0).lower()==nickname.lower()) + { + return true; + } + ++ignoreList; + } + + return false; +} + +void Preferences::setNotifyList(const QMap &newList) +{ self()->mNotifyList=newList; } + +const QMap Preferences::notifyList() { return self()->mNotifyList; } + +const QStringList Preferences::notifyListByGroupName(const QString& groupName) +{ + int id=serverGroupIdByName(groupName); + if (id && self()->mNotifyList.find(id) != self()->mNotifyList.end()) + return self()->mNotifyList[id]; + else + return QStringList(); +} + +const QString Preferences::notifyStringByGroupName(const QString& groupName) +{ + return notifyListByGroupName(groupName).join(" "); +} + +bool Preferences::addNotify(int serverGroupId, const QString& newPattern) +{ + if (!self()->mNotifyList[serverGroupId].contains(newPattern)) + { + QStringList nicknameList = self()->mNotifyList[serverGroupId]; + nicknameList.append(newPattern); + self()->mNotifyList[serverGroupId] = nicknameList; + return true; + } + return false; +} + +bool Preferences::removeNotify(const QString& groupName, const QString& pattern) +{ + int id=serverGroupIdByName(groupName); + if(!id) return false; + + if (self()->mNotifyList.find(id) != self()->mNotifyList.end()) + { + QStringList nicknameList = self()->mNotifyList[id]; + nicknameList.remove(pattern); + if (nicknameList.isEmpty()) + self()->mNotifyList.remove(id); + else + self()->mNotifyList[id] = nicknameList; + return true; + } + return false; +} + +bool Preferences::isNotify(int serverGroupId, const QString& pattern) +{ + if (self()->mNotifyList.find(serverGroupId) != self()->mNotifyList.end()) + { + QStringList nicknameList = self()->mNotifyList[serverGroupId]; + + if (nicknameList.contains(pattern)) return true; + } + return false; +} + +bool Preferences::hasNotifyList(int serverGroupId) +{ + if (self()->mNotifyList.find(serverGroupId) != self()->mNotifyList.end()) + return true; + else + return false; +} + +// Default identity functions +void Preferences::addIdentity(IdentityPtr identity) { self()->mIdentityList.append(identity); } +void Preferences::removeIdentity(IdentityPtr identity) { self()->mIdentityList.remove(identity); } + +void Preferences::clearIdentityList() +{ + self()->mIdentityList.clear(); +} + +const IdentityList Preferences::identityList() { return self()->mIdentityList; } + +void Preferences::setIdentityList(const IdentityList& list) +{ + self()->mIdentityList.clear(); + self()->mIdentityList = list; +} + +const IdentityPtr Preferences::identityByName(const QString& name) +{ + QValueList identities = identityList(); + QValueList::iterator it = identities.begin(); + + while(it != identities.end()) + { + if((*it)->getName() == name) + { + return (*it); + } + + ++it; + } + + // no self()->matching identity found, return default identity + return identities.first(); +} + +const IdentityPtr Preferences::identityById(int id) +{ + QValueList identList = identityList(); + for(QValueList::iterator it = identList.begin(); it != identList.end(); ++it) + { + if((*it)->id() == id) + { + return (*it); + } + } + + return identList.first(); +} + +QStringList Preferences::defaultAliasList() +{ + // Auto-alias scripts + QStringList scripts = KGlobal::dirs()->findAllResources("data","konversation/scripts/*"); + QFileInfo* fileInfo = new QFileInfo(); + QStringList aliasList; + QString newAlias; + + for (QStringList::ConstIterator it = scripts.begin(); it != scripts.end(); ++it) + { + fileInfo->setFile(*it); + if (fileInfo->isExecutable()) + { + newAlias = (*it).section('/',-1)+' '+"/exec "+(*it).section('/', -1 ); + aliasList.append(newAlias); + + // FIXME: Historically, defaultAliasList() is primarily used to dynamically + // compile a list of installed scripts and generate appropriate aliases for + // them. It's not only used when the alias preferences are reset or initia- + // lized, but also on application start. The following crudely adds two + // aliases when the 'media' script is found, to provide easy access to its + // capability to differentiate between audio and video media. This method + // needs at the very least to be split up in two, or scripts may in the + // future determine what aliases they want to add. + if ((*it).section('/',-1) == "media") + { + aliasList.append("audio /exec media audio"); + aliasList.append("video /exec media video"); + } + } + } + + delete fileInfo; + + return aliasList; +} + + +const QString Preferences::realName() { return self()->mIdentityList[0]->getRealName(); } +void Preferences::setRealName(const QString &name) { self()->mIdentityList[0]->setRealName(name); } + +const QString Preferences::ident() { return self()->mIdentityList[0]->getIdent(); } +void Preferences::setIdent(const QString &ident) { self()->mIdentityList[0]->setIdent(ident); } + +const QString Preferences::partReason() { return self()->mIdentityList[0]->getPartReason(); } +void Preferences::setPartReason(const QString &newReason) { self()->mIdentityList[0]->setPartReason(newReason); } + +const QString Preferences::kickReason() { return self()->mIdentityList[0]->getKickReason(); } +void Preferences::setKickReason(const QString &newReason) { self()->mIdentityList[0]->setKickReason(newReason); } + +bool Preferences::showAwayMessage() { return self()->mIdentityList[0]->getShowAwayMessage(); } +void Preferences::setShowAwayMessage(bool state) { self()->mIdentityList[0]->setShowAwayMessage(state); } + +const QString Preferences::awayMessage() { return self()->mIdentityList[0]->getAwayMessage(); } +void Preferences::setAwayMessage(const QString &newMessage) { self()->mIdentityList[0]->setAwayMessage(newMessage); } +const QString Preferences::unAwayMessage() { return self()->mIdentityList[0]->getReturnMessage(); } +void Preferences::setUnAwayMessage(const QString &newMessage) { self()->mIdentityList[0]->setReturnMessage(newMessage); } + +void Preferences::clearIgnoreList() { self()->mIgnoreList.clear(); } +const QPtrList Preferences::ignoreList() { return self()->mIgnoreList; } + +const QString Preferences::nickname(int index) { return self()->mIdentityList[0]->getNickname(index); } +const QStringList Preferences::nicknameList() { return self()->mIdentityList[0]->getNicknameList(); } +void Preferences::setNickname(int index,const QString &newName) { self()->mIdentityList[0]->setNickname(index,newName); } +void Preferences::setNicknameList(const QStringList &newList) { self()->mIdentityList[0]->setNicknameList(newList); } + +void Preferences::setShowTrayIcon(bool state) +{ + PreferencesBase::setShowTrayIcon(state); + emit self()->updateTrayIcon(); +} + +void Preferences::setTrayNotify(bool state) +{ + PreferencesBase::setTrayNotify(state); + emit self()->updateTrayIcon(); +} + + +void Preferences::setAutoUserhost(bool state) +{ + PreferencesBase::setAutoUserhost(state); +} + +bool Preferences::dialogFlag(const QString& flagName) +{ + KConfig* config=KApplication::kApplication()->config(); + + config->setGroup("Notification self()->Messages"); + + if( !config->readEntry(flagName).isEmpty() ) + return false; + else + return true; +} + +void Preferences::setDialogFlag(const QString& flagName,bool state) +{ + KConfig* config=KApplication::kApplication()->config(); + + config->setGroup("Notification self()->Messages"); + + if(state) + config->deleteEntry(flagName); + else + { + if ( config->readEntry(flagName).isEmpty() ) + config->writeEntry(flagName,"no"); + } + + config->sync(); +} + + +// Channel Encodings +const QString Preferences::channelEncoding(const QString& server,const QString& channel) +{ + return channelEncoding(serverGroupIdByName(server),channel); +} + +const QString Preferences::channelEncoding(int serverGroupId,const QString& channel) +{ + if(self()->mChannelEncodingsMap.contains(serverGroupId)) + if(self()->mChannelEncodingsMap[serverGroupId].contains(channel.lower())) + return self()->mChannelEncodingsMap[serverGroupId][channel.lower()]; + return QString(); +} + +void Preferences::setChannelEncoding(const QString& server,const QString& channel,const QString& encoding) +{ + setChannelEncoding(serverGroupIdByName(server),channel,encoding); +} + +void Preferences::setChannelEncoding(int serverGroupId,const QString& channel,const QString& encoding) +{ + self()->mChannelEncodingsMap[serverGroupId][channel.lower()]=encoding; +} + +const QValueList Preferences::channelEncodingsServerGroupIdList() +{ + return self()->mChannelEncodingsMap.keys(); +} + +const QStringList Preferences::channelEncodingsChannelList(int serverGroupId) +{ + return self()->mChannelEncodingsMap[serverGroupId].keys(); +} + +const QString Preferences::defaultNicknameSortingOrder() +{ + return "qpohv-"; +} + +// override to add %u if needed +QString Preferences::webBrowserCmd() +{ + // add %u to command if it's not in there + QString cmd=self()->mWebBrowserCmd; + if(cmd.find("%u")==-1) cmd+=" %u"; + return cmd; +} + +#include "preferences.moc" diff --git a/konversation/src/config/preferences.h b/konversation/src/config/preferences.h new file mode 100644 index 0000000..ed27d0a --- /dev/null +++ b/konversation/src/config/preferences.h @@ -0,0 +1,169 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2005 Ismail Donmez + Copyright (C) 2005 Peter Simonsson + Copyright (C) 2005 John Tapsell + Copyright (C) 2005-2008 Eike Hein +*/ + +#ifndef PREFERENCES_H +#define PREFERENCES_H + +#include "servergroupsettings.h" +#include "identity.h" +#include "preferences_base.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +/* +Options still to be GUIfied: + +Operator LEDs (int) +OperatorColor (int) +VoiceColor (int) +NoRightsColor (int) +*/ + +class Ignore; +class Highlight; + +class Preferences : public QObject, public PreferencesBase +{ + Q_OBJECT + + protected: + Preferences(); + static Preferences *mSelf; + + public: + + static Preferences *self(); + ~Preferences(); + enum Pages + { + NotifyPage, + ChatWinAppearancePage + }; + static const Konversation::ServerGroupList serverGroupList(); + static void setServerGroupList(const Konversation::ServerGroupList& list); + static void addServerGroup(Konversation::ServerGroupSettingsPtr serverGroup); + static const Konversation::ServerGroupSettingsPtr serverGroupById(int id); + static const Konversation::ServerGroupSettingsPtr serverGroupByServer(const QString& server); + static int serverGroupIdByName(const QString& serverGroup); + static bool isServerGroup(const QString& server); + static void removeServerGroup(int id); + + /** Returns a list of alias set up by default. This is a set of aliases for the scripts found. */ + static QStringList defaultAliasList(); + + //notifylist is in kconfigxt - FIXME + static const QMap notifyList(); + static const QStringList notifyListByGroupName(const QString& groupName); + static const QString notifyStringByGroupName(const QString& groupName); + static void setNotifyList(const QMap& newList); + static bool addNotify(int serverGroupId, const QString& newPattern); + static bool removeNotify(const QString& groupName, const QString& pattern); + static bool isNotify(int serverGroupId, const QString& pattern); + static bool hasNotifyList(int serverGroupId); + + static const QPtrList highlightList(); + static void setHighlightList(QPtrList newList); + static void addHighlight(const QString& newHighlight,bool regExp, const QColor &color,const QString& sound,const QString& autoText); + + /* All of the below work on the first (default) identity in your identity list*/ + static void addIgnore(const QString &newIgnore); + static bool removeIgnore(const QString &oldIgnore); + static bool isIgnored(const QString &nickname); + static void clearIgnoreList(); + static const QPtrList ignoreList(); + static void setIgnoreList(QPtrList newList); + + static const QStringList quickButtonList(); + static const QStringList defaultQuickButtonList(); + static void setQuickButtonList(const QStringList newList); + static void clearQuickButtonList(); + + static const QStringList autoreplaceList(); + static const QStringList defaultAutoreplaceList(); + static void setAutoreplaceList(const QStringList newList); + static void clearAutoreplaceList(); + + static void addIdentity(IdentityPtr identity); + static void removeIdentity(IdentityPtr identity); + static void clearIdentityList(); + static const IdentityList identityList(); + static void setIdentityList(const IdentityList& list); + static const IdentityPtr identityByName(const QString& name); + static const IdentityPtr identityById(int id); + static const QString ident(); + static void setIdent(const QString &ident); + static const QString realName(); + static void setRealName(const QString &name); + static const QString partReason(); + static void setPartReason(const QString &newReason); + static const QString kickReason(); + static void setKickReason(const QString &newReason); + static void setShowAwayMessage(bool state); + static bool showAwayMessage(); + static const QString awayMessage(); + static void setAwayMessage(const QString &newMessage); + static const QString unAwayMessage(); + static void setUnAwayMessage(const QString &newMessage); + static const QString defaultNicknameSortingOrder(); + static const QString nickname(int index); + static const QStringList nicknameList(); + static void setNickname(int index,const QString &newName); + static void setNicknameList(const QStringList &newList); + + static bool dialogFlag(const QString& flagName); + static void setDialogFlag(const QString& flagName,bool state); + + static const QString channelEncoding(const QString& server,const QString& channel); + static const QString channelEncoding(int serverGroupId,const QString& channel); + static void setChannelEncoding(const QString& server,const QString& channel,const QString& encoding); + static void setChannelEncoding(int serverGroupId,const QString& channel,const QString& encoding); + static const QValueList channelEncodingsServerGroupIdList(); + static const QStringList channelEncodingsChannelList(int serverGroupId); + + static void setShowTrayIcon(bool state); + static void setTrayNotify(bool state); + static void setAutoUserhost(bool state); + + static QString webBrowserCmd(); + + signals: + void requestServerConnection(int number); + void requestSaveOptions(); + void autoContinuousWhoChanged(); + void updateTrayIcon(); + + protected: + IdentityPtr mIdentity; + Konversation::ServerGroupList mServerGroupList; + QPtrList mIgnoreList; + QValueList mIdentityList; + QPtrList mHighlightList; + QMap mNotifyList; // network id, list of nicks + QMap< int,QMap > mChannelEncodingsMap; // mChannelEncodingsMap[serverGroupdId][channelName] + QStringList mQuickButtonList; + QStringList mAutoreplaceList; + QString mSortingOrder; +}; +#endif diff --git a/konversation/src/config/preferences_base.kcfgc b/konversation/src/config/preferences_base.kcfgc new file mode 100644 index 0000000..a728d44 --- /dev/null +++ b/konversation/src/config/preferences_base.kcfgc @@ -0,0 +1,8 @@ +ClassName=PreferencesBase +File=konversation.kcfg +GlobalEnums=true +Mutators=true +SetUserTexts=true +Singleton=true +MemberVariables=private +ItemAccessors=true diff --git a/konversation/src/connectionbehavior_preferences.ui b/konversation/src/connectionbehavior_preferences.ui new file mode 100644 index 0000000..c1489ca --- /dev/null +++ b/konversation/src/connectionbehavior_preferences.ui @@ -0,0 +1,187 @@ + +ConnectionBehavior_Config +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. + +Copyright (C) 2005 Peter Simonsson + + + ConnectionBehavior_Config + + + + 0 + 0 + 421 + 240 + + + + + unnamed + + + 0 + + + + kcfg_AutoReconnect + + + Enable Automatic Reconnect + + + true + + + + unnamed + + + + reconnectDelayLabel + + + Reconnect delay: + + + reconnectDelaySpin + + + + + spacer53 + + + Horizontal + + + Expanding + + + + 278 + 20 + + + + + + textLabel1 + + + Reconnection attempts: + + + + + kcfg_ReconnectDelay + + + + + + 120 + + + 1 + + + 9999 + + + seconds + + + + + kcfg_ReconnectCount + + + 100 + + + 0 + + + Unlimited + + + + + spacer53_3 + + + Horizontal + + + Expanding + + + + 280 + 20 + + + + + + + + spacer54 + + + Vertical + + + Expanding + + + + 21 + 60 + + + + + + debugGBox + + + Debug + + + + unnamed + + + + kcfg_RawLog + + + Show raw &log window when connecting + + + + + + + + + + kcfg_AutoReconnect + kcfg_ReconnectDelay + kcfg_ReconnectCount + kcfg_RawLog + + + + + knuminput.h + knuminput.h + knuminput.h + knuminput.h + + diff --git a/konversation/src/connectionmanager.cpp b/konversation/src/connectionmanager.cpp new file mode 100644 index 0000000..bb491c3 --- /dev/null +++ b/konversation/src/connectionmanager.cpp @@ -0,0 +1,580 @@ +/* + 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. +*/ + +/* + Copyright (C) 2008 Eike Hein +*/ + +#include "connectionmanager.h" +#include "connectionsettings.h" +#include "serversettings.h" +#include "servergroupsettings.h" +#include "config/preferences.h" +#include "konversationapplication.h" +#include "konversationmainwindow.h" +#include "statuspanel.h" + +#include + +#include +#include + + +ConnectionManager::ConnectionManager(QObject* parent) : QObject(parent) +{ + connect(this, SIGNAL(requestReconnect(Server*)), this, SLOT(handleReconnect(Server*))); +} + +ConnectionManager::~ConnectionManager() +{ +} + +void ConnectionManager::connectTo(Konversation::ConnectionFlag flag, const QString& target, + const QString& port, const QString& password, const QString& nick, const QString& channel, + bool useSSL) +{ + ConnectionSettings settings; + + if (target.startsWith("irc://")) + decodeIrcUrl(target, settings); + else + { + decodeAddress(target, settings); + + Konversation::ServerSettings server = settings.server(); + + if (!port.isEmpty()) server.setPort(port.toInt()); + + if (!password.isEmpty()) server.setPassword(password); + + if (useSSL) server.setSSLEnabled(true); + + settings.setServer(server); + + if (!nick.isEmpty()) settings.setInitialNick(nick); + + if (!channel.isEmpty()) + { + Konversation::ChannelSettings channelSettings(channel); + + settings.setInitialChannel(channelSettings); + } + } + + connectTo(flag, settings); +} + +void ConnectionManager::connectTo(Konversation::ConnectionFlag flag, int serverGroupId) +{ + ConnectionSettings settings; + + Konversation::ServerGroupSettingsPtr serverGroup; + + serverGroup = Preferences::serverGroupById(serverGroupId); + + if (serverGroup) + { + settings.setServerGroup(serverGroup); + + if (serverGroup->serverList().size() > 0) + settings.setServer(serverGroup->serverList()[0]); + } + + connectTo(flag, settings); +} + +void ConnectionManager::connectTo(Konversation::ConnectionFlag flag, ConnectionSettings& settings) +{ + if (!settings.isValid()) return; + + emit closeServerList(); + + if (flag != Konversation::CreateNewConnection + && reuseExistingConnection(settings, (flag == Konversation::PromptToReuseConnection))) + { + return; + } + + IdentityPtr identity = settings.identity(); + + if (!identity || !validateIdentity(identity)) return; + + KonversationApplication* konvApp = static_cast(kapp); + KonversationMainWindow* mainWindow = konvApp->getMainWindow(); + + Server* server = new Server(this, settings); + + enlistConnection(server->connectionId(), server); + + connect(server, SIGNAL(destroyed(int)), this, SLOT(delistConnection(int))); + + connect(server, SIGNAL(connectionStateChanged(Server*, Konversation::ConnectionState)), + this, SLOT(handleConnectionStateChange(Server*, Konversation::ConnectionState))); + + connect(server, SIGNAL(awayState(bool)), this, SIGNAL(connectionChangedAwayState(bool))); + + connect(server, SIGNAL(nicksNowOnline(Server*, const QStringList&, bool)), + mainWindow, SLOT(setOnlineList(Server*, const QStringList&,bool))); + connect(server, SIGNAL(awayInsertRememberLine(Server*)), + mainWindow, SIGNAL(triggerRememberLines(Server*))); + + connect(mainWindow, SIGNAL(startNotifyTimer(int)), server, SLOT(startNotifyTimer(int))); + + connect(server, SIGNAL(multiServerCommand(const QString&, const QString&)), + konvApp, SLOT(sendMultiServerCommand(const QString&, const QString&))); +} + +void ConnectionManager::enlistConnection(int connectionId, Server* server) +{ + m_connectionList.insert(connectionId, server); +} + +void ConnectionManager::delistConnection(int connectionId) +{ + m_connectionList.remove(connectionId); +} + +void ConnectionManager::handleConnectionStateChange(Server* server, Konversation::ConnectionState state) +{ + emit connectionChangedState(server, state); + + int identityId = server->getIdentity()->id(); + + if (state == Konversation::SSConnected) + { + if (!m_activeIdentities.contains(identityId)) + { + m_activeIdentities.append(identityId); + + emit identityOnline(identityId); + } + } + else if (state != Konversation::SSConnecting) + { + if (m_activeIdentities.contains(identityId)) + { + m_activeIdentities.remove(identityId); + + emit identityOffline(identityId); + } + } + + if (state == Konversation::SSInvoluntarilyDisconnected) + { + // The asynchronous invocation of handleReconnect() makes sure that + // connectionChangedState() is emitted and delivered before it runs + // (and causes the next connection state change to occur). + emit requestReconnect(server); + } +} + +void ConnectionManager::handleReconnect(Server* server) +{ + if (!Preferences::autoReconnect()) return; + + ConnectionSettings settings = server->getConnectionSettings(); + + uint reconnectCount = Preferences::reconnectCount(); + + // For server groups, one iteration over their server list shall count as one + // connection attempt. + if (settings.serverGroup()) + reconnectCount = reconnectCount * settings.serverGroup()->serverList().size(); + + if (reconnectCount == 0 || settings.reconnectCount() < reconnectCount) + { + if (settings.serverGroup() && settings.serverGroup()->serverList().size() > 1) + { + Konversation::ServerList serverList = settings.serverGroup()->serverList(); + + int index = serverList.findIndex(settings.server()); + int size = serverList.size(); + + if (index == size - 1 || index == -1) + settings.setServer(serverList[0]); + else if (index < size - 1) + settings.setServer(serverList[index+1]); + + server->setConnectionSettings(settings); + + server->getStatusView()->appendServerMessage(i18n("Info"), + i18n("Trying to connect to %1 in %2 seconds.") + .arg(settings.server().host()) + .arg(Preferences::reconnectDelay())); + } + else + { + server->getStatusView()->appendServerMessage(i18n("Info"), + i18n("Trying to reconnect to %1 in %2 seconds.") + .arg(settings.server().host()) + .arg(Preferences::reconnectDelay())); + } + + server->getConnectionSettings().incrementReconnectCount(); + + QTimer::singleShot(Preferences::reconnectDelay() * 1000, server, SLOT(connectToIRCServer())); + } + else + server->getStatusView()->appendServerMessage(i18n("Error"), i18n("Reconnection attempts exceeded.")); +} + +void ConnectionManager::quitServers() +{ + QMap::ConstIterator it; + + for (it = m_connectionList.begin(); it != m_connectionList.end(); ++it) + it.data()->quitServer(); +} + +void ConnectionManager::decodeIrcUrl(const QString& url, ConnectionSettings& settings) +{ + if (!url.startsWith("irc://")) return; + + QString mangledUrl = url; + + mangledUrl.remove(QRegExp("^irc:/+")); + + if (mangledUrl.isEmpty()) return; + + // Parsing address and channel. + QStringList mangledUrlSegments; + + mangledUrlSegments = QStringList::split('/', mangledUrl, false); + + // Check for ",isserver". + if (mangledUrlSegments[0].contains(',')) + { + QStringList addressSegments; + bool checkIfServerGroup = true; + + addressSegments = QStringList::split(',', mangledUrlSegments[0], false); + + if (addressSegments.grep("isserver", false).size() > 0) + checkIfServerGroup = false; + + decodeAddress(addressSegments[0], settings, checkIfServerGroup); + } + else + decodeAddress(mangledUrlSegments[0], settings); + + QString channel; + Konversation::ChannelSettings channelSettings; + + // Grabbing channel from in front of potential ?key=value parameters. + if (mangledUrlSegments.size() > 1) + channel = mangledUrlSegments[1].section('?', 0, 0); + + if (!channel.isEmpty()) + { + // Add default prefix to channel if necessary. + if (!channel.contains(QRegExp("^[#+&]{1}"))) + channel = '#' + channel; + + channelSettings.setName(channel); + } + + // Parsing ?key=value parameters. + QString parameterString; + + if (mangledUrlSegments.size() > 1) + parameterString = mangledUrlSegments[1].section('?', 1); + + if (parameterString.isEmpty() && mangledUrlSegments.size() > 2) + parameterString = mangledUrlSegments[2]; + + if (!parameterString.isEmpty()) + { + QRegExp parameterCatcher; + + parameterCatcher.setPattern("pass=([^&]+)"); + + if (parameterCatcher.search(parameterString) != -1) + { + Konversation::ServerSettings server = settings.server(); + + server.setPassword(parameterCatcher.cap(1)); + + settings.setServer(server); + } + + parameterCatcher.setPattern("key=([^&]+)"); + + if (parameterCatcher.search(parameterString) != -1) + channelSettings.setPassword(parameterCatcher.cap(1)); + } + + // Assigning channel. + if (!channelSettings.name().isEmpty()) + settings.setInitialChannel(channelSettings); +} + +void ConnectionManager::decodeAddress(const QString& address, ConnectionSettings& settings, + bool checkIfServerGroup) +{ + QString host; + QString port = "6667"; + + // Full-length IPv6 address with port + // Example: RFC 2732 notation: [2001:0DB8:0000:0000:0000:0000:1428:57ab]:6666 + // Example: Non-RFC 2732 notation: 2001:0DB8:0000:0000:0000:0000:1428:57ab:6666 + if (address.contains(':')==8) + { + host = address.section(':',0,-2).remove("[").remove("]"); + port = address.section(':',-1); + } + // Full-length IPv6 address without port or not-full-length IPv6 address with port + // Example: Without port, RFC 2732 notation: [2001:0DB8:0000:0000:0000:0000:1428:57ab] + // Example: Without port, Non-RFC 2732 notation: 2001:0DB8:0000:0000:0000:0000:1428:57ab + // Example: With port, RFC 2732 notation: [2001:0DB8::1428:57ab]:6666 + else if (address.contains(':')>=4) + { + // Last segment does not end with ], but the next to last does; + // Assume not-full-length IPv6 address with port + // Example: [2001:0DB8::1428:57ab]:6666 + if (address.section(':',0,-2).endsWith("]") && !address.section(':',-1).endsWith("]")) + { + host = address.section(':',0,-2).remove("[").remove("]"); + port = address.section(':',-1); + } + else + { + QString addressCopy = address; + host = addressCopy.remove("[").remove("]"); + } + } + // IPv4 address or ordinary hostname with port + // Example: IPv4 address with port: 123.123.123.123:6666 + // Example: Hostname with port: irc.bla.org:6666 + else if (address.contains(':')==1) + { + host = address.section(':',0,-2); + port = address.section(':',-1); + } + else + host = address; + + // Try to assign server group. + if (checkIfServerGroup && Preferences::isServerGroup(host)) + { + // If host is found to be the name of a server group. + + int serverGroupId = Preferences::serverGroupIdByName(host); + + Konversation::ServerGroupSettingsPtr serverGroup; + + serverGroup = Preferences::serverGroupById(serverGroupId); + + settings.setServerGroup(serverGroup); + + if (serverGroup->serverList().size() > 0) + settings.setServer(serverGroup->serverList()[0]); + } + else + { + if (Preferences::serverGroupByServer(host)) + { + // If the host is found to be part of a server group's server list. + + Konversation::ServerGroupSettingsPtr serverGroup; + + serverGroup = Preferences::serverGroupByServer(host); + + settings.setServerGroup(serverGroup); + } + + Konversation::ServerSettings server; + + server.setHost(host); + server.setPort(port.toInt()); + + settings.setServer(server); + } +} + +bool ConnectionManager::reuseExistingConnection(ConnectionSettings& settings, bool interactive) +{ + Server* dupe = 0; + ConnectionDupe dupeType; + bool doReuse = true; + + KonversationApplication* konvApp = static_cast(kapp); + KonversationMainWindow* mainWindow = konvApp->getMainWindow(); + + QMap::ConstIterator it; + + for (it = m_connectionList.begin(); it != m_connectionList.end(); ++it) + { + if (it.data()->getServerGroup() && settings.serverGroup() + && it.data()->getServerGroup() == settings.serverGroup()) + { + dupe = it.data(); + dupeType = SameServerGroup; + + break; + } + } + + if (!dupe) + { + for (it = m_connectionList.begin(); it != m_connectionList.end(); ++it) + { + if (it.data()->getConnectionSettings().server() == settings.server()) + { + dupe = it.data(); + dupeType = SameServer; + + break; + } + } + } + + if (dupe && interactive) + { + int result = KMessageBox::warningContinueCancel( + mainWindow, + i18n("You are already connected to %1. Do you want to open another connection?") + .arg(dupe->getDisplayName()), + i18n("Already connected to %1").arg(dupe->getDisplayName()), + i18n("Create connection"), + "ReuseExistingConnection"); + + if (result == KMessageBox::Continue) doReuse = false; + } + + if (dupe && doReuse) + { + if (interactive && dupeType == SameServerGroup + && !(dupe->getConnectionSettings().server() == settings.server())) + { + int result = KMessageBox::warningContinueCancel( + mainWindow, + i18n("You are presently connected to %1 via '%2' (port %3). Do you want to switch to '%4' (port %5) instead?") + .arg(dupe->getDisplayName()) + .arg(dupe->getServerName()) + .arg(dupe->getPort()) + .arg(settings.server().host()) + .arg(settings.server().port()), + i18n("Already connected to %1").arg(dupe->getDisplayName()), + i18n("Switch Server"), + "ReconnectWithDifferentServer"); + + if (result == KMessageBox::Continue) + { + dupe->disconnect(); + + dupe->setConnectionSettings(settings); + } + } + + if (!dupe->isConnected()) + { + if (!settings.initialChannel().name().isEmpty()) + dupe->updateAutoJoin(settings.initialChannel()); + + if (!dupe->isConnecting()) + dupe->reconnect(); + } + else + { + if (!settings.initialChannel().name().isEmpty()) + { + dupe->sendJoinCommand(settings.initialChannel().name(), + settings.initialChannel().password()); + } + } + } + + return (dupe && doReuse); +} + +bool ConnectionManager::validateIdentity(IdentityPtr identity, bool interactive) +{ + KonversationApplication* konvApp = static_cast(kapp); + KonversationMainWindow* mainWindow = konvApp->getMainWindow(); + + QString errors; + + if (identity->getIdent().isEmpty()) + errors+=i18n("Please fill in your Ident.
"); + + if (identity->getRealName().isEmpty()) + errors+=i18n("Please fill in your Real name.
"); + + if (identity->getNickname(0).isEmpty()) + errors+=i18n("Please provide at least one Nickname.
"); + + if (!errors.isEmpty()) + { + if (interactive) + { + int result = KMessageBox::warningContinueCancel(mainWindow, + i18n("Your identity \"%1\" is not set up correctly:
%2
") + .arg(identity->getName()).arg(errors), + i18n("Identity Settings"), + i18n("Edit Identity...")); + + if (result == KMessageBox::Continue) + { + identity = mainWindow->editIdentity(identity); + + if (identity && validateIdentity(identity, false)) + return true; + else + return false; + } + else + return false; + } + + return false; + } + + return true; +} + +QPtrList ConnectionManager::getServerList() +{ + QPtrList serverList; + + QMap::ConstIterator it; + + for (it = m_connectionList.begin(); it != m_connectionList.end(); ++it) + serverList.append(it.data()); + + return serverList; +} + +Server* ConnectionManager::getServerByConnectionId(int connectionId) +{ + if (m_connectionList.contains(connectionId)) + return m_connectionList[connectionId]; + else + return 0; +} + +Server* ConnectionManager::getServerByName(const QString& name) +{ + QMap::ConstIterator it; + + for (it = m_connectionList.begin(); it != m_connectionList.end(); ++it) + { + if (it.data()->getDisplayName() == name || it.data()->getServerName() == name) + return it.data(); + } + + return 0; +} + +Server* ConnectionManager::getAnyServer() +{ + if ( m_connectionList.count() > 0) + return m_connectionList[0]; + + return 0; +} + +#include "connectionmanager.moc" diff --git a/konversation/src/connectionmanager.h b/konversation/src/connectionmanager.h new file mode 100644 index 0000000..9ada279 --- /dev/null +++ b/konversation/src/connectionmanager.h @@ -0,0 +1,95 @@ +/* + 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. +*/ + +/* + Copyright (C) 2008 Eike Hein +*/ + +#ifndef CONNECTIONMANAGER_H +#define CONNECTIONMANAGER_H + +#include "server.h" +#include "identity.h" + +#include + + +class ConnectionSettings; + +class ConnectionManager : public QObject +{ + Q_OBJECT + + public: + explicit ConnectionManager(QObject* parent = 0); + ~ConnectionManager(); + + uint connectionCount() const { return m_connectionList.count(); } + + QPtrList getServerList(); + + Server* getServerByConnectionId(int connectionId); + Server* getServerByName(const QString& name); + Server* getAnyServer(); + + void quitServers(); + void toggleGlobalAway(); + + + public slots: + void connectTo(Konversation::ConnectionFlag flag, + const QString& target, + const QString& port = "", + const QString& password = "", + const QString& nick = "", + const QString& channel = "", + bool useSSL = false); + + void connectTo(Konversation::ConnectionFlag flag, int serverGroupId); + void connectTo(Konversation::ConnectionFlag flag, ConnectionSettings& settings); + + + signals: + void connectionChangedState(Server* server, Konversation::ConnectionState state); + + void connectionChangedAwayState(bool away); + + void requestReconnect(Server* server); + + void identityOnline(int identityId); + void identityOffline(int identityId); + + void closeServerList(); + + + private slots: + void delistConnection(int connectionId); + + void handleConnectionStateChange(Server* server, Konversation::ConnectionState state); + + void handleReconnect(Server* server); + + + private: + void enlistConnection(int connectionId, Server* server); + + void decodeIrcUrl(const QString& url, ConnectionSettings& settings); + + void decodeAddress(const QString& address, + ConnectionSettings& settings, + bool checkIfServerGroup = true); + + bool reuseExistingConnection(ConnectionSettings& settings, bool interactive); + bool validateIdentity(IdentityPtr identity, bool interactive = true); + + QMap m_connectionList; + QValueList m_activeIdentities; + + enum ConnectionDupe { SameServer, SameServerGroup }; +}; + +#endif diff --git a/konversation/src/connectionsettings.cpp b/konversation/src/connectionsettings.cpp new file mode 100644 index 0000000..f835406 --- /dev/null +++ b/konversation/src/connectionsettings.cpp @@ -0,0 +1,55 @@ +/* + 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. +*/ + +/* + Copyright (C) 2008 Eike Hein +*/ + +#include "connectionsettings.h" +#include "config/preferences.h" + + +ConnectionSettings::ConnectionSettings() +{ + m_reconnectCount = 0; +} + +ConnectionSettings::~ConnectionSettings() +{ +} + +bool ConnectionSettings::isValid() +{ + if (m_server.host().isEmpty()) return false; + + return true; +} + +QString ConnectionSettings::name() const +{ + if (m_serverGroup) + return m_serverGroup->name(); + else + return m_server.host(); +} + +IdentityPtr ConnectionSettings::identity() const +{ + if (m_serverGroup) + return m_serverGroup->identity(); + + return Preferences::identityById(0); +} + +QString ConnectionSettings::initialNick() const +{ + if (!m_initialNick.isEmpty()) + return m_initialNick; + + return identity()->getNickname(0); +} + diff --git a/konversation/src/connectionsettings.h b/konversation/src/connectionsettings.h new file mode 100644 index 0000000..caa01ce --- /dev/null +++ b/konversation/src/connectionsettings.h @@ -0,0 +1,61 @@ +/* + 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. +*/ + +/* + Copyright (C) 2008 Eike Hein +*/ + +#ifndef CONNECTIONSETTINGS_H +#define CONNECTIONSETTINGS_H + +#include "servergroupsettings.h" +#include "serversettings.h" + +#include + + +class ConnectionSettings +{ + public: + explicit ConnectionSettings(); + ~ConnectionSettings(); + + bool isValid(); + + QString name() const; + + Konversation::ServerSettings server() const { return m_server; } + void setServer(Konversation::ServerSettings server) { m_server = server; } + + Konversation::ServerGroupSettingsPtr serverGroup() const { return m_serverGroup; } + void setServerGroup(Konversation::ServerGroupSettingsPtr serverGroup) { m_serverGroup = serverGroup; } + + IdentityPtr identity() const; + + QString initialNick() const; + void setInitialNick(const QString& nick) { m_initialNick = nick; } + + Konversation::ChannelSettings initialChannel() const { return m_initialChannel; } + void setInitialChannel(Konversation::ChannelSettings& channel) { m_initialChannel = channel; } + + uint reconnectCount() const { return m_reconnectCount; } + void incrementReconnectCount() { m_reconnectCount++; } + void setReconnectCount(uint count) { m_reconnectCount = count; } + + + private: + Konversation::ServerSettings m_server; + Konversation::ServerGroupSettingsPtr m_serverGroup; + + QString m_initialNick; + Konversation::ChannelSettings m_initialChannel; + + uint m_reconnectCount; +}; + + +#endif diff --git a/konversation/src/dcc_preferences.cpp b/konversation/src/dcc_preferences.cpp new file mode 100644 index 0000000..89ad86b --- /dev/null +++ b/konversation/src/dcc_preferences.cpp @@ -0,0 +1,54 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 Ismail Donmez + Copyright (C) 2006 John Tapsell +*/ + +#include "dcc_preferences.h" + +#include +#include +#include + + +DCC_Config::DCC_Config(QWidget *parent, const char* name) : + DCC_ConfigUI(parent,name) +{ + languageChange(); + connect(kcfg_DccMethodToGetOwnIp, SIGNAL(activated(int)), this, SLOT(dccMethodChanged(int))); dccMethodChanged(kcfg_DccMethodToGetOwnIp->currentItem()); + + +} + +void DCC_Config::show() +{ + QWidget::show(); + + kcfg_DccSpecificOwnIp->setEnabled(kcfg_DccMethodToGetOwnIp->currentItem() == 2); +} + +void DCC_Config::dccMethodChanged(int index) +{ + kcfg_DccSpecificOwnIp->setEnabled( index == 2 ); +} + +void DCC_Config::languageChange() +{ + kcfg_DccMethodToGetOwnIp->clear(); + kcfg_DccMethodToGetOwnIp->insertItem(i18n("Network Interface")); + kcfg_DccMethodToGetOwnIp->insertItem(i18n("Reply From IRC Server")); + kcfg_DccMethodToGetOwnIp->insertItem(i18n("Specify Manually")); + +} + +DCC_Config::~DCC_Config() +{ +} +#include "dcc_preferences.moc" + diff --git a/konversation/src/dcc_preferences.h b/konversation/src/dcc_preferences.h new file mode 100644 index 0000000..cfbcf51 --- /dev/null +++ b/konversation/src/dcc_preferences.h @@ -0,0 +1,38 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 Ismail Donmez + Copyright (C) 2006 John Tapsell +*/ + +#ifndef EXDCCPREFERENCES_H +#define EXDCCPREFERENCES_H + +#include "dcc_preferencesui.h" + + +class QComboBox; + +class DCC_Config : public DCC_ConfigUI +{ + Q_OBJECT + + public: + DCC_Config(QWidget* parent, const char* name); + ~DCC_Config(); + + public slots: + virtual void show(); + + + protected slots: + virtual void languageChange(); + void dccMethodChanged(int index); +}; + +#endif diff --git a/konversation/src/dcc_preferencesui.ui b/konversation/src/dcc_preferencesui.ui new file mode 100644 index 0000000..9bfdfcb --- /dev/null +++ b/konversation/src/dcc_preferencesui.ui @@ -0,0 +1,527 @@ + +DCC_ConfigUI +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. + + + DCC_ConfigUI + + + + 0 + 0 + 578 + 517 + + + + DCC_Settings + + + + unnamed + + + 0 + + + + dccPathLbl + + + Download &folder: + + + kcfg_DccPath + + + + + kcfg_DccPath + + + + 7 + 5 + 0 + 0 + + + + 2 + + + + + kcfg_DccAddPartner + + + &Add sender to file name + + + + + kcfg_DccCreateFolder + + + Cr&eate folder for sender + + + + + kcfg_DccSpaceToUnderscore + + + Convert spaces in file names to underscores before sending + + + + + + + + kcfg_DccAutoGet + + + Automaticall&y accept download offer + + + + + kcfg_DccAutoResume + + + Au&tomatically resume download + + + + + kcfg_DccFastSend + + + Enable fast DCC send (Might &not work with all clients) + + + + + spacer4_2 + + + Vertical + + + Expanding + + + + 20 + 16 + + + + + + textLabel6 + + + Buffer si&ze: + + + kcfg_DccBufferSize + + + + + textLabel7 + + + DCC send t&imeout: + + + kcfg_DccSendTimeout + + + + + kcfg_DccIPv4Fallback + + + Fallback to an IPv&4 interface for DCC send: + + + If this option enabled dcc transfers for IPv6 connections will be done over IPv4 interface set here + + + + + kcfg_DccBufferSize + + + bytes + + + 65536 + + + 512 + + + 128 + + + + + kcfg_DccSendTimeout + + + sec + + + 300 + + + 1 + + + + + kcfg_DccIPv4FallbackIface + + + false + + + + + kcfg_DccPassiveSend + + + Enable passive DCC send + + + + + + + + spacer5 + + + Horizontal + + + Maximum + + + + 70 + 20 + + + + + + spacer3 + + + Horizontal + + + Expanding + + + + 70 + 20 + + + + + + spacer3_2 + + + Horizontal + + + Expanding + + + + 70 + 20 + + + + + + groupBox1 + + + IP + + + + unnamed + + + + kcfg_DccSpecificOwnIp + + + + + textLabel4 + + + &Method to get own IP: + + + kcfg_DccMethodToGetOwnIp + + + + + ownIP + + + O&wn IP: + + + kcfg_DccSpecificOwnIp + + + + + kcfg_DccMethodToGetOwnIp + + + + + + + groupBox2 + + + Ports + + + + unnamed + + + + kcfg_DccSpecificChatPorts + + + Enable specific p&orts for DCC chat: + + + + + spacer6 + + + Horizontal + + + Expanding + + + + 50 + 21 + + + + + + kcfg_DccChatPortsFirst + + + false + + + 65535 + + + 1026 + + + + + textLabel2_2 + + + false + + + to + + + AlignCenter + + + + + kcfg_DccChatPortsLast + + + false + + + 65535 + + + 1027 + + + + + kcfg_DccSpecificSendPorts + + + Enable specific &ports for DCC transfer server: + + + + + spacer4 + + + Horizontal + + + Expanding + + + + 50 + 21 + + + + + + kcfg_DccSendPortsFirst + + + false + + + 65535 + + + 1026 + + + + + textLabel1_2 + + + false + + + to + + + AlignCenter + + + + + kcfg_DccSendPortsLast + + + false + + + 65535 + + + 1027 + + + + + + + + + + + kcfg_DccSpecificSendPorts + toggled(bool) + kcfg_DccSendPortsFirst + setEnabled(bool) + + + kcfg_DccSpecificSendPorts + toggled(bool) + textLabel1_2 + setEnabled(bool) + + + kcfg_DccSpecificSendPorts + toggled(bool) + kcfg_DccSendPortsLast + setEnabled(bool) + + + kcfg_DccSpecificChatPorts + toggled(bool) + kcfg_DccChatPortsFirst + setEnabled(bool) + + + kcfg_DccSpecificChatPorts + toggled(bool) + textLabel2_2 + setEnabled(bool) + + + kcfg_DccSpecificChatPorts + toggled(bool) + kcfg_DccChatPortsLast + setEnabled(bool) + + + kcfg_DccIPv4Fallback + toggled(bool) + kcfg_DccIPv4FallbackIface + setEnabled(bool) + + + + kcfg_DccPath + kcfg_DccAddPartner + kcfg_DccCreateFolder + kcfg_DccSpaceToUnderscore + kcfg_DccAutoGet + kcfg_DccAutoResume + kcfg_DccFastSend + kcfg_DccPassiveSend + kcfg_DccIPv4Fallback + kcfg_DccIPv4FallbackIface + kcfg_DccSendTimeout + kcfg_DccBufferSize + kcfg_DccMethodToGetOwnIp + kcfg_DccSpecificOwnIp + kcfg_DccSpecificSendPorts + kcfg_DccSendPortsFirst + kcfg_DccSendPortsLast + kcfg_DccSpecificChatPorts + kcfg_DccChatPortsFirst + kcfg_DccChatPortsLast + + + + kurlrequester.h + klineedit.h + kpushbutton.h + klineedit.h + + diff --git a/konversation/src/dccchat.cpp b/konversation/src/dccchat.cpp new file mode 100644 index 0000000..37b8b6f --- /dev/null +++ b/konversation/src/dccchat.cpp @@ -0,0 +1,473 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2006 Eike Hein + Copyright (C) 2004,2007 Shintaro Matsuoka +*/ + +#include "dccchat.h" +#include "dcccommon.h" +#include "konversationapplication.h" +#include "konversationmainwindow.h" +#include "irccharsets.h" +#include "ircview.h" +#include "ircviewbox.h" +#include "ircinput.h" +#include "topiclabel.h" +#include "server.h" +#include "channel.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DCCCHAT_BUFFER_SIZE 1024 + + +DccChat::DccChat(QWidget* parent, bool listen, Server* server, const QString& ownNick, const QString& partnerNick, const QString& partnerHost, int partnerPort) + : ChatWindow(parent) +{ + kdDebug() << "DccChat::DccChat() [BEGIN]" << endl; + + m_dccSocket = 0; + m_listenSocket = 0; + + m_ownNick = ownNick; + + m_partnerNick = partnerNick; + m_partnerHost = partnerHost; + m_partnerPort = partnerPort; + + setType(ChatWindow::DccChat); + setChannelEncodingSupported(true); + + m_headerSplitter = new QSplitter(Qt::Vertical, this); + + m_sourceLine = new Konversation::TopicLabel(m_headerSplitter); + + IRCViewBox* ircViewBox = new IRCViewBox(m_headerSplitter, NULL); + setTextView(ircViewBox->ircView()); + + m_dccChatInput = new IRCInput(this); + getTextView()->installEventFilter(m_dccChatInput); + m_dccChatInput->setEnabled( false ); + + ChatWindow::setName( '-' + m_partnerNick + '-' ); + ChatWindow::setLogfileName( '-' + m_partnerNick + '-' ); + + QPopupMenu* popup = textView->getPopup(); + + if (popup) + { + KAction* action = KonversationApplication::instance()->getMainWindow()->actionCollection()->action("open_logfile"); + + if (action) + { + popup->insertSeparator(); + action->plug(popup); + } + } + + // connect the signals and slots + connect( m_dccChatInput, SIGNAL( submit() ), this, SLOT( dccChatTextEntered() ) ); + connect( m_dccChatInput, SIGNAL( textPasted( const QString& ) ), this, SLOT( textPasted( const QString& ) ) ); + + connect( getTextView(), SIGNAL( textPasted(bool) ), m_dccChatInput, SLOT( paste(bool) ) ); + connect( getTextView(), SIGNAL( gotFocus() ), m_dccChatInput, SLOT( setFocus() ) ); + connect( getTextView(), SIGNAL( autoText(const QString&) ), this, SLOT( sendDccChatText( const QString& ) ) ); + + if (listen) + { + listenForPartner(); + QString ownNumericalIp = DccCommon::textIpToNumericalIp( DccCommon::getOwnIp( server ) ); + server->requestDccChat( m_partnerNick, ownNumericalIp, QString::number( m_ownPort ) ); + } + else + { + connectToPartner(); + } + + kdDebug() << "DccChat::DccChat() [END]" << endl; + + updateAppearance(); +} + +DccChat::~DccChat() +{ + kdDebug() << "DccChat::~DccChat()" << endl; + if(m_dccSocket) + m_dccSocket->close(); + if(m_listenSocket) + m_listenSocket->close(); +} + +void DccChat::listenForPartner() +{ + kdDebug() << "DccChat::listenForPartner() [BEGIN]" << endl; + + // Set up server socket + QString failedReason; + if ( Preferences::dccSpecificChatPorts() ) + m_listenSocket = DccCommon::createServerSocketAndListen( this, &failedReason, Preferences::dccChatPortsFirst(), Preferences::dccChatPortsLast() ); + else + m_listenSocket = DccCommon::createServerSocketAndListen( this, &failedReason ); + if ( !m_listenSocket ) + { + getTextView()->appendServerMessage( i18n( "DCC" ), i18n( "Could not open a socket for listening: %1" ).arg( failedReason ) ); + return; + } + + connect( m_listenSocket, SIGNAL(readyAccept()), this, SLOT(heardPartner()) ); + + // Get our own port number + m_ownPort = DccCommon::getServerSocketPort( m_listenSocket ); + kdDebug() << "DccChat::listenForPartner(): using port " << m_ownPort << endl; + + getTextView()->appendServerMessage( i18n("DCC"), i18n("Offering DCC Chat connection to %1 on port %2...").arg( m_partnerNick ).arg( m_ownPort ) ); + m_sourceLine->setText(i18n( "DCC chat with %1 on port %2." ).arg( m_partnerNick ).arg( m_ownPort ) ); + kdDebug() << "DccChat::listenForPartner() [END]" << endl; +} + +void DccChat::connectToPartner() +{ + QHostAddress ip; + + ip.setAddress(m_partnerHost.toUInt()); + m_partnerHost=ip.toString(); + + getTextView()->appendServerMessage( i18n( "DCC" ), i18n( "%1 = nickname, %2 = IP, %3 = port", + "Establishing DCC Chat connection to %1 (%2:%3)..." ).arg( m_partnerNick ).arg( m_partnerHost ).arg( m_partnerPort ) ); + + m_sourceLine->setText( i18n( "%1 = nickname, %2 = IP, %3 = port", "DCC chat with %1 on %2:%3." ).arg( m_partnerNick ).arg( host ).arg( m_partnerPort ) ); + + m_dccSocket = new KNetwork::KStreamSocket( m_partnerHost, QString::number( m_partnerPort ), this ); + + m_dccSocket->setBlocking(false); + m_dccSocket->setFamily(KNetwork::KResolver::InetFamily); + m_dccSocket->enableRead(false); + m_dccSocket->enableWrite(false); + m_dccSocket->setTimeout(10000); + m_dccSocket->blockSignals(false); + + connect( m_dccSocket, SIGNAL( hostFound() ), this, SLOT( lookupFinished() ) ); + connect( m_dccSocket, SIGNAL( connected( const KResolverEntry& ) ), this, SLOT( dccChatConnectionSuccess() ) ); + connect( m_dccSocket, SIGNAL( gotError( int ) ), this, SLOT( dccChatBroken( int ) ) ); + connect( m_dccSocket, SIGNAL( readyRead() ), this, SLOT( readData() ) ); + connect( m_dccSocket, SIGNAL( closed() ), this, SLOT( socketClosed() ) ); + + m_dccSocket->connect(); + +#if 0 + //getTextView()->appendServerMessage(i18n("DCC"),i18n("Looking for host %1...").arg(host)); +#endif + +} + +void DccChat::lookupFinished() +{ + +#if 0 + //getTextView()->appendServerMessage(i18n("DCC"),i18n("Host found, connecting...")); +#endif + +} + +void DccChat::dccChatConnectionSuccess() +{ + getTextView()->appendServerMessage( i18n( "DCC" ), i18n( "Established DCC Chat connection to %1." ).arg( m_partnerNick ) ); + m_dccSocket->enableRead(true); + m_dccChatInput->setEnabled(true); +} + +void DccChat::dccChatBroken(int error) +{ + getTextView()->appendServerMessage(i18n("Error"),i18n("Connection broken, error code %1.").arg(error)); + m_dccSocket->enableRead(false); + m_dccSocket->blockSignals(true); + m_dccSocket->close(); +} + +void DccChat::readData() +{ + kdDebug() << k_funcinfo << ( m_listenSocket == 0 ) << " BEGIN" << endl; + int available=0; + int actual=0; + char* buffer=0; + QString line; + QTextCodec* codec = Konversation::IRCCharsets::self()->codecForName(m_encoding.isEmpty() ? Konversation::IRCCharsets::self()->encodingForLocale() : m_encoding); + + available = m_dccSocket->bytesAvailable(); + if( available > 0 ) + { + buffer = new char[ available + 1 ]; + actual = m_dccSocket->readBlock( buffer, available ); + buffer[ actual ] = 0; + line.append( codec->toUnicode( buffer ) ); + delete[] buffer; + + QStringList lines = QStringList::split( '\n', line ); + + for( QStringList::iterator itLine = lines.begin() ; itLine != lines.end() ; itLine++ ) + { + if( (*itLine).startsWith( "\x01" ) ) + { + // cut out the CTCP command + QString ctcp = (*itLine).mid( 1, (*itLine).find( 1, 1 ) - 1 ); + + QString ctcpCommand = ctcp.section( " ", 0, 0 ); + QString ctcpArgument = ctcp.section( " ", 1 ); + + if( ctcpCommand.lower() == "action" ) + appendAction( m_partnerNick, ctcpArgument ); + else + getTextView()->appendServerMessage( i18n( "CTCP" ), i18n( "Received unknown CTCP-%1 request from %2" ).arg( ctcp ).arg( m_partnerNick ) ); + } + else getTextView()->append( m_partnerNick, *itLine ); + } // endfor + } else { + dccChatBroken(m_dccSocket->error()); + } + + kdDebug() << k_funcinfo << " END" << endl; +} + +void DccChat::dccChatTextEntered() +{ + QString line = m_dccChatInput->text(); + m_dccChatInput->setText(""); + if ( line.lower() == Preferences::commandChar()+"clear" ) + { + textView->clear(); + } + else if ( !line.isEmpty() ) + { + sendDccChatText(line); + } +} + +void DccChat::sendDccChatText(const QString& sendLine) +{ + kdDebug() << k_funcinfo << " BEGIN" << endl; + // create a work copy + QString output(sendLine); + QString cc=Preferences::commandChar(); + + if(!output.isEmpty()) + { + QStringList lines = QStringList::split('\n',output); + // wrap socket into a stream + QTextStream stream(m_dccSocket); + // init stream props + stream.setCodec(Konversation::IRCCharsets::self()->codecForName(m_encoding.isEmpty() ? Konversation::IRCCharsets::self()->encodingForLocale() : m_encoding)); + + for( QStringList::iterator itLine = lines.begin() ; itLine != lines.end() ; itLine++ ) + { + QString line( *itLine ); + + // replace aliases and wildcards + // if(filter.replaceAliases(line)) line=server->parseWildcards(line,nick,getName(),QString::null,QString::null,QString::null); + + // line=filter.parse(nick,line,getName()); + + // convert /me actions + QString cmd=line.section(' ', 0,0).lower(); + if (cmd == cc+"me") + { + appendAction( m_ownNick, line.section( " ", 1 ) ); + line=QString("\x01%1 %2\x01").arg("ACTION").arg(line.section(" ",1)); + } + else if (cmd == cc+"close") + { + closeYourself(false); + return; + } + else + getTextView()->append( m_ownNick, line ); + + stream << line << endl; + } // endfor + + // detach stream + stream.unsetDevice(); + } + kdDebug() << k_funcinfo << " END" << endl; +} + +void DccChat::heardPartner() +{ + m_dccSocket = static_cast( m_listenSocket->accept() ); + + if( !m_dccSocket ) + { + getTextView()->appendServerMessage( i18n( "Error" ),i18n( "Could not accept the client." ) ); + return; + } + + connect( m_dccSocket, SIGNAL( readyRead() ), this, SLOT( readData() ) ); + connect( m_dccSocket, SIGNAL( closed() ), this, SLOT( socketClosed() ) ); + connect( m_dccSocket, SIGNAL( gotError( int ) ), this, SLOT( dccChatBroken( int ) ) ); + + // the listen socket isn't needed anymore + disconnect( m_listenSocket, 0, 0, 0 ); + m_listenSocket->close(); + m_listenSocket = 0; + + m_dccSocket->enableRead(true); + m_dccChatInput->setEnabled(true); + + getTextView()->appendServerMessage( i18n( "DCC" ), i18n( "Established DCC Chat connection to %1." ).arg( m_partnerNick ) ); +} + +void DccChat::socketClosed() +{ + getTextView()->appendServerMessage(i18n("DCC"),"Connection closed."); + m_dccChatInput->setEnabled(false); + m_dccSocket = 0; +} + +void DccChat::textPasted(const QString& text) +{ + sendDccChatText(text); +} + +void DccChat::childAdjustFocus() +{ + m_dccChatInput->setFocus(); +} + +bool DccChat::canBeFrontView() +{ + return true; +} + +bool DccChat::searchView() +{ + return true; +} + +int DccChat::getOwnPort() +{ + return m_ownPort; +} + +QString DccChat::getTextInLine() +{ + return m_dccChatInput->text(); +} + +void DccChat::appendInputText( const QString& s, bool fromCursor ) +{ + if(!fromCursor) + { + m_dccChatInput->append(s); + } + else + { + int para = 0, index = 0; + m_dccChatInput->getCursorPosition(¶, &index); + m_dccChatInput->insertAt(s, para, index); + m_dccChatInput->setCursorPosition(para, index + s.length()); + } +} + +//FIXME uh... where is the confimation for this? +bool DccChat::closeYourself(bool) +{ + deleteLater(); + return true; +} + +void DccChat::setChannelEncoding(const QString& encoding) // virtual +{ + m_encoding = encoding; +} + +QString DccChat::getChannelEncoding() // virtual +{ + return m_encoding; +} + +QString DccChat::getChannelEncodingDefaultDesc() // virtual +{ + return i18n("Default ( %1 )").arg(Konversation::IRCCharsets::self()->encodingForLocale()); +} + +void DccChat::showEvent(QShowEvent* /* event */) +{ + if(m_initialShow) { + m_initialShow = false; + QValueList sizes; + sizes << m_sourceLine->sizeHint().height() << (height() - m_sourceLine->sizeHint().height()); + m_headerSplitter->setSizes(sizes); + } +} + +void DccChat::updateAppearance() +{ + QColor fg; + QColor bg; + + if(Preferences::inputFieldsBackgroundColor()) + { + fg=Preferences::color(Preferences::ChannelMessage); + bg=Preferences::color(Preferences::TextViewBackground); + } + else + { + fg=colorGroup().foreground(); + bg=colorGroup().base(); + } + + m_dccChatInput->unsetPalette(); + m_dccChatInput->setPaletteForegroundColor(fg); + m_dccChatInput->setPaletteBackgroundColor(bg); + + getTextView()->unsetPalette(); + + if(Preferences::showBackgroundImage()) + { + getTextView()->setViewBackground(Preferences::color(Preferences::TextViewBackground), + Preferences::backgroundImage()); + } + else + { + getTextView()->setViewBackground(Preferences::color(Preferences::TextViewBackground), + QString()); + } + + if (Preferences::customTextFont()) + { + getTextView()->setFont(Preferences::textFont()); + m_dccChatInput->setFont(Preferences::textFont()); + } + else + { + getTextView()->setFont(KGlobalSettings::generalFont()); + m_dccChatInput->setFont(KGlobalSettings::generalFont()); + } + + ChatWindow::updateAppearance(); +} + +#include "dccchat.moc" diff --git a/konversation/src/dccchat.h b/konversation/src/dccchat.h new file mode 100644 index 0000000..d4a5f13 --- /dev/null +++ b/konversation/src/dccchat.h @@ -0,0 +1,102 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2006 Eike Hein +*/ + +#ifndef DCCCHAT_H +#define DCCCHAT_H + +#include "chatwindow.h" + + +class QSplitter; + +class IRCInput; +class KLineEdit; +class Server; + +namespace KNetwork +{ + class KServerSocket; + class KStreamSocket; +} + +namespace Konversation +{ + class TopicLabel; +} + +class DccChat : public ChatWindow +{ + Q_OBJECT + + public: + DccChat(QWidget* parent, bool listen, Server* server, const QString& ownNick, const QString& partnerNick, const QString& partnerHost = QString(), int partnerPort = 0); + ~DccChat(); + + virtual QString getTextInLine(); + virtual bool closeYourself(bool askForConfirmation=true); + virtual bool canBeFrontView(); + virtual bool searchView(); + + int getOwnPort(); + + virtual void setChannelEncoding(const QString& encoding); + virtual QString getChannelEncoding(); + virtual QString getChannelEncodingDefaultDesc(); + + virtual bool isInsertSupported() { return true; } + + QString getOwnNick() { return m_ownNick; } + + public slots: + void appendInputText(const QString& s, bool fromCursor); + void updateAppearance(); + + protected slots: + void lookupFinished(); + void dccChatConnectionSuccess(); + void dccChatBroken(int error); + void readData(); + void dccChatTextEntered(); + void sendDccChatText(const QString& sendLine); + void textPasted(const QString& text); + void heardPartner(); + void socketClosed(); + + protected: + void listenForPartner(); + void connectToPartner(); + + virtual void showEvent(QShowEvent* event); + + /** Called from ChatWindow adjustFocus */ + virtual void childAdjustFocus(); + + QString m_ownNick; + QString m_partnerNick; + QString m_partnerHost; + int m_partnerPort; + QString host; + + //QString m_ip; + int m_ownPort; + + QSplitter* m_headerSplitter; + Konversation::TopicLabel* m_sourceLine; + IRCInput* m_dccChatInput; + KNetwork::KStreamSocket* m_dccSocket; + KNetwork::KServerSocket* m_listenSocket; + + QString m_encoding; + + bool m_initialShow; +}; +#endif diff --git a/konversation/src/dcccommon.cpp b/konversation/src/dcccommon.cpp new file mode 100644 index 0000000..d03548d --- /dev/null +++ b/konversation/src/dcccommon.cpp @@ -0,0 +1,118 @@ +/* + 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. +*/ + +/* + Copyright (C) 2007 Shintaro Matsuoka +*/ + +#include "dcccommon.h" +#include "channel.h" +#include "preferences.h" +#include "server.h" + +#include + +#include + +#include +#include +#include + + +QString DccCommon::textIpToNumericalIp( const QString& ipString ) +{ + QHostAddress ip; + ip.setAddress( ipString ); + + return QString::number( ip.ip4Addr() ); +} + +QString DccCommon::numericalIpToTextIp( const QString& numericalIp ) +{ + QHostAddress ip; + ip.setAddress( numericalIp.toULong() ); + + return ip.toString(); +} + +QString DccCommon::getOwnIp( Server* server ) +{ + QString ownIp; + int methodId = Preferences::dccMethodToGetOwnIp(); + + if ( methodId == 1 && server ) + { + // by the WELCOME message or the USERHOST message from the server + ownIp = server->getOwnIpByServerMessage(); + } + else if ( methodId == 2 && !Preferences::dccSpecificOwnIp().isEmpty() ) + { + // manual + KNetwork::KResolverResults res = KNetwork::KResolver::resolve(Preferences::dccSpecificOwnIp(), ""); + if(res.error() == KResolver::NoError && res.size() > 0) + { + ownIp = res.first().address().nodeName(); + } + } + + // fallback or methodId == 3 (network interface) + if ( ownIp.isEmpty() && server ) + { + ownIp = server->getOwnIpByNetworkInterface(); + } + + kdDebug() << "DccCommon::getOwnIp(): " << ownIp << endl; + return ownIp; +} + +KNetwork::KServerSocket* DccCommon::createServerSocketAndListen( QObject* parent, QString* failedReason, int minPort, int maxPort ) +{ + KNetwork::KServerSocket* socket = new KNetwork::KServerSocket( parent ); + socket->setFamily( KNetwork::KResolver::InetFamily ); + + if ( minPort > 0 && maxPort >= minPort ) // ports are configured manually + { + // set port + bool found = false; // whether succeeded to set port + for ( int port = minPort; port <= maxPort ; ++port ) + { + socket->setAddress( QString::number( port ) ); + bool success = socket->listen(); + if ( ( found = ( success && socket->error() == KNetwork::KSocketBase::NoError ) ) ) + break; + socket->close(); + } + if ( !found ) + { + if ( failedReason ) + *failedReason = i18n( "No vacant port" ); + delete socket; + return 0; + } + } + else + { + // Let the operating system choose a port + socket->setAddress( "0" ); + if ( !socket->listen() ) + { + if ( failedReason ) + *failedReason = i18n( "Could not open a socket" ); + delete socket; + return 0; + } + } + + return socket; +} + +int DccCommon::getServerSocketPort( KNetwork::KServerSocket* serverSocket ) +{ + KNetwork::KSocketAddress ipAddr = serverSocket->localAddress(); + const struct sockaddr_in* socketAddress = (sockaddr_in*)ipAddr.address(); + return ntohs( socketAddress->sin_port ); +} diff --git a/konversation/src/dcccommon.h b/konversation/src/dcccommon.h new file mode 100644 index 0000000..f3e8220 --- /dev/null +++ b/konversation/src/dcccommon.h @@ -0,0 +1,48 @@ +/* + 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. +*/ + +/* + Copyright (C) 2007 Shintaro Matsuoka +*/ + +#ifndef DCCCOMMON_H +#define DCCCOMMON_H + +#include + +class QObject; + +namespace KNetwork +{ + class KServerSocket; +} + +class Server; + +class DccCommon +{ + public: + // converts an IP text like "127.0.0.1" to a number. + static QString textIpToNumericalIp( const QString& ipString ); + + // converts a numerical IP text like "12345678" to a normal IP text. + static QString numericalIpToTextIp( const QString& numericalIp ); + + // returns the self IP following the setting. + static QString getOwnIp( Server* server = 0 ); + + // creates an instance of KNetwork::ServerSocket following the DCC settings + static KNetwork::KServerSocket* createServerSocketAndListen( QObject* parent = 0, QString* failedReason = 0, int minPort = 0, int maxPort = 0 ); + + // returns the port number from a server socket + static int getServerSocketPort( KNetwork::KServerSocket* serverSocket ); + + private: + DccCommon(); +}; + +#endif // DCCCOMMON_H diff --git a/konversation/src/dccrecipientdialog.cpp b/konversation/src/dccrecipientdialog.cpp new file mode 100644 index 0000000..8c86caf --- /dev/null +++ b/konversation/src/dccrecipientdialog.cpp @@ -0,0 +1,100 @@ +/* + 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. +*/ + +/* + lets the user choose a nick from the list + begin: Sam Dez 7 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include "dccrecipientdialog.h" + +#include + +#include +#include +#include + + +QString DccRecipientDialog::selectedNickname; // static + +DccRecipientDialog::DccRecipientDialog(QWidget* parent, const QStringList &list,const QSize &size) : + KDialogBase(parent,"dcc_recipient_dialog",true,i18n("Select Recipient"), + KDialogBase::Ok | KDialogBase::Cancel,KDialogBase::Ok,true) +{ + // Create the top level widget + QWidget* page=new QWidget(this); + setMainWidget(page); + // Add the layout to the widget + QVBoxLayout* dialogLayout=new QVBoxLayout(page); + dialogLayout->setSpacing(spacingHint()); + // Add the nickname list widget + KListBox* nicknameList=new KListBox(page,"recipient_list"); + + nicknameList->insertStringList(list); + nicknameList->sort(true); + + nicknameInput=new KLineEdit(page,"nickname_input"); + + dialogLayout->addWidget(nicknameList); + dialogLayout->addWidget(nicknameInput); + + connect(nicknameList,SIGNAL (highlighted(QListBoxItem*)),this,SLOT (newNicknameSelected(QListBoxItem*)) ); + connect(nicknameList,SIGNAL (doubleClicked(QListBoxItem*)),this,SLOT (newNicknameSelectedQuit(QListBoxItem*)) ); + + setButtonOK(KGuiItem(i18n("&OK"),"button_ok",i18n("Select nickname and close the window"))); + setButtonCancel(KGuiItem(i18n("&Cancel"),"button_cancel",i18n("Close the window without changes"))); + + setInitialSize(size); + show(); +} + +DccRecipientDialog::~DccRecipientDialog() +{ +} + +QString DccRecipientDialog::getSelectedNickname() +{ + return selectedNickname; +} + +void DccRecipientDialog::newNicknameSelected(QListBoxItem* item) +{ + nicknameInput->setText(item->text()); +} + +void DccRecipientDialog::newNicknameSelectedQuit(QListBoxItem* item) +{ + newNicknameSelected(item); + selectedNickname=nicknameInput->text(); + + delayedDestruct(); +} + +void DccRecipientDialog::slotCancel() +{ + selectedNickname=QString(); + KDialogBase::slotCancel(); +} + +void DccRecipientDialog::slotOk() +{ + selectedNickname=nicknameInput->text(); + KDialogBase::slotOk(); +} + +QString DccRecipientDialog::getNickname(QWidget* parent, const QStringList& list) +{ + QSize size; // TODO: get it from Preferences + DccRecipientDialog dlg(parent,list,size); + dlg.exec(); + + return dlg.getSelectedNickname(); +} + +#include "dccrecipientdialog.moc" diff --git a/konversation/src/dccrecipientdialog.h b/konversation/src/dccrecipientdialog.h new file mode 100644 index 0000000..94d77ca --- /dev/null +++ b/konversation/src/dccrecipientdialog.h @@ -0,0 +1,47 @@ +/* + 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. +*/ + +/* + lets the user choose a nick from the list + begin: Sam Dez 7 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#ifndef DCCRECIPIENTDIALOG_H +#define DCCRECIPIENTDIALOG_H + +#include + + +class KLineEdit; + +class DccRecipientDialog : public KDialogBase +{ + Q_OBJECT + + public: + DccRecipientDialog(QWidget* parent, const QStringList &list, const QSize &size); + ~DccRecipientDialog(); + + static QString getNickname(QWidget* parent, const QStringList& list); + + protected slots: + void newNicknameSelected(QListBoxItem* item); + // KDE double click + void newNicknameSelectedQuit(QListBoxItem* item); + + void slotOk(); + void slotCancel(); + + protected: + QString getSelectedNickname(); + static QString selectedNickname; + + KLineEdit* nicknameInput; +}; +#endif diff --git a/konversation/src/dccresumedialog.cpp b/konversation/src/dccresumedialog.cpp new file mode 100644 index 0000000..b8376b8 --- /dev/null +++ b/konversation/src/dccresumedialog.cpp @@ -0,0 +1,198 @@ +/* + 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. +*/ + +/* + Copyright (C) 2004 Dario Abatianni + Copyright (C) 2004 Shintaro Matsuoka +*/ + +#include "dccresumedialog.h" +#include "dcctransferrecv.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + + +DccResumeDialog::ReceiveAction DccResumeDialog::ask(DccTransferRecv* item, const QString& message, int enabledActions, ReceiveAction defaultAction) +{ + int enabledButtonCodes = 0; + KDialogBase::ButtonCode defaultButtonCode = KDialogBase::Ok; + + if(enabledActions & RA_Rename || enabledActions & RA_Overwrite) + enabledButtonCodes |= KDialogBase::Ok; + if(enabledActions & RA_Resume) + enabledButtonCodes |= KDialogBase::User1; + if(enabledActions & RA_Cancel) + enabledButtonCodes |= KDialogBase::Cancel; + + if(defaultAction == RA_Rename || defaultAction == RA_Overwrite) + defaultButtonCode = KDialogBase::Ok; + else if(defaultAction == RA_Resume) + defaultButtonCode = KDialogBase::User1; + else if(defaultAction == RA_Cancel) + defaultButtonCode = KDialogBase::Cancel; + + DccResumeDialog dlg(item, i18n("DCC Receive Question"), message, enabledActions, enabledButtonCodes, defaultButtonCode); + dlg.exec(); + + ReceiveAction ra = dlg.m_selectedAction; + + if(ra == RA_Rename) + item->setFileURL( dlg.m_urlreqFileURL->url() ); + + return ra; +} + +DccResumeDialog::DccResumeDialog(DccTransferRecv* item, const QString& caption, const QString& message, int enabledActions, int enabledButtonCodes, + KDialogBase::ButtonCode defaultButtonCode) +: KDialogBase(0, "dcc_resume_dialog", true, caption, enabledButtonCodes, defaultButtonCode, true) +, m_item(item) +, m_enabledActions(enabledActions) +, m_selectedAction(RA_Cancel) +{ + if(enabledButtonCodes & KDialogBase::User1) + setButtonText(KDialogBase::User1, i18n("&Resume")); + + QFrame* page = new QFrame(this); + QVBoxLayout* pageLayout = new QVBoxLayout(page); + pageLayout->setSpacing(spacingHint()); + setMainWidget(page); + + QLabel* labelMessage = new QLabel(page); + labelMessage->setText(message); + + m_urlreqFileURL = new KURLRequester(m_item->getFileURL().prettyURL(), page); + connect(m_urlreqFileURL, SIGNAL(textChanged(const QString&)), this, SLOT(updateDialogButtons())); + + pageLayout->addWidget(labelMessage); + pageLayout->addWidget(m_urlreqFileURL); + + if(m_enabledActions & RA_Rename) + { + QFrame* filePathToolsFrame = new QFrame(page); + QHBoxLayout* filePathToolsLayout = new QHBoxLayout(filePathToolsFrame); + filePathToolsLayout->setSpacing(spacingHint()); + + QPushButton* btnDefaultName = new QPushButton(i18n("O&riginal Filename"),filePathToolsFrame); + QPushButton* btnSuggestNewName = new QPushButton(i18n("Suggest &New Filename"),filePathToolsFrame); + filePathToolsLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding)); + filePathToolsLayout->addWidget(btnDefaultName); + filePathToolsLayout->addWidget(btnSuggestNewName); + connect(btnSuggestNewName, SIGNAL(clicked()), this, SLOT(suggestNewName())); + connect(btnDefaultName, SIGNAL(clicked()), this, SLOT(setDefaultName())); + + pageLayout->addWidget(filePathToolsFrame); + + } + + updateDialogButtons(); + setInitialSize(QSize(500, sizeHint().height())); + +} + +DccResumeDialog::~DccResumeDialog() +{ +} + +void DccResumeDialog::slotOk() +{ + if(m_item->getFileURL() == m_urlreqFileURL->url()) + m_selectedAction = RA_Overwrite; + else + m_selectedAction = RA_Rename; + KDialogBase::slotOk(); +} + +void DccResumeDialog::slotUser1() +{ + m_selectedAction = RA_Resume; + done(KDialogBase::User1); +} + +void DccResumeDialog::slotCancel() +{ + m_selectedAction = RA_Cancel; + KDialogBase::slotCancel(); +} + +void DccResumeDialog::updateDialogButtons() // slot +{ + if(m_item->getFileURL() == m_urlreqFileURL->url()) + { + setButtonText(KDialogBase::Ok, i18n("&Overwrite")); + enableButton(KDialogBase::Ok, m_enabledActions & RA_Overwrite); + enableButton(KDialogBase::User1, true); + } + else + { + setButtonText(KDialogBase::Ok, i18n("R&ename")); + enableButton(KDialogBase::Ok, m_enabledActions & RA_Rename); + enableButton(KDialogBase::User1, false); + } +} + +// FIXME: kio-fy me! +// taken and adapted from kio::renamedlg.cpp +void DccResumeDialog::suggestNewName() // slot +{ + QString dotSuffix, suggestedName; + QString basename = m_urlreqFileURL->url().section("/", -1); + KURL baseURL(m_urlreqFileURL->url().section("/", 0, -2)); + + int index = basename.find( '.' ); + if ( index != -1 ) + { + dotSuffix = basename.mid( index ); + basename.truncate( index ); + } + + int pos = basename.findRev( '_' ); + if(pos != -1 ) + { + QString tmp = basename.mid( pos+1 ); + bool ok; + int number = tmp.toInt( &ok ); + if ( !ok ) // ok there is no number + { + suggestedName = basename + '1' + dotSuffix; + } + else + { + // yes there's already a number behind the _ so increment it by one + basename.replace( pos+1, tmp.length(), QString::number(number+1) ); + suggestedName = basename + dotSuffix; + } + } + else // no underscore yet + suggestedName = basename + "_1" + dotSuffix ; + + // Check if suggested name already exists + bool exists = false; + // TODO: network transparency. However, using NetAccess from a modal dialog + // could be a problem, no? (given that it uses a modal widget itself....) + if ( baseURL.isLocalFile() ) + exists = QFileInfo( baseURL.path(+1) + suggestedName ).exists(); + + m_urlreqFileURL->setURL( baseURL.path(+1) + suggestedName ); + + if ( exists ) // already exists -> recurse + suggestNewName(); +} + +void DccResumeDialog::setDefaultName() // slot +{ + m_urlreqFileURL->setURL(m_item->getFileURL().prettyURL()); +} + +#include "dccresumedialog.moc" diff --git a/konversation/src/dccresumedialog.h b/konversation/src/dccresumedialog.h new file mode 100644 index 0000000..03135f8 --- /dev/null +++ b/konversation/src/dccresumedialog.h @@ -0,0 +1,59 @@ +/* + 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. +*/ + +/* + Copyright (C) 2004 Dario Abatianni + Copyright (C) 2004 Shintaro Matsuoka +*/ + +#ifndef DCCRESUMEDIALOG_H +#define DCCRESUMEDIALOG_H + +#include + + +class KURLRequester; +class DccTransferRecv; + +class DccResumeDialog : public KDialogBase +{ + Q_OBJECT + + public: + enum ReceiveAction + { + RA_Rename = 0x01, + RA_Overwrite = 0x02, + RA_Resume = 0x04, + RA_Cancel = 0x08 + }; + + virtual ~DccResumeDialog(); + + static ReceiveAction ask(DccTransferRecv* item, const QString& message, int enabledActions, ReceiveAction defaultAction); + + protected slots: + void slotOk(); + void slotUser1(); + void slotCancel(); + void suggestNewName(); + void setDefaultName(); + void updateDialogButtons(); + + protected: + DccResumeDialog(DccTransferRecv* item, const QString& caption, const QString& message, int enabledActions, int enabledButtonCodes, KDialogBase::ButtonCode defaultButtonCode); + + // UI + KURLRequester* m_urlreqFileURL; + + // data + DccTransferRecv* m_item; + int m_enabledActions; + ReceiveAction m_selectedAction; + +}; +#endif diff --git a/konversation/src/dcctransfer.cpp b/konversation/src/dcctransfer.cpp new file mode 100644 index 0000000..30ae5c2 --- /dev/null +++ b/konversation/src/dcctransfer.cpp @@ -0,0 +1,358 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002-2004 Dario Abatianni + Copyright (C) 2004-2007 Shintaro Matsuoka + Copyright (C) 2004,2005 John Tapsell +*/ + +#include "dcctransfer.h" +#include "preferences.h" + +#include +#include + +#include + + +DccTransfer::DccTransfer( DccType dccType, QObject* parent ) : QObject(parent) +{ + kdDebug() << "DccTransfer::DccTransfer()" << endl; + + m_type = dccType; + + m_status = Configuring; + + m_fileSize = 0; + m_resumed = false; + m_reverse = false; + m_connectionId = -1; // Not configured + m_timeLeft = DccTransfer::NotInTransfer; + m_transferringPosition = 0; + m_transferStartPosition = 0; + m_averageSpeed = 0.0; + m_currentSpeed = 0.0; + + m_bufferSize = Preferences::dccBufferSize(); + m_buffer = new char[ m_bufferSize ]; + + connect( &m_loggerTimer, SIGNAL( timeout() ), this, SLOT( logTransfer() ) ); + + m_timeOffer = QDateTime::currentDateTime(); +} + +DccTransfer::~DccTransfer() +{ + kdDebug() << "DccTransfer::~DccTransfer()" << endl; + delete[] m_buffer; + m_loggerTimer.stop(); +} + +DccTransfer::DccTransfer( const DccTransfer& obj ) + : QObject() +{ + m_buffer = 0; + m_bufferSize = 0; + m_averageSpeed = obj.getAverageSpeed(); + m_currentSpeed = obj.getCurrentSpeed(); + m_status = obj.getStatus(); + m_statusDetail = obj.getStatusDetail(); + m_type = obj.getType(); + m_fileName = obj.getFileName(); + m_fileSize = obj.getFileSize(); + m_fileURL = obj.getFileURL(); + // m_loggerBaseTime + // m_loggerTimer + m_ownIp = obj.getOwnIp(); + m_ownPort = obj.getOwnPort(); + m_partnerIp = obj.getPartnerIp(); + m_partnerNick = obj.getPartnerNick(); + m_partnerPort = obj.getPartnerPort(); + m_resumed = obj.isResumed(); + m_reverse = obj.isReverse(); + m_connectionId = obj.getConnectionId(); + m_timeLeft = obj.getTimeLeft(); + m_timeOffer = obj.getTimeOffer(); + m_timeTransferFinished = obj.getTimeTransferFinished(); + m_timeTransferStarted = obj.getTimeTransferStarted(); + // m_transferLogPosition + // m_transferLogTime + m_transferringPosition = obj.getTransferringPosition(); + m_transferStartPosition = obj.getTransferStartPosition(); +} + +void DccTransfer::setConnectionId( int id ) +{ + if ( getStatus() == Configuring || getStatus() == Queued ) + m_connectionId = id; +} + +void DccTransfer::setPartnerNick( const QString& nick ) +{ + if ( getStatus() == Configuring || getStatus() == Queued ) + m_partnerNick = nick; +} + +bool DccTransfer::queue() +{ + kdDebug() << "DccTransfer::queue()" << endl; + if ( getStatus() != Configuring ) + return false; + + if ( m_fileName.isEmpty() ) + return false; + + if ( m_connectionId == -1 || m_partnerNick.isEmpty() ) + return false; + + setStatus( Queued ); + return true; +} + +void DccTransfer::startTransferLogger() +{ + m_timeTransferStarted = QDateTime::currentDateTime(); + m_loggerBaseTime.start(); + m_loggerTimer.start( 100 ); +} + +void DccTransfer::finishTransferLogger() +{ + if ( m_timeTransferFinished.isNull() ) + m_timeTransferFinished = QDateTime::currentDateTime(); + m_loggerTimer.stop(); + updateTransferMeters(); +} + +// called by m_loggerTimer +void DccTransfer::logTransfer() +{ + m_transferLogTime.append( m_loggerBaseTime.elapsed() ); + m_transferLogPosition.append( m_transferringPosition ); + updateTransferMeters(); +} + +void DccTransfer::setStatus( DccStatus status, const QString& statusDetail ) +{ + bool changed = ( status != m_status ); + DccStatus oldStatus = m_status; + m_status = status; + m_statusDetail = statusDetail; + if ( changed ) + emit statusChanged( this, m_status, oldStatus ); +} + +void DccTransfer::updateTransferMeters() +{ + const int timeToCalc = 5; + + if ( getStatus() == Transferring ) + { + // update CurrentSpeed + + // remove too old data + QValueList::iterator itTime = m_transferLogTime.begin(); + QValueList::iterator itPos = m_transferLogPosition.begin(); + while ( itTime != m_transferLogTime.end() && ( m_transferLogTime.last() - (*itTime) > timeToCalc * 1000 ) ) + { + itTime = m_transferLogTime.remove( itTime ); + itPos = m_transferLogPosition.remove( itPos ); + } + + // shift the base of the time (m_transferLoggerBaseTime) + // reason: QTime can't handle a time longer than 24 hours + int shiftOffset = m_loggerBaseTime.restart(); + itTime = m_transferLogTime.begin(); + for ( ; itTime != m_transferLogTime.end() ; ++itTime ) + (*itTime) = (*itTime) - shiftOffset; + + if ( m_transferLogTime.count() >= 2 ) + { + // FIXME: precision of average speed is too bad + m_averageSpeed = (double)( m_transferringPosition - m_transferStartPosition ) / (double)m_timeTransferStarted.secsTo( QDateTime::currentDateTime() ); + m_currentSpeed = (double)( m_transferLogPosition.last() - m_transferLogPosition.front() ) / (double)( m_transferLogTime.last() - m_transferLogTime.front() ) * 1000; + } + else // avoid zero devision + { + m_averageSpeed = DccTransfer::Calculating; + m_currentSpeed = DccTransfer::Calculating; + } + + // update the remaining time + if ( m_currentSpeed <= 0 ) + m_timeLeft = DccTransfer::InfiniteValue; + else + m_timeLeft = (int)( (double)( m_fileSize - m_transferringPosition ) / m_currentSpeed ); + } + else if ( m_status >= Done ) + { + if ( m_timeTransferStarted.secsTo( m_timeTransferFinished ) > 1 ) + m_averageSpeed = (double)( m_transferringPosition - m_transferStartPosition ) / (double)m_timeTransferStarted.secsTo( m_timeTransferFinished ); + else + m_averageSpeed = DccTransfer::InfiniteValue; + m_currentSpeed = 0; + m_timeLeft = DccTransfer::NotInTransfer; + } + else + { + m_averageSpeed = 0; + m_currentSpeed = 0; + m_timeLeft = DccTransfer::NotInTransfer; + } +} + +QString DccTransfer::sanitizeFileName( const QString& fileName ) +{ + QString fileNameTmp = QFileInfo( fileName ).fileName(); + if ( fileNameTmp.startsWith( "." ) ) + fileNameTmp.replace( 0, 1, '_' ); // Don't create hidden files + if ( fileNameTmp.isEmpty() ) + fileNameTmp = "unnamed"; + return fileNameTmp; +} + +//FIXME: IPv6 support +QString DccTransfer::getNumericalIpText( const QString& ipString ) +{ + QHostAddress ip; + ip.setAddress( ipString ); + + return QString::number( ip.ip4Addr() ); +} + +unsigned long DccTransfer::intel( unsigned long value ) +{ + value = ( (value & 0xff000000) >> 24 ) + + ( (value & 0xff0000) >> 8 ) + + ( (value & 0xff00) << 8 ) + + ( (value & 0xff) << 24 ); + + return value; +} + +DccTransfer::DccType DccTransfer::getType() const +{ + return m_type; +} + +DccTransfer::DccStatus DccTransfer::getStatus() const +{ + return m_status; +} + +const QString& DccTransfer::getStatusDetail() const +{ + return m_statusDetail; +} + +QDateTime DccTransfer::getTimeOffer() const +{ + return m_timeOffer; +} + +int DccTransfer::getConnectionId() const +{ + return m_connectionId; +} + +QString DccTransfer::getOwnIp() const +{ + return m_ownIp; +} + +QString DccTransfer::getOwnPort() const +{ + return m_ownPort; +} + +QString DccTransfer::getPartnerNick() const +{ + return m_partnerNick; +} + +QString DccTransfer::getPartnerIp() const +{ + return m_partnerIp; +} + +QString DccTransfer::getPartnerPort() const +{ + return m_partnerPort; +} + +QString DccTransfer::getFileName() const +{ + return m_fileName; +} + +KIO::filesize_t DccTransfer::getFileSize() const +{ + return m_fileSize; +} + +KIO::fileoffset_t DccTransfer::getTransferringPosition() const +{ + return m_transferringPosition; +} + +KIO::fileoffset_t DccTransfer::getTransferStartPosition() const +{ + return m_transferStartPosition; +} + +KURL DccTransfer::getFileURL() const +{ + return m_fileURL; +} + +bool DccTransfer::isResumed() const +{ + return m_resumed; +} + +bool DccTransfer::isReverse() const +{ + return m_reverse; +} + +QString DccTransfer::getReverseToken() const +{ + return m_reverseToken; +} + +transferspeed_t DccTransfer::getAverageSpeed() const +{ + return m_averageSpeed; +} + +transferspeed_t DccTransfer::getCurrentSpeed() const +{ + return m_currentSpeed; +} + +int DccTransfer::getTimeLeft() const +{ + return m_timeLeft; +} + +int DccTransfer::getProgress() const +{ + return (int)( ( (double)getTransferringPosition() / (double)getFileSize() ) * 100 ); +} + +QDateTime DccTransfer::getTimeTransferStarted() const +{ + return m_timeTransferStarted; +} + +QDateTime DccTransfer::getTimeTransferFinished() const +{ + return m_timeTransferFinished; +} + +#include "dcctransfer.moc" diff --git a/konversation/src/dcctransfer.h b/konversation/src/dcctransfer.h new file mode 100644 index 0000000..d264def --- /dev/null +++ b/konversation/src/dcctransfer.h @@ -0,0 +1,186 @@ +/* + This class represents a DCC transfer. +*/ + +/* + 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. +*/ + +/* + Copyright (C) 2002-2004 Dario Abatianni + Copyright (C) 2004-2007 Shintaro Matsuoka + Copyright (C) 2004,2005 John Tapsell +*/ + +#ifndef DCCTRANSFER_H +#define DCCTRANSFER_H + +#include +#include +#include + +#include +#include + +typedef double transferspeed_t; + +class DccTransfer : public QObject +{ + Q_OBJECT + + public: + enum DccType + { + Receive, + Send + }; + + enum DccStatus + { + Configuring = 0, // Not queud yet (this means that user can't see the item at this time) + Queued, // Newly added DCC, waiting user's response + Preparing, // Opening KIO to write received data + WaitingRemote, // Waiting for remote host's response + Connecting, // RECV: trying to connect to the server + Transferring, + Done, + Failed, + Aborted + }; + + enum UnavailableStatus + { + Calculating = -1, + NotInTransfer = -2, + InfiniteValue = -3 + }; + + DccTransfer( DccType dccType, QObject* parent ); + virtual ~DccTransfer(); + + // info of DccTransfer can be copied with this constructor. + DccTransfer( const DccTransfer& obj ); + + DccType getType() const; + DccStatus getStatus() const; + const QString& getStatusDetail() const; + QDateTime getTimeOffer() const; + int getConnectionId() const; + QString getOwnIp() const; + QString getOwnPort() const; + QString getPartnerNick() const; + QString getPartnerIp() const; + QString getPartnerPort() const; + QString getFileName() const; + KIO::filesize_t getFileSize() const; + KIO::fileoffset_t getTransferringPosition() const; + KIO::fileoffset_t getTransferStartPosition() const; + KURL getFileURL() const; + bool isResumed() const; + bool isReverse() const; + QString getReverseToken() const; + transferspeed_t getAverageSpeed() const; + transferspeed_t getCurrentSpeed() const; + int getTimeLeft() const; + int getProgress() const; + QDateTime getTimeTransferStarted() const; + QDateTime getTimeTransferFinished() const; + + // common settings for DccTransferRecv / DccTransferSend + + // REQUIRED + void setConnectionId( int connectionId ); + // REQUIRED + void setPartnerNick( const QString& nick ); + + signals: + void transferStarted( DccTransfer* item ); + void done( DccTransfer* item ); + void statusChanged( DccTransfer* item, int newStatus, int oldStatus ); + + public slots: + virtual bool queue(); + virtual void start() {}; + virtual void abort() {}; + + protected: + void setStatus( DccStatus status, const QString& statusDetail = QString() ); + void startTransferLogger(); + void finishTransferLogger(); + + static QString sanitizeFileName( const QString& fileName ); + static QString getNumericalIpText( const QString& ipString ); + static unsigned long intel( unsigned long value ); + + protected slots: + void logTransfer(); + + protected: + // transfer information + DccType m_type; + DccStatus m_status; + QString m_statusDetail; + bool m_resumed; + bool m_reverse; + QString m_reverseToken; + KIO::fileoffset_t m_transferringPosition; + KIO::fileoffset_t m_transferStartPosition; + + /* + QValueList m_transferTimeLog; // write per packet to calc CPS + QValueList m_transferPositionLog; // write per packet to calc CPS + */ + + // we'll communicate with the partner via this server + int m_connectionId; + QString m_partnerNick; + QString m_partnerIp; // null when unknown + QString m_partnerPort; + QString m_ownIp; + QString m_ownPort; + + unsigned long m_bufferSize; + char* m_buffer; + + /** + * The filename. + * For receiving, it holds the filename as the sender said. + * So be careful, it can contain "../" and so on. + */ + QString m_fileName; + + /** The file size of the complete file sending/recieving. */ + KIO::filesize_t m_fileSize; + + /** + * If we are sending a file, this is the url of the file we are sending. + * If we are recieving a file, this is the url of the file we are saving + * to in the end (Temporararily it will be filename+".part" ). + */ + KURL m_fileURL; + + private: + DccTransfer& operator = ( const DccTransfer& obj ); + + void updateTransferMeters(); + + private: + QDateTime m_timeOffer; + QDateTime m_timeTransferStarted; + //QDateTime m_timeLastActive; + QDateTime m_timeTransferFinished; + + QTimer m_loggerTimer; + QTime m_loggerBaseTime; // for calculating CPS + QValueList m_transferLogTime; + QValueList m_transferLogPosition; + + transferspeed_t m_averageSpeed; + transferspeed_t m_currentSpeed; + int m_timeLeft; +}; + +#endif // DCCTRANSFER_H diff --git a/konversation/src/dcctransferdetailedinfopanel.cpp b/konversation/src/dcctransferdetailedinfopanel.cpp new file mode 100644 index 0000000..f7a55ff --- /dev/null +++ b/konversation/src/dcctransferdetailedinfopanel.cpp @@ -0,0 +1,214 @@ +/* + 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. +*/ + +/* + Copyright (C) 2007 Shintaro Matsuoka +*/ + +#include "dcctransferdetailedinfopanel.h" +#include "channel.h" +#include "dcctransfer.h" +#include "dcctransfermanager.h" +#include "dcctransferrecv.h" +#include "dcctransferpanelitem.h" +#include "konversationapplication.h" +#include "connectionmanager.h" +#include "server.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + + +DccTransferDetailedInfoPanel::DccTransferDetailedInfoPanel( QWidget* parent, const char* name ) + : DccTransferDetailedInfoPanelUI( parent, name ) +{ + m_autoViewUpdateTimer = new QTimer( this ); + + connect( m_urlreqLocation, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotLocationChanged( const QString& ) ) ); + connect( m_buttonOpenFolder, SIGNAL( clicked() ), this, SLOT( slotOpenFolderButtonClicked() ) ); + connect( KonversationApplication::instance()->getDccTransferManager(), SIGNAL( fileURLChanged( DccTransferRecv* ) ), + this, SLOT( updateView() ) ); // it's a little rough.. +} + +DccTransferDetailedInfoPanel::~DccTransferDetailedInfoPanel() +{ +} + +void DccTransferDetailedInfoPanel::setItem( DccTransferPanelItem* item ) +{ + m_autoViewUpdateTimer->stop(); + + // disconnect all slots once + disconnect( this ); + // we can't do disconnect( m_item->transfer(), 0, this, 0 ) here + // because m_item can have been deleted already. + + // set up the auto view-update timer + connect( m_autoViewUpdateTimer, SIGNAL( timeout() ), this, SLOT( updateView() ) ); + + m_item = item; + + // If the file is already being transferred, the timer must be started here, + // otherwise the information will not be updated every 0.5sec + if (m_item->transfer()->getStatus() == DccTransfer::Transferring) + m_autoViewUpdateTimer->start(500, false); + connect( m_item->transfer(), SIGNAL( statusChanged( DccTransfer*, int, int ) ), this, SLOT( slotTransferStatusChanged( DccTransfer*, int, int ) ) ); + + updateView(); +} + +void DccTransferDetailedInfoPanel::updateView() +{ + DccTransfer* transfer = m_item->transfer(); + + // Type: + QString type( transfer->getType() == DccTransfer::Send ? i18n( "DCC Send" ) : i18n( "DCC Receive" ) ); + if ( transfer->isReverse() ) + type += i18n( " (Reverse DCC)" ); + m_labelDccType->setText( type ); + + // Filename: + m_labelFilename->setText( transfer->getFileName() ); + + // Location: + m_urlreqLocation->setURL( transfer->getFileURL().prettyURL() ); + //m_urlreqLocation->lineEdit()->setFocusPolicy( transfer->getStatus() == DccTransfer::Queued ? StrongFocus : ClickFocus ); + m_urlreqLocation->lineEdit()->setReadOnly( transfer->getStatus() != DccTransfer::Queued ); + m_urlreqLocation->lineEdit()->setFrame( transfer->getStatus() == DccTransfer::Queued ); + m_urlreqLocation->button()->setEnabled( transfer->getStatus() == DccTransfer::Queued ); + m_buttonOpenFolder->setEnabled( !m_urlreqLocation->lineEdit()->text().isEmpty() ); + + // Partner: + QString partnerInfoServerName; + if ( transfer->getConnectionId() == -1 ) + partnerInfoServerName = i18n( "Unknown server" ); + else if ( KonversationApplication::instance()->getConnectionManager()->getServerByConnectionId( transfer->getConnectionId() ) ) + partnerInfoServerName = KonversationApplication::instance()->getConnectionManager()->getServerByConnectionId( transfer->getConnectionId() )->getServerName(); + else + partnerInfoServerName = i18n( "Unknown server" ); + QString partnerInfo( i18n( "%1 on %2" ) + .arg( transfer->getPartnerNick().isEmpty() ? "?" : transfer->getPartnerNick() ) + .arg( partnerInfoServerName ) ); + if ( !transfer->getPartnerIp().isEmpty() ) + partnerInfo += i18n( ", %1 (port %2)" ).arg( transfer->getPartnerIp() ).arg( transfer->getPartnerPort() ); + m_labelPartner->setText( partnerInfo ); + + // Self: + if ( transfer->getOwnIp().isEmpty() ) + m_labelSelf->setText( "" ); + else + m_labelSelf->setText( i18n( "%1 (port %2)" ).arg( transfer->getOwnIp() ).arg( transfer->getOwnPort() ) ); + + // Status: + if ( transfer->getStatus() == DccTransfer::Transferring ) + m_labelStatus->setText( m_item->getStatusText() + " ( " + m_item->getCurrentSpeedPrettyText() + " )" ); + else + m_labelStatus->setText( transfer->getStatusDetail().isEmpty() ? m_item->getStatusText() : m_item->getStatusText() + " (" + transfer->getStatusDetail() + ')' ); + + // Progress: + m_progress->setProgress( transfer->getProgress() ); + + // Current Position: + m_labelCurrentPosition->setText( KGlobal::locale()->formatNumber( transfer->getTransferringPosition(), 0 ) ); + + // File Size: + m_labelFileSize->setText( KGlobal::locale()->formatNumber( transfer->getFileSize(), 0 ) ); + + // Current Speed: + m_labelCurrentSpeed->setText( m_item->getCurrentSpeedPrettyText() ); + + // Average Speed: + m_labelAverageSpeed->setText( m_item->getAverageSpeedPrettyText() ); + + // Resumed: + if ( transfer->isResumed() ) + m_labelIsResumed->setText( i18n( "Yes, %1" ).arg( KGlobal::locale()->formatNumber( transfer->getTransferStartPosition(), 0 ) ) ); + else + m_labelIsResumed->setText( i18n( "No" ) ); + + // Transferring Time: + if ( transfer->getTimeTransferStarted().isNull() ) + m_labelTransferringTime->setText( "" ); + else + { + int transferringTime; + + // The transfer is still in progress + if ( transfer->getTimeTransferFinished().isNull() ) + transferringTime = transfer->getTimeTransferStarted().secsTo( QDateTime::currentDateTime() ); + // The transfer has finished + else + transferringTime = transfer->getTimeTransferStarted().secsTo( transfer->getTimeTransferFinished() ); + + if ( transferringTime >= 1 ) + m_labelTransferringTime->setText( DccTransferPanelItem::secToHMS( transferringTime ) ); + else + m_labelTransferringTime->setText( i18n( "< 1sec" ) ); + } + + // Estimated Time Left: + m_labelTimeLeft->setText( m_item->getTimeLeftPrettyText() ); + + // Offered at: + m_labelTimeOffered->setText( transfer->getTimeOffer().toString( "hh:mm:ss" ) ); + + // Started at: + if ( !transfer->getTimeTransferStarted().isNull() ) + m_labelTimeStarted->setText( transfer->getTimeTransferStarted().toString( "hh:mm:ss" ) ); + else + m_labelTimeStarted->setText( "" ); + + // Finished at: + if ( !transfer->getTimeTransferFinished().isNull() ) + m_labelTimeFinished->setText( transfer->getTimeTransferFinished().toString( "hh:mm:ss" ) ); + else + m_labelTimeFinished->setText( "" ); +} + +void DccTransferDetailedInfoPanel::slotTransferStatusChanged( DccTransfer* /* transfer */, int newStatus, int oldStatus ) +{ + updateView(); + if ( newStatus == DccTransfer::Transferring ) + { + // start auto view-update timer + m_autoViewUpdateTimer->start( 500, false ); + } + else if ( oldStatus == DccTransfer::Transferring ) + { + // stop auto view-update timer + m_autoViewUpdateTimer->stop(); + } +} + +void DccTransferDetailedInfoPanel::slotLocationChanged( const QString& url ) +{ + if ( m_item->transfer()->getType() == DccTransfer::Receive ) + { + DccTransferRecv* transfer = static_cast< DccTransferRecv* >( m_item->transfer() ); + transfer->setFileURL( KURL::fromPathOrURL( url ) ); + } +} + +void DccTransferDetailedInfoPanel::slotOpenFolderButtonClicked() +{ + QString urlString = m_urlreqLocation->lineEdit()->text(); + if ( !urlString.isEmpty() ) + { + KURL url = KURL::fromPathOrURL( urlString ); + url.setFileName( QString() ); + new KRun( url, 0, true, true ); + } +} + +#include "dcctransferdetailedinfopanel.moc" diff --git a/konversation/src/dcctransferdetailedinfopanel.h b/konversation/src/dcctransferdetailedinfopanel.h new file mode 100644 index 0000000..38eb692 --- /dev/null +++ b/konversation/src/dcctransferdetailedinfopanel.h @@ -0,0 +1,44 @@ +/* + 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. +*/ + +/* + Copyright (C) 2007 Shintaro Matsuoka +*/ + +#ifndef DCCTRANSFERDETAILEDINFOPANEL_H +#define DCCTRANSFERDETAILEDINFOPANEL_H + +#include "dcctransferdetailedinfopanelui.h" + + +class QTimer; + +class DccTransfer; +class DccTransferPanelItem; + +class DccTransferDetailedInfoPanel : public DccTransferDetailedInfoPanelUI +{ + Q_OBJECT + + public: + explicit DccTransferDetailedInfoPanel( QWidget* parent = 0, const char* name = 0 ); + virtual ~DccTransferDetailedInfoPanel(); + + void setItem( DccTransferPanelItem* item ); + + private slots: + void updateView(); + void slotTransferStatusChanged( DccTransfer* transfer, int newStatus, int oldStatus ); + void slotLocationChanged( const QString& url ); + void slotOpenFolderButtonClicked(); + + private: + DccTransferPanelItem* m_item; + QTimer* m_autoViewUpdateTimer; +}; + +#endif // DCCTRANSFERDETAILEDINFOPANEL_H diff --git a/konversation/src/dcctransferdetailedinfopanelui.ui b/konversation/src/dcctransferdetailedinfopanelui.ui new file mode 100644 index 0000000..9c3f136 --- /dev/null +++ b/konversation/src/dcctransferdetailedinfopanelui.ui @@ -0,0 +1,492 @@ + +DccTransferDetailedInfoPanelUI + + + DccTransferDetailedInfoPanelUI + + + + 0 + 0 + 646 + 289 + + + + + 7 + 1 + 0 + 0 + + + + + unnamed + + + + layout7 + + + + unnamed + + + + m_labelFilename + + + + + m_labelDccType + + + + + textLabel4 + + + Filename: + + + + + textLabel1_3 + + + Self: + + + + + textLabel12 + + + Type: + + + + + textLabel10 + + + Status: + + + + + textLabel3 + + + Location: + + + + + textLabel18 + + + Progress: + + + + + m_labelStatus + + + + + m_labelPartner + + + + + m_progress + + + + + textLabel23 + + + Partner: + + + + + layout6 + + + + unnamed + + + + m_urlreqLocation + + + + + m_buttonOpenFolder + + + Open Folder + + + + + + + + + + m_labelSelf + + + + + + + line1 + + + HLine + + + Sunken + + + Horizontal + + + + + layout26 + + + + unnamed + + + + layout24 + + + + unnamed + + + + m_labelCurrentSpeed + + + + 0 + 5 + 0 + 0 + + + + + 130 + 0 + + + + AlignVCenter|AlignRight + + + + + textLabel21 + + + File Size: + + + + + m_labelIsResumed + + + + 0 + 5 + 0 + 0 + + + + + 130 + 0 + + + + AlignVCenter|AlignRight + + + + + m_labelFileSize + + + + 0 + 5 + 0 + 0 + + + + + 130 + 0 + + + + AlignVCenter|AlignRight + + + + + textLabel1 + + + Average Speed: + + + + + textLabel14 + + + Resumed: + + + + + m_labelCurrentPosition + + + + 0 + 5 + 0 + 0 + + + + + 130 + 0 + + + + AlignVCenter|AlignRight + + + + + textLabel1_2 + + + Current Speed: + + + + + textLabel19 + + + Current Position: + + + + + m_labelAverageSpeed + + + + 0 + 5 + 0 + 0 + + + + + 130 + 0 + + + + AlignVCenter|AlignRight + + + + + + + line3 + + + VLine + + + Sunken + + + Vertical + + + + + layout25 + + + + unnamed + + + + textLabel8 + + + Estimated Time Left: + + + + + textLabel5 + + + Offered at: + + + + + m_labelTimeFinished + + + AlignVCenter|AlignRight + + + + + m_labelTransferringTime + + + + 0 + 5 + 0 + 0 + + + + + 130 + 0 + + + + AlignVCenter|AlignRight + + + + + textLabel7 + + + Finished at: + + + + + textLabel6_2 + + + Started at: + + + + + m_labelTimeLeft + + + + 0 + 5 + 0 + 0 + + + + + 130 + 0 + + + + AlignVCenter|AlignRight + + + + + m_labelTimeOffered + + + AlignVCenter|AlignRight + + + + + textLabel6 + + + Transferring Time: + + + + + m_labelTimeStarted + + + AlignVCenter|AlignRight + + + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 110 + 20 + + + + + + + + + + kprogress.h + kurlrequester.h + ksqueezedtextlabel.h + klineedit.h + kpushbutton.h + + diff --git a/konversation/src/dcctransfermanager.cpp b/konversation/src/dcctransfermanager.cpp new file mode 100644 index 0000000..41b73bd --- /dev/null +++ b/konversation/src/dcctransfermanager.cpp @@ -0,0 +1,238 @@ +/* + 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. +*/ + +/* + Copyright (C) 2007 Shintaro Matsuoka +*/ + +#include "dcctransfermanager.h" +#include "dcctransferrecv.h" +#include "dcctransfersend.h" +#include "konversationapplication.h" +#include "preferences.h" + +#include + + +DccTransferManager::DccTransferManager( QObject* parent ) + : QObject( parent ) +{ + // initial number + m_nextReverseTokenNumber = 1001; + + m_defaultIncomingFolder = Preferences::dccPath(); + + connect( KonversationApplication::instance(), SIGNAL( appearanceChanged() ), + this, SLOT( slotSettingsChanged() ) ); +} + +DccTransferManager::~DccTransferManager() +{ + m_sendItems.clear(); + m_recvItems.clear(); +} + +DccTransferRecv* DccTransferManager::newDownload() +{ + DccTransferRecv* transfer = new DccTransferRecv(this); + m_recvItems.push_back( transfer ); + connect( transfer, SIGNAL( done( DccTransfer* ) ), this, SLOT( removeRecvItem( DccTransfer* ) ) ); + initTransfer( transfer ); + return transfer; +} + +DccTransferSend* DccTransferManager::newUpload() +{ + DccTransferSend* transfer = new DccTransferSend(this); + m_sendItems.push_back( transfer ); + connect( transfer, SIGNAL( done( DccTransfer* ) ), this, SLOT( removeSendItem( DccTransfer* ) ) ); + initTransfer( transfer ); + return transfer; +} + +DccTransferRecv* DccTransferManager::resumeDownload( int connectionId, const QString& partnerNick, const QString& fileName, const QString& ownPort, unsigned long position ) +{ + DccTransferRecv* transfer = 0; + + // find applicable one + QValueListConstIterator< DccTransferRecv* > it; + for ( it = m_recvItems.begin() ; it != m_recvItems.end() ; ++it ) + { + if ( ( (*it)->getStatus() == DccTransfer::Queued || (*it)->getStatus() == DccTransfer::WaitingRemote ) && + (*it)->getConnectionId() == connectionId && + (*it)->getPartnerNick() == partnerNick && + (*it)->getFileName() == fileName && + (*it)->isResumed() ) + { + transfer = (*it); + kdDebug() << "DccTransferManager::resumeDownload(): filename match: " << fileName << ", claimed port: " << ownPort << ", item port: " << transfer->getOwnPort() << endl; + // the port number can be changed behind NAT, so we pick an item which only the filename is correspondent in that case. + if ( transfer->getOwnPort() == ownPort ) + { + break; + } + } + } + + if ( transfer ) + transfer->startResume( position ); + + return transfer; +} + +DccTransferSend* DccTransferManager::resumeUpload( int connectionId, const QString& partnerNick, const QString& fileName, const QString& ownPort, unsigned long position ) +{ + DccTransferSend* transfer = 0; + + // find applicable one + QValueListConstIterator< DccTransferSend* > it; + for ( it = m_sendItems.begin() ; it != m_sendItems.end() ; ++it ) + { + if ( ( (*it)->getStatus() == DccTransfer::Queued || (*it)->getStatus() == DccTransfer::WaitingRemote ) && + (*it)->getConnectionId() == connectionId && + (*it)->getPartnerNick() == partnerNick && + (*it)->getFileName() == fileName && + !(*it)->isResumed() ) + { + transfer = (*it); + kdDebug() << "DccTransferManager::resumeUpload(): filename match: " << fileName << ", claimed port: " << ownPort << ", item port: " << transfer->getOwnPort() << endl; + // the port number can be changed behind NAT, so we pick an item which only the filename is correspondent in that case. + if ( transfer->getOwnPort() == ownPort ) + { + break; + } + } + } + + if ( transfer ) + transfer->setResume( position ); + + return transfer; +} + +DccTransferSend* DccTransferManager::startReverseSending( int connectionId, const QString& partnerNick, const QString& fileName, const QString& partnerHost, const QString& partnerPort, unsigned long fileSize, const QString& token ) +{ + kdDebug() << "DccTransferManager::startReverseSending(): server group ID: " << connectionId << ", partner: " << partnerNick << ", filename: " << fileName << ", partner IP: " << partnerHost << ", parnter port: " << partnerPort << ", filesize: " << fileSize << ", token: " << token << endl; + DccTransferSend* transfer = 0; + + // find applicable one + QValueListConstIterator< DccTransferSend* > it; + for ( it = m_sendItems.begin() ; it != m_sendItems.end() ; ++it ) + { + if ( + (*it)->getStatus() == DccTransfer::WaitingRemote && + (*it)->getConnectionId() == connectionId && + (*it)->getPartnerNick() == partnerNick && + (*it)->getFileName() == fileName && + (*it)->getFileSize() == fileSize && + (*it)->getReverseToken() == token + ) + { + transfer = (*it); + break; + } + } + + if ( transfer ) + transfer->connectToReceiver( partnerHost, partnerPort ); + + return transfer; +} + +void DccTransferManager::initTransfer( DccTransfer* transfer ) +{ + connect( transfer, SIGNAL( statusChanged( DccTransfer*, int, int ) ), this, SLOT( slotTransferStatusChanged( DccTransfer*, int, int ) ) ); + + emit newTransferAdded( transfer ); +} + +bool DccTransferManager::isLocalFileInWritingProcess( const KURL& url ) const +{ + QValueListConstIterator< DccTransferRecv* > it; + for ( it = m_recvItems.begin() ; it != m_recvItems.end() ; ++it ) + { + if ( ( (*it)->getStatus() == DccTransfer::Connecting || + (*it)->getStatus() == DccTransfer::Transferring ) && + (*it)->getFileURL() == url ) + { + return true; + } + } + return false; +} + +int DccTransferManager::generateReverseTokenNumber() +{ + return m_nextReverseTokenNumber++; +} + +bool DccTransferManager::hasActiveTransfers() +{ + QValueListConstIterator< DccTransferSend* > it; + for ( it = m_sendItems.begin() ; it != m_sendItems.end() ; ++it ) + { + if ((*it)->getStatus() == DccTransfer::Transferring) + return true; + } + + QValueListConstIterator< DccTransferRecv* > it2; + for ( it2 = m_recvItems.begin() ; it2 != m_recvItems.end() ; ++it2 ) + { + if ((*it2)->getStatus() == DccTransfer::Transferring) + return true; + } + + return false; +} + +void DccTransferManager::slotTransferStatusChanged( DccTransfer* item, int newStatus, int oldStatus ) +{ + kdDebug() << "DccTransferManager::slotTransferStatusChanged(): " << oldStatus << " -> " << newStatus << " " << item->getFileName() << " (" << item->getType() << ")" << endl; + + if ( newStatus == DccTransfer::Queued ) + emit newTransferQueued( item ); +} + +void DccTransferManager::slotSettingsChanged() +{ + // update the default incoming directory for already existed DCCRECV items + if ( Preferences::dccPath() != m_defaultIncomingFolder ) + { + QValueListConstIterator< DccTransferRecv* > it; + for ( it = m_recvItems.begin() ; it != m_recvItems.end() ; ++it ) + { + if ( (*it)->getStatus() == DccTransfer::Queued && + (*it)->getFileURL().directory() == m_defaultIncomingFolder ) + { + KURL url; + url.setDirectory( Preferences::dccPath() ); + url.setFileName( (*it)->getFileURL().fileName() ); + (*it)->setFileURL( url ); + + emit fileURLChanged( *it ); + } + } + + m_defaultIncomingFolder = Preferences::dccPath(); + } +} + +void DccTransferManager::removeSendItem( DccTransfer* item_ ) +{ + DccTransferSend* item = static_cast< DccTransferSend* > ( item_ ); + m_sendItems.remove( item ); + item->deleteLater(); +} + +void DccTransferManager::removeRecvItem( DccTransfer* item_ ) +{ + DccTransferRecv* item = static_cast< DccTransferRecv* > ( item_ ); + m_recvItems.remove( item ); + item->deleteLater(); +} + +#include "dcctransfermanager.moc" diff --git a/konversation/src/dcctransfermanager.h b/konversation/src/dcctransfermanager.h new file mode 100644 index 0000000..0f2d655 --- /dev/null +++ b/konversation/src/dcctransfermanager.h @@ -0,0 +1,95 @@ +/* + DccTransferManager controls DccTransfer instances. + All DccTransferRecv/DccTransferSend instances are created and deleted by this class. + Each DccTransfer instance is deleted immediately after its transfer done. +*/ + +/* + 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. +*/ + +/* + Copyright (C) 2007 Shintaro Matsuoka +*/ + +#ifndef DCCTRANSFERMANAGER_H +#define DCCTRANSFERMANAGER_H + +#include "dcctransfer.h" + +#include +#include + + +class KURL; + +class DccTransferRecv; +class DccTransferSend; + +class DccTransferManager : public QObject +{ + Q_OBJECT + + public: + DccTransferManager( QObject* parent = 0 ); + ~DccTransferManager(); + + signals: + /* + * The status of the item is DccTransfer::Configuring when this signal is emitted. + */ + void newTransferAdded( DccTransfer* transfer ); + /* + * The status of the item is DccTransfer::Queued when this signal is emitted. + */ + void newTransferQueued( DccTransfer* transfer ); + + void fileURLChanged( DccTransferRecv* transfer ); + + public: + DccTransferRecv* newDownload(); + DccTransferSend* newUpload(); + + /** + * @return a DccTransferRecv item if applicable one found, otherwise 0. + */ + DccTransferRecv* resumeDownload(int connectionId, const QString& partnerNick, const QString& fileName, const QString& ownPort, unsigned long position ); + + /** + * @return a DccTransferSend item if applicable one found, otherwise 0. + */ + DccTransferSend* resumeUpload(int connectionId, const QString& partnerNick, const QString& fileName, const QString& ownPort, unsigned long position ); + + DccTransferSend* startReverseSending(int connectionId, const QString& partnerNick, const QString& fileName, const QString& partnerHost, const QString& partnerPort, unsigned long fileSize, const QString& token ); + + bool isLocalFileInWritingProcess( const KURL& localUrl ) const; + + int generateReverseTokenNumber(); + + bool hasActiveTransfers(); + + private: + /* + * initTransfer() does the common jobs for newDownload() and newUpload() + */ + void initTransfer( DccTransfer* transfer ); + + private slots: + void slotTransferStatusChanged( DccTransfer* item, int newStatus, int oldStatus ); + void removeSendItem( DccTransfer* item ); + void removeRecvItem( DccTransfer* item ); + + void slotSettingsChanged(); + + private: + QValueList< DccTransferSend* > m_sendItems; + QValueList< DccTransferRecv* > m_recvItems; + + int m_nextReverseTokenNumber; + QString m_defaultIncomingFolder; // store here to know if this settings is changed +}; + +#endif // DCCTRANSFERMANAGER_H diff --git a/konversation/src/dcctransferpanel.cpp b/konversation/src/dcctransferpanel.cpp new file mode 100644 index 0000000..3a2df9c --- /dev/null +++ b/konversation/src/dcctransferpanel.cpp @@ -0,0 +1,459 @@ +/* + 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. +*/ + +/* + begin: Mit Aug 7 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ +// Copyright (C) 2004-2008 Shintaro Matsuoka + +#include "dcctransferpanel.h" +#include "konversationapplication.h" +#include "dcctransferdetailedinfopanel.h" +#include "dcctransfermanager.h" +#include "dcctransferpanelitem.h" +#include "dcctransfersend.h" +#include "preferences.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +DccTransferPanel::DccTransferPanel(QWidget* parent) : ChatWindow(parent) +{ + setType(ChatWindow::DccTransferPanel); + setName(i18n("DCC Status")); + + initGUI(); + + connect( KonversationApplication::instance()->getDccTransferManager(), SIGNAL( newTransferAdded( DccTransfer* ) ), this, SLOT( slotNewTransferAdded( DccTransfer* ) ) ); +} + +DccTransferPanel::~DccTransferPanel() +{ + // remember column widths + QValueList columnWidths; + for ( uint i = 0 ; i < Column::COUNT ; ++i ) + columnWidths.push_back( m_listView->columnWidth( i ) ); + Preferences::setDccColumnWidths( columnWidths ); +} + +void DccTransferPanel::initGUI() +{ + setSpacing( 0 ); + + m_listView = new KListView(this,"dcc_control_panel"); + + m_listView->setSelectionMode(QListView::Extended); + m_listView->setDragEnabled(true); + m_listView->setAcceptDrops(true); + m_listView->setSorting(-1,false); + m_listView->setAllColumnsShowFocus(true); + + for(unsigned int i=0 ; i < Column::COUNT ; ++i) + m_listView->addColumn(""); + + //m_listView->setColumnText(Column::TypeIcon, ""); + m_listView->setColumnText(Column::OfferDate, i18n("Started at")); + m_listView->setColumnText(Column::Status, i18n("Status")); + m_listView->setColumnText(Column::FileName, i18n("File")); + m_listView->setColumnText(Column::PartnerNick, i18n("Partner")); + m_listView->setColumnText(Column::Progress, i18n("Progress")); + m_listView->setColumnText(Column::Position, i18n("Position")); + m_listView->setColumnText(Column::TimeLeft, i18n("Remaining")); + m_listView->setColumnText(Column::CurrentSpeed, i18n("Speed")); + m_listView->setColumnText(Column::SenderAddress, i18n("Sender Address")); + + QValueList columnWidths = Preferences::dccColumnWidths(); + for ( uint i = 0 ; i < Column::COUNT && i < columnWidths.count() ; ++i ) + m_listView->setColumnWidth( i, columnWidths[i] ); + + m_listView->setColumnWidthMode(Column::FileName, QListView::Manual); + + m_listView->setColumnAlignment(Column::OfferDate, AlignHCenter); + m_listView->setColumnAlignment(Column::Progress, AlignHCenter); + m_listView->setColumnAlignment(Column::Position, AlignHCenter); + m_listView->setColumnAlignment(Column::TimeLeft, AlignHCenter); + m_listView->setColumnAlignment(Column::CurrentSpeed, AlignHCenter); + + m_listView->setSorting(Column::OfferDate, false); + + connect(m_listView,SIGNAL (selectionChanged()),this,SLOT (updateButton()) ); + + // detailed info panel + m_detailPanel = new DccTransferDetailedInfoPanel(this); + + // button + + QHBox* buttonsBox=new QHBox(this); + buttonsBox->setSpacing(spacing()); + + // convenience, undeffed below again to avoid name clashes + #define icon(s) KGlobal::iconLoader()->loadIconSet( s, KIcon::Small ) + + m_buttonAccept = new QPushButton(icon("player_play"), i18n("Accept"), buttonsBox, "start_dcc"); + m_buttonAbort = new QPushButton(icon("stop"), i18n("Abort"), buttonsBox, "abort_dcc"); + m_buttonClear = new QPushButton(icon("editdelete"), i18n("Clear"), buttonsBox, "clear_dcc"); + m_buttonOpen = new QPushButton(icon("exec"), i18n("Open File"), buttonsBox, "open_dcc_file"); + m_buttonDetail = new QPushButton(icon("view_text"), i18n("Details"), buttonsBox, "detail_dcc"); + m_buttonDetail->setToggleButton( true ); + + QToolTip::add( m_buttonAccept, i18n( "Start receiving" ) ); + QToolTip::add( m_buttonAbort, i18n( "Abort the transfer(s)" ) ); + QToolTip::add( m_buttonOpen, i18n( "Run the file" ) ); + QToolTip::add( m_buttonDetail, i18n( "View DCC transfer details" ) ); + + connect( m_buttonAccept, SIGNAL(clicked()), this, SLOT(acceptDcc()) ); + connect( m_buttonAbort, SIGNAL(clicked()), this, SLOT(abortDcc()) ); + connect( m_buttonClear, SIGNAL(clicked()), this, SLOT(clearDcc()) ); + connect( m_buttonOpen, SIGNAL(clicked()), this, SLOT(runDcc()) ); + //connect( m_buttonDetail, SIGNAL(clicked()), this, SLOT(openDetail()) ); + connect( m_buttonDetail, SIGNAL(toggled(bool)), m_detailPanel, SLOT(setShown(bool)) ); + m_buttonDetail->setOn(true); + + + // popup menu + + m_popup = new KPopupMenu(this); + m_popup->insertItem( i18n("&Select All Items"), Popup::SelectAll); + m_popup->insertItem( i18n("S&elect All Completed Items"), Popup::SelectAllCompleted); + m_popup->insertSeparator(); // ----- + m_popup->insertItem(icon("player_play"), i18n("&Accept"), Popup::Accept); + m_popup->insertItem(icon("stop"), i18n("A&bort"), Popup::Abort); + m_popup->insertSeparator(); // ----- + // FIXME: make it neat + m_popup->insertItem(icon("redo"), i18n("Resend"), Popup::Resend); + m_popup->insertItem(icon("editdelete"), i18n("&Clear"), Popup::Clear); + m_popup->insertSeparator(); // ----- + m_popup->insertItem(icon("exec"), i18n("&Open File"), Popup::Open); + m_popup->insertItem(icon("messagebox_info"), i18n("File &Information"), Popup::Info); + + #undef icon + + connect(m_listView, SIGNAL(contextMenuRequested(QListViewItem*,const QPoint&,int)), this, SLOT(popupRequested(QListViewItem*,const QPoint&,int))); + connect(m_popup, SIGNAL(activated(int)), this, SLOT(popupActivated(int))); + + // misc. + connect(m_listView, SIGNAL(doubleClicked(QListViewItem*,const QPoint&,int)), this, SLOT(doubleClicked(QListViewItem*,const QPoint&,int))); + + connect(m_listView, SIGNAL(currentChanged(QListViewItem*)), this, SLOT(setDetailPanelItem(QListViewItem*))); + + updateButton(); +} + +void DccTransferPanel::slotNewTransferAdded( DccTransfer* transfer ) +{ + DccTransferPanelItem* item = new DccTransferPanelItem( this, transfer ); + connect( transfer, SIGNAL( statusChanged( DccTransfer*, int, int ) ), this, SLOT( slotTransferStatusChanged() ) ); + if ( m_listView->childCount() == 1 ) + { + m_listView->clearSelection(); + m_listView->setSelected( item, true ); + m_listView->setCurrentItem( item ); + updateButton(); + setDetailPanelItem( item ); + } +} + +void DccTransferPanel::slotTransferStatusChanged() +{ + updateButton(); + activateTabNotification(Konversation::tnfSystem); +} + +void DccTransferPanel::updateButton() +{ + bool accept = true, + abort = false, + clear = false, + info = true, + open = true, + resend = false, + selectAll = false, + selectAllCompleted = false; + + int selectedItems = 0; + QListViewItemIterator it( m_listView ); + + while( it.current() ) + { + DccTransferPanelItem* item = static_cast( it.current() ); + + DccTransfer::DccType type = item->transfer()->getType(); + DccTransfer::DccStatus status = item->transfer()->getStatus(); + + selectAll = true; + selectAllCompleted |= ( status >= DccTransfer::Done ); + + if( it.current()->isSelected() ) + { + ++selectedItems; + + accept &= ( status == DccTransfer::Queued ); + + abort |= ( status < DccTransfer::Done ); + + clear |= ( status >= DccTransfer::Done ); + + info &= ( type == DccTransfer::Send || + status == DccTransfer::Done ); + + open &= ( type == DccTransfer::Send || + status == DccTransfer::Done ); + + resend |= ( type == DccTransfer::Send && + status >= DccTransfer::Done ); + } + ++it; + } + + if( !selectedItems ) + { + accept = false; + abort = false; + clear = false; + info = false; + open = false; + resend = false; + } + + if (!kapp->authorize("allow_downloading")) + { + accept = false; + } + + m_buttonAccept->setEnabled( accept ); + m_buttonAbort->setEnabled( abort ); + m_buttonClear->setEnabled( clear ); + m_buttonOpen->setEnabled( open ); + + m_popup->setItemEnabled( Popup::SelectAll, selectAll ); + m_popup->setItemEnabled( Popup::SelectAllCompleted, selectAllCompleted ); + m_popup->setItemEnabled( Popup::Accept, accept ); + m_popup->setItemEnabled( Popup::Abort, abort ); + m_popup->setItemEnabled( Popup::Clear, clear ); + m_popup->setItemEnabled( Popup::Open, open ); + m_popup->setItemEnabled( Popup::Resend, resend ); + m_popup->setItemEnabled( Popup::Info, info ); +} + +void DccTransferPanel::setDetailPanelItem(QListViewItem* item_) +{ + if ( item_ ) + { + DccTransferPanelItem* item = static_cast< DccTransferPanelItem* >( item_ ); + m_detailPanel->setItem( item ); + } +} + +void DccTransferPanel::acceptDcc() +{ + QListViewItemIterator it( m_listView ); + while( it.current() ) + { + if( it.current()->isSelected() ) + { + DccTransferPanelItem* item=static_cast( it.current() ); + DccTransfer* transfer = item->transfer(); + if( transfer->getType() == DccTransfer::Receive && transfer->getStatus() == DccTransfer::Queued ) + transfer->start(); + } + ++it; + } +} + +void DccTransferPanel::abortDcc() +{ + QListViewItemIterator it( m_listView ); + while( it.current() ) + { + if( it.current()->isSelected() ) + { + DccTransferPanelItem* item=static_cast( it.current() ); + DccTransfer* transfer = item->transfer(); + if( transfer->getStatus() < DccTransfer::Done ) + transfer->abort(); + } + ++it; + } +} + +void DccTransferPanel::resendFile() +{ + QListViewItemIterator it( m_listView ); + while( it.current() ) + { + if( it.current()->isSelected() ) + { + DccTransferPanelItem* item=static_cast( it.current() ); + DccTransfer* transfer = item->transfer(); + if( transfer->getType() == DccTransfer::Send && transfer->getStatus() >= DccTransfer::Done ) + { + DccTransferSend* newTransfer = KonversationApplication::instance()->getDccTransferManager()->newUpload(); + + newTransfer->setConnectionId( transfer->getConnectionId() ); + newTransfer->setPartnerNick( transfer->getPartnerNick() ); + newTransfer->setFileURL( transfer->getFileURL() ); + newTransfer->setFileName( transfer->getFileName() ); + // FIXME + newTransfer->setOwnIp( transfer->getOwnIp() ); + + if ( newTransfer->queue() ) + newTransfer->start(); + } + } + ++it; + } +} + +void DccTransferPanel::clearDcc() +{ + QPtrList lst; + QListViewItemIterator it( m_listView ); + while( it.current() ) + { + DccTransferPanelItem* item = static_cast( it.current() ); + // should we check that [item] is not null? + if( it.current()->isSelected() && item->transfer()->getStatus() >= DccTransfer::Done ) + lst.append( it.current() ); + ++it; + } + + // Figure out the first 'gap' in the selection and select that item, + // or, if there are no gaps, select first item below the selection + QPtrListIterator selected( lst ); + bool itemSelected = false; + while( selected.current() ) + { + if (selected.current()->itemBelow() && !lst.containsRef(selected.current()->itemBelow())) + { + m_listView->setSelected(selected.current()->itemBelow(),true); + m_listView->setCurrentItem(selected.current()->itemBelow()); + itemSelected = true; + break; + } + ++selected; + } + + // When there are neither gaps in nor items below the selection, select the first item + if (!itemSelected) + { + m_listView->setSelected(m_listView->firstChild(),true); + m_listView->setCurrentItem(m_listView->firstChild()); + } + + lst.setAutoDelete( true ); + while( lst.remove() ) ; + updateButton(); +} + +void DccTransferPanel::runDcc() +{ + QListViewItemIterator it( m_listView ); + while( it.current() ) + { + if( it.current()->isSelected() ) + { + DccTransferPanelItem* item=static_cast( it.current() ); + DccTransfer* transfer = item->transfer(); + if( transfer->getType() == DccTransfer::Send || transfer->getStatus() == DccTransfer::Done ) + item->runFile(); + } + ++it; + } +} + +void DccTransferPanel::showFileInfo() +{ + QListViewItemIterator it( m_listView ); + while( it.current() ) + { + if( it.current()->isSelected() ) + { + DccTransferPanelItem* item=static_cast( it.current() ); + if( item->transfer()->getType() == DccTransfer::Send || item->transfer()->getStatus() == DccTransfer::Done ) + item->openFileInfoDialog(); + } + ++it; + } +} + +void DccTransferPanel::selectAll() +{ + QListViewItemIterator it( m_listView ); + while ( it.current() ) + { + m_listView->setSelected( *it, true ); + ++it; + } + updateButton(); +} + +void DccTransferPanel::selectAllCompleted() +{ + QListViewItemIterator it( m_listView ); + while ( it.current() ) + { + DccTransferPanelItem* item=static_cast( it.current() ); + m_listView->setSelected( *it, item->transfer()->getStatus() >= DccTransfer::Done ); + ++it; + } + updateButton(); +} + +void DccTransferPanel::popupRequested(QListViewItem* /* item */, const QPoint& pos, int /* col */) // slot +{ + updateButton(); + m_popup->popup(pos); +} + +void DccTransferPanel::popupActivated( int id ) // slot +{ + if ( id == Popup::Abort ) abortDcc(); + else if ( id == Popup::Accept ) acceptDcc(); + else if ( id == Popup::Clear ) clearDcc(); + else if ( id == Popup::Info ) showFileInfo(); + else if ( id == Popup::Open ) runDcc(); + else if ( id == Popup::SelectAll ) selectAll(); + else if ( id == Popup::SelectAllCompleted ) selectAllCompleted(); + else if ( id == Popup::Resend ) resendFile(); +} + +void DccTransferPanel::doubleClicked(QListViewItem* _item, const QPoint& /* _pos */, int /* _col */) +{ + DccTransferPanelItem* item = static_cast(_item); + item->runFile(); +} + +// virtual +void DccTransferPanel::childAdjustFocus() +{ +} + +KListView* DccTransferPanel::getListView() +{ + return m_listView; +} + +#include "dcctransferpanel.moc" diff --git a/konversation/src/dcctransferpanel.h b/konversation/src/dcctransferpanel.h new file mode 100644 index 0000000..882edb7 --- /dev/null +++ b/konversation/src/dcctransferpanel.h @@ -0,0 +1,113 @@ +/* + 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. +*/ + +/* + begin: Mit Aug 7 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ +// Copyright (C) 2004-2007 Shintaro Matsuoka + +#ifndef DCCTRANSFERPANEL_H +#define DCCTRANSFERPANEL_H + +#include "chatwindow.h" +#include "dcctransferpanelitem.h" + + +class QContextMenuEvent; +class QPushButton; +class KListView; +class KPopupMenu; + +class DccTransferDetailedInfoPanel; + +class DccTransferPanel : public ChatWindow +{ + Q_OBJECT + + public: + class Column + { + public: + enum Object + { + TypeIcon, + OfferDate, + Status, + FileName, + PartnerNick, + Progress, + Position, + TimeLeft, + CurrentSpeed, + SenderAddress, + COUNT + }; + }; + + class Popup + { + public: + enum Object + { + SelectAll, + SelectAllCompleted, + Accept, + Abort, + Clear, + Open, + Info, + Resend + }; + }; + + DccTransferPanel(QWidget* parent); + ~DccTransferPanel(); + + KListView* getListView(); + + protected slots: + void slotNewTransferAdded( DccTransfer* transfer ); + void slotTransferStatusChanged(); + + void acceptDcc(); + void abortDcc(); + void resendFile(); + void clearDcc(); + void runDcc(); + void showFileInfo(); + void selectAll(); + void selectAllCompleted(); + + void popupRequested(QListViewItem* item,const QPoint& pos,int col); + void popupActivated(int id); + + void doubleClicked(QListViewItem* _item,const QPoint& _pos,int _col); + + void updateButton(); + + void setDetailPanelItem(QListViewItem* item_); + + protected: + /** Called from ChatWindow adjustFocus */ + virtual void childAdjustFocus(); + + void initGUI(); + + KListView* m_listView; + KPopupMenu* m_popup; + + DccTransferDetailedInfoPanel* m_detailPanel; + + QPushButton* m_buttonAccept; + QPushButton* m_buttonAbort; + QPushButton* m_buttonClear; + QPushButton* m_buttonOpen; + QPushButton* m_buttonDetail; +}; +#endif diff --git a/konversation/src/dcctransferpanelitem.cpp b/konversation/src/dcctransferpanelitem.cpp new file mode 100644 index 0000000..811828c --- /dev/null +++ b/konversation/src/dcctransferpanelitem.cpp @@ -0,0 +1,403 @@ +/* + begin: Mit Aug 7 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ +// Copyright (C) 2004-2007 Shintaro Matsuoka +// Copyright (C) 2004,2005 John Tapsell + +/* + 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. +*/ + +#include "dcctransferpanelitem.h" +#include "dcctransferpanel.h" +#include "konversationapplication.h" +#include "config/preferences.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +DccTransferPanelItem::DccTransferPanelItem( DccTransferPanel* panel, DccTransfer* transfer ) + : KListViewItem( panel->getListView() ) + , m_panel( panel ) + , m_transfer( transfer ) + , m_isTransferInstanceBackup( false ) +{ + m_autoUpdateViewTimer = 0; + + m_progressBar = new KProgress( 100, listView()->viewport() ); + m_progressBar->setCenterIndicator( true ); + m_progressBar->setPercentageVisible( true ); + + connect( m_transfer, SIGNAL( transferStarted( DccTransfer* ) ), this, SLOT( startAutoViewUpdate() ) ); + connect( m_transfer, SIGNAL( done( DccTransfer* ) ), this, SLOT( stopAutoViewUpdate() ) ); + connect( m_transfer, SIGNAL( done( DccTransfer* ) ), this, SLOT( backupTransferInfo( DccTransfer* ) ) ); + + connect( m_transfer, SIGNAL( statusChanged( DccTransfer*, int, int ) ), this, SLOT( slotStatusChanged( DccTransfer*, int, int ) ) ); + + updateView(); +} + +DccTransferPanelItem::~DccTransferPanelItem() +{ + kdDebug() << "DccTransferPanelItem::~DccTransferPanelItem()" << endl; + stopAutoViewUpdate(); + delete m_progressBar; + if ( m_isTransferInstanceBackup ) + delete m_transfer; +} + +void DccTransferPanelItem::updateView() +{ + setPixmap( DccTransferPanel::Column::TypeIcon, getTypeIcon() ); + setPixmap( DccTransferPanel::Column::Status, getStatusIcon() ); + + setText( DccTransferPanel::Column::OfferDate, m_transfer->getTimeOffer().toString( "hh:mm:ss" ) ); + setText( DccTransferPanel::Column::Status, getStatusText() ); + setText( DccTransferPanel::Column::FileName, m_transfer->getFileName() ); + setText( DccTransferPanel::Column::PartnerNick, m_transfer->getPartnerNick() ); + setText( DccTransferPanel::Column::Position, getPositionPrettyText() ); + setText( DccTransferPanel::Column::TimeLeft, getTimeLeftPrettyText() ); + setText( DccTransferPanel::Column::CurrentSpeed, getCurrentSpeedPrettyText() ); + setText( DccTransferPanel::Column::SenderAddress, getSenderAddressPrettyText() ); + + if ( m_transfer->getFileSize() ) + m_progressBar->setProgress( m_transfer->getProgress() ); + else // filesize is unknown + { + m_progressBar->hide(); + setText( DccTransferPanel::Column::Progress, i18n( "unknown" ) ); + } +} + + +int DccTransferPanelItem::compare( QListViewItem* i, int col, bool ascending ) const +{ + DccTransferPanelItem* item = static_cast( i ); + + switch ( col ) + { + case DccTransferPanel::Column::TypeIcon: + if ( m_transfer->getType() > item->transfer()->getType() ) return 1; + if ( m_transfer->getType() < item->transfer()->getType() ) return -1; + return 0; + break; + case DccTransferPanel::Column::OfferDate: + if ( m_transfer->getTimeOffer() > item->transfer()->getTimeOffer() ) return 1; + if ( m_transfer->getTimeOffer() < item->transfer()->getTimeOffer() ) return -1; + return 0; + break; + case DccTransferPanel::Column::Status: + if ( m_transfer->getStatus() > item->transfer()->getStatus() ) return 1; + if ( m_transfer->getStatus() < item->transfer()->getStatus() ) return -1; + return 0; + break; + case DccTransferPanel::Column::Position: + if ( m_transfer->getTransferringPosition() > item->transfer()->getTransferringPosition() ) return 1; + if ( m_transfer->getTransferringPosition() < item->transfer()->getTransferringPosition() ) return -1; + return 0; + break; + case DccTransferPanel::Column::TimeLeft: + if ( m_transfer->getTimeLeft() > item->transfer()->getTimeLeft() ) return 1; + if ( m_transfer->getTimeLeft() < item->transfer()->getTimeLeft() ) return -1; + return 0; + break; + case DccTransferPanel::Column::CurrentSpeed: + if ( m_transfer->getCurrentSpeed() > item->transfer()->getCurrentSpeed() ) return 1; + if ( m_transfer->getCurrentSpeed() < item->transfer()->getCurrentSpeed() ) return -1; + return 0; + break; + default: + return QListViewItem::compare( i, col, ascending ); + } + return QListViewItem::compare( i, col, ascending ); +} + +void DccTransferPanelItem::slotStatusChanged( DccTransfer* /* transfer */, int newStatus, int /* oldStatus */ ) +{ + updateView(); + + if ( newStatus == DccTransfer::Transferring ) + startAutoViewUpdate(); +} + +void DccTransferPanelItem::startAutoViewUpdate() +{ + stopAutoViewUpdate(); + m_autoUpdateViewTimer = new QTimer( this ); + connect( m_autoUpdateViewTimer, SIGNAL( timeout() ), this, SLOT( updateView()) ); + m_autoUpdateViewTimer->start( 500 ); +} + +void DccTransferPanelItem::stopAutoViewUpdate() +{ + if ( m_autoUpdateViewTimer ) + { + m_autoUpdateViewTimer->stop(); + delete m_autoUpdateViewTimer; + m_autoUpdateViewTimer = 0; + } +} + +void DccTransferPanelItem::paintCell( QPainter* painter, const QColorGroup& colorgroup, int column, int width, int alignment ) // virtual public +{ + KListViewItem::paintCell( painter, colorgroup, column, width, alignment ); + if ( column == DccTransferPanel::Column::Progress ) + showProgressBar(); +} + +void DccTransferPanelItem::showProgressBar() +{ + if ( m_transfer->getFileSize() ) + { + QRect rect = listView()->itemRect( this ); + QHeader *head = listView()->header(); + rect.setLeft( head->sectionPos( DccTransferPanel::Column::Progress ) - head->offset() ); + rect.setWidth( head->sectionSize( DccTransferPanel::Column::Progress ) ); + m_progressBar->setGeometry( rect ); + m_progressBar->show(); + } +} + +void DccTransferPanelItem::runFile() +{ + if ( m_transfer->getType() == DccTransfer::Send || m_transfer->getStatus() == DccTransfer::Done ) + new KRun( m_transfer->getFileURL(), listView() ); +} + +void DccTransferPanelItem::openFileInfoDialog() +{ + if ( m_transfer->getType() == DccTransfer::Send || m_transfer->getStatus() == DccTransfer::Done ) + { + QStringList infoList; + + QString path=m_transfer->getFileURL().path(); + + // get meta info object + KFileMetaInfo fileInfo(path,QString(),KFileMetaInfo::Everything); + + // is there any info for this file? + if(!fileInfo.isEmpty()) + { + // get list of meta information groups + QStringList groupList=fileInfo.groups(); + // look inside for keys + for(unsigned int index=0;index"+infoList.join("
")+"", + i18n("File Information") + ); + #endif + } + } + else + { + KMessageBox::sorry(listView(),i18n("No detailed information for this file found."),i18n("File Information")); + } + } +} + +void DccTransferPanelItem::backupTransferInfo( DccTransfer* transfer ) +{ + kdDebug() << "DccTransferPanelItem::backupTransferInfo()" << endl; + // instances of DccTransfer are deleted immediately after the transfer is done + // so we need to make a backup of DccTransfer. + + m_transfer = new DccTransfer( *transfer ); + m_isTransferInstanceBackup = true; +} + +QString DccTransferPanelItem::getTypeText() const +{ + if ( m_transfer->getType() == DccTransfer::Send ) + return i18n( "Send" ); + else + return i18n( "Receive" ); +} + +QPixmap DccTransferPanelItem::getTypeIcon() const +{ + if ( m_transfer->getType() == DccTransfer::Send ) + return KGlobal::iconLoader()->loadIcon( "up", KIcon::Small ); + else + return KGlobal::iconLoader()->loadIcon( "down", KIcon::Small ); +} + +QPixmap DccTransferPanelItem::getStatusIcon() const +{ + QString icon; + switch ( m_transfer->getStatus() ) + { + case DccTransfer::Queued: + icon = "player_stop"; + break; + case DccTransfer::Preparing: + case DccTransfer::WaitingRemote: + case DccTransfer::Connecting: + icon = "goto"; + break; + case DccTransfer::Transferring: + icon = "player_play"; + break; + case DccTransfer::Done: + icon = "ok"; + break; + case DccTransfer::Aborted: + case DccTransfer::Failed: + icon = "stop"; + break; + default: + break; + } + return KGlobal::iconLoader()->loadIcon( icon, KIcon::Small ); +} + +QString DccTransferPanelItem::getStatusText() const +{ + DccTransfer::DccStatus status = m_transfer->getStatus(); + DccTransfer::DccType type = m_transfer->getType(); + + if ( status == DccTransfer::Queued ) + return i18n( "Queued" ); + else if ( status == DccTransfer::Preparing ) + return i18n( "Preparing" ); + else if ( status == DccTransfer::WaitingRemote ) + return i18n( "Awaiting" ); + else if ( status == DccTransfer::Connecting ) + return i18n( "Connecting" ); + else if ( status == DccTransfer::Transferring && type == DccTransfer::Receive ) + return i18n( "Receiving" ); + else if ( status == DccTransfer::Transferring && type == DccTransfer::Send ) + return i18n( "Sending" ); + else if ( status == DccTransfer::Done ) + return i18n( "Done" ); + else if ( status == DccTransfer::Failed ) + return i18n( "Failed" ); + else if ( status == DccTransfer::Aborted ) + return i18n( "Aborted" ); + + return QString(); +} + +QString DccTransferPanelItem::getFileSizePrettyText() const +{ + return KIO::convertSize( m_transfer->getFileSize() ); +} + +QString DccTransferPanelItem::getPositionPrettyText( bool detailed ) const +{ + if ( detailed ) + return KGlobal::locale()->formatNumber( m_transfer->getTransferringPosition(), 0 ) + " / " + + KGlobal::locale()->formatNumber( m_transfer->getFileSize(), 0 ); + else + return KIO::convertSize( m_transfer->getTransferringPosition() ) + " / " + KIO::convertSize( m_transfer->getFileSize() ); +} + +QString DccTransferPanelItem::getTimeLeftPrettyText() const +{ + QString text; + + if ( m_transfer->getTimeLeft() == DccTransfer::NotInTransfer ) + ; + else if ( m_transfer->getTimeLeft() == DccTransfer::InfiniteValue ) + text = "?"; + else + text = secToHMS( m_transfer->getTimeLeft() ); + + return text; +} + +QString DccTransferPanelItem::getAverageSpeedPrettyText() const +{ + return getSpeedPrettyText( m_transfer->getAverageSpeed() ); +} + +QString DccTransferPanelItem::getCurrentSpeedPrettyText() const +{ + return getSpeedPrettyText( m_transfer->getCurrentSpeed() ); +} + +QString DccTransferPanelItem::getSenderAddressPrettyText() const +{ + if ( m_transfer->getType() == DccTransfer::Send ) + return QString( "%1:%2" ).arg( m_transfer->getOwnIp() ).arg( m_transfer->getOwnPort() ); + else + return QString( "%1:%2" ).arg( m_transfer->getPartnerIp() ).arg( m_transfer->getPartnerPort() ); +} + +QString DccTransferPanelItem::getSpeedPrettyText( transferspeed_t speed ) +{ + if ( speed == DccTransfer::Calculating || speed == DccTransfer::InfiniteValue ) + return QString( "?" ); + else if ( speed == DccTransfer::NotInTransfer ) + return QString(); + else + return i18n("%1/sec").arg( KIO::convertSize( (KIO::fileoffset_t)speed ) ); +} + +QString DccTransferPanelItem::secToHMS( long sec ) +{ + int remSec = sec; + int remHour = remSec / 3600; remSec -= remHour * 3600; + int remMin = remSec / 60; remSec -= remMin * 60; + + // remHour can be more than 25, so we can't use QTime here. + return QString( "%1:%2:%3" ) + .arg( QString::number( remHour ).rightJustify( 2, '0', false ) ) + .arg( QString::number( remMin ).rightJustify( 2, '0' ) ) + .arg( QString::number( remSec ).rightJustify( 2, '0' ) ); +} + +#include "dcctransferpanelitem.moc" diff --git a/konversation/src/dcctransferpanelitem.h b/konversation/src/dcctransferpanelitem.h new file mode 100644 index 0000000..e9fbb84 --- /dev/null +++ b/konversation/src/dcctransferpanelitem.h @@ -0,0 +1,98 @@ +/* + begin: Mit Aug 7 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ +// Copyright (C) 2004-2007 Shintaro Matsuoka +// Copyright (C) 2004,2005 John Tapsell + +/* + 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. +*/ + +#ifndef DCCTRANSFERPANELITEM_H +#define DCCTRANSFERPANELITEM_H + +#include "dcctransfer.h" + +#include + +#include +#include +#include + + +class QStringList; +class QTimer; + +class KProgress; + +namespace KIO +{ + class Job; +} + +class DccTransferPanel; + +class DccTransferPanelItem : public QObject, public KListViewItem +{ + Q_OBJECT + + public: + DccTransferPanelItem( DccTransferPanel* panel, DccTransfer* transfer ); + virtual ~DccTransferPanelItem(); + + virtual void paintCell( QPainter* painter, const QColorGroup& colorgroup, int column, int width, int alignment ); + + virtual int compare( QListViewItem* i, int col, bool ascending ) const; + + void runFile(); + void openFileInfoDialog(); + + DccTransfer* transfer() const { return m_transfer; } + + // called from updateView() + QString getTypeText() const; + QPixmap getTypeIcon() const; + QPixmap getStatusIcon() const; + QString getStatusText() const; + QString getFileSizePrettyText() const; + QString getPositionPrettyText( bool detailed = false ) const; + QString getTimeLeftPrettyText() const; + QString getAverageSpeedPrettyText() const; + QString getCurrentSpeedPrettyText() const; + QString getSenderAddressPrettyText() const; + + static QString getSpeedPrettyText( transferspeed_t speed ); + static QString secToHMS( long sec ); + + private slots: + void slotStatusChanged( DccTransfer* transfer, int newStatus, int oldStatus ); + void updateView(); + + private: + DccTransferPanel* m_panel; + DccTransfer* m_transfer; + bool m_isTransferInstanceBackup; + + private slots: + void startAutoViewUpdate(); + void stopAutoViewUpdate(); + + void backupTransferInfo( DccTransfer* transfer ); + + private: + void updateTransferInfo(); + void updateTransferMeters(); + + void showProgressBar(); // called from printCell() + + // UI + QTimer* m_autoUpdateViewTimer; + KProgress* m_progressBar; +}; + +#endif // DCCTRANSFERPANELITEM_H diff --git a/konversation/src/dcctransferrecv.cpp b/konversation/src/dcctransferrecv.cpp new file mode 100644 index 0000000..a1b69d3 --- /dev/null +++ b/konversation/src/dcctransferrecv.cpp @@ -0,0 +1,799 @@ +/* + receive a file on DCC protocol + begin: Mit Aug 7 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ +// Copyright (C) 2004-2007 Shintaro Matsuoka +// Copyright (C) 2004,2005 John Tapsell + +/* + 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. +*/ + +#include "dcctransferrecv.h" +#include "dcccommon.h" +#include "channel.h" +#include "dcctransfermanager.h" +#include "konversationapplication.h" +#include "connectionmanager.h" +#include "server.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +class DccResumeDialog; + +/* + *flow chart* + + DccTransferRecv() + + start() : called from DccTransferPanel when user pushes the accept button + | \ + | requestResume() : called when user chooses to resume in DccResumeDialog. it emits the signal ResumeRequest() + | + | startResume() : called by "Server" + | | +connectToSender() + +connectionSuccess() : called by recvSocket + +*/ + +DccTransferRecv::DccTransferRecv(QObject* parent) + : DccTransfer( DccTransfer::Receive, parent ) +{ + kdDebug() << "DccTransferRecv::DccTransferRecv()" << endl; + + m_serverSocket = 0; + m_recvSocket = 0; + m_writeCacheHandler = 0; + + m_connectionTimer = new QTimer( this ); + connect( m_connectionTimer, SIGNAL( timeout() ), this, SLOT( connectionTimeout() ) ); + //timer hasn't started yet. qtimer will be deleted automatically when 'this' object is deleted +} + +DccTransferRecv::~DccTransferRecv() +{ + cleanUp(); +} + +QString DccTransferRecv::getTypeText() const +{ + return i18n( "Receive" ); +} + +QPixmap DccTransferRecv::getTypeIcon() const +{ + return KGlobal::iconLoader()->loadIcon( "down", KIcon::Small ); +} + +void DccTransferRecv::cleanUp() +{ + kdDebug() << "DccTransferRecv::cleanUp()" << endl; + + stopConnectionTimer(); + finishTransferLogger(); + if ( m_serverSocket ) + { + m_serverSocket->close(); + m_serverSocket = 0; + } + if ( m_recvSocket ) + { + m_recvSocket->close(); + m_recvSocket = 0; // the instance will be deleted automatically by its parent + } + if ( m_writeCacheHandler ) + { + m_writeCacheHandler->closeNow(); + m_writeCacheHandler->deleteLater(); + m_writeCacheHandler = 0; + } +} + +// just for convenience +void DccTransferRecv::failed( const QString& errorMessage ) +{ + setStatus( Failed, errorMessage ); + cleanUp(); + emit done( this ); +} + +void DccTransferRecv::setPartnerIp( const QString& ip ) +{ + if ( getStatus() == Configuring ) + m_partnerIp = ip; +} + +void DccTransferRecv::setPartnerPort( const QString& port ) +{ + if ( getStatus() == Configuring ) + m_partnerPort = port; +} + +void DccTransferRecv::setFileSize( unsigned long fileSize ) +{ + if ( getStatus() == Configuring ) + m_fileSize = fileSize; +} + +void DccTransferRecv::setFileName( const QString& fileName ) +{ + if ( getStatus() == Configuring ) + m_fileName = fileName; +} + +void DccTransferRecv::setFileURL( const KURL& url ) +{ + if ( getStatus() == Configuring || getStatus() == Queued ) + m_fileURL = url; +} + +void DccTransferRecv::setReverse( bool reverse, const QString& reverseToken ) +{ + if ( getStatus() == Configuring ) + { + m_reverse = reverse; + if ( reverse ) + { + m_partnerPort = QString::number( 0 ); + m_reverseToken = reverseToken; + } + } +} + +bool DccTransferRecv::queue() +{ + kdDebug() << "DccTransferRecv::queue()" << endl; + + if ( getStatus() != Configuring ) + return false; + + if ( m_partnerIp.isEmpty() || m_partnerPort.isEmpty() ) + return false; + + if (!kapp->authorize("allow_downloading")) + { + //note we have this after the initialisations so that item looks okay + //Do not have the rights to send the file. Shouldn't have gotten this far anyway + failed(i18n("The admin has restricted the right to receive files")); + return false; + } + + // check if the sender IP is valid + if ( m_partnerIp == "0.0.0.0" ) + { + failed( i18n( "Invalid sender address (%1)" ).arg( m_partnerIp ) ); + return false; + } + + // TODO: should we support it? + if ( m_fileSize == 0 ) + { + failed( i18n( "Unsupported negotiation (filesize=0)" ) ); + return false; + } + + if ( m_fileName.isEmpty() ) + { + m_fileName = "unnamed_file"; + } + + if ( m_fileURL.isEmpty() ) + { + // determine default incoming file URL + + // set default folder + if ( !Preferences::dccPath().isEmpty() ) + m_fileURL = KURL( Preferences::dccPath() ); + else + m_fileURL.setPath( KUser( KUser::UseRealUserID ).homeDir() ); // default folder is *not* specified + + // add a slash if there is none + m_fileURL.adjustPath( 1 ); + + // Append folder with partner's name if wanted + if ( Preferences::dccCreateFolder() ) + m_fileURL.addPath( m_partnerNick + '/' ); + + // Just incase anyone tries to do anything nasty + QString fileNameSanitized = sanitizeFileName( m_fileName ); + + // Append partner's name to file name if wanted + if ( Preferences::dccAddPartner() ) + m_fileURL.addPath( m_partnerNick + '.' + fileNameSanitized ); + else + m_fileURL.addPath( fileNameSanitized ); + } + + return DccTransfer::queue(); +} + +void DccTransferRecv::abort() // public slot +{ + kdDebug() << "DccTransferRecv::abort()" << endl; + + if(m_writeCacheHandler) + { + m_writeCacheHandler->write( true ); // flush + } + + setStatus( Aborted ); + cleanUp(); + emit done( this ); +} + +void DccTransferRecv::start() // public slot +{ + kdDebug() << "DccTransferRecv::start() [BEGIN]" << endl; + + if ( getStatus() != Queued ) + return; + + setStatus( Preparing ); + + prepareLocalKio( false, false ); + + kdDebug() << "DccTransferRecv::start() [END]" << endl; +} + +void DccTransferRecv::prepareLocalKio( bool overwrite, bool resume, KIO::fileoffset_t startPosition /* = 0 */ ) +{ + kdDebug() << "DccTransferRecv::prepareLocalKio()" << endl + << "DccTransferRecv::prepareLocalKio(): URL: " << m_fileURL << endl + << "DccTransferRecv::prepareLocalKio(): Overwrite: " << overwrite << endl + << "DccTransferRecv::prepareLocalKio(): Resume: " << resume << " (Position: " << QString::number( startPosition ) << ")" << endl; + + m_resumed = resume; + m_transferringPosition = startPosition; + + if ( !createDirs( m_fileURL.upURL() ) ) + { + askAndPrepareLocalKio( i18n( "Cannot create the folder.
" + "Folder: %1
" ) + .arg( m_fileURL.upURL().prettyURL() ), + DccResumeDialog::RA_Rename | DccResumeDialog::RA_Cancel, + DccResumeDialog::RA_Rename ); + return; + } + + KIO::TransferJob* transferJob = KIO::put( m_fileURL, -1, overwrite, m_resumed, false ); + + if ( !transferJob ) + { + kdDebug() << "DccTransferRecv::prepareLocalKio(): KIO::put() returned NULL. what happened?" << endl; + failed( i18n( "Could not create a KIO instance" ) ); + return; + } + + connect( transferJob, SIGNAL( canResume( KIO::Job*, KIO::filesize_t ) ), this, SLOT( slotLocalCanResume( KIO::Job*, KIO::filesize_t ) ) ); + connect( transferJob, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotLocalGotResult( KIO::Job* ) ) ); + connect( transferJob, SIGNAL( dataReq( KIO::Job*, QByteArray& ) ), this, SLOT( slotLocalReady( KIO::Job* ) ) ); +} + +void DccTransferRecv::askAndPrepareLocalKio( const QString& message, int enabledActions, DccResumeDialog::ReceiveAction defaultAction, KIO::fileoffset_t startPosition ) +{ + switch ( DccResumeDialog::ask( this, message, enabledActions, defaultAction ) ) + { + case DccResumeDialog::RA_Resume: + prepareLocalKio( false, true, startPosition ); + break; + case DccResumeDialog::RA_Overwrite: + prepareLocalKio( true, false ); + break; + case DccResumeDialog::RA_Rename: + prepareLocalKio( false, false ); + break; + case DccResumeDialog::RA_Cancel: + default: + setStatus( Queued ); + } +} + +bool DccTransferRecv::createDirs( const KURL& dirURL ) const +{ + KURL kurl( dirURL ); + QString surl = kurl.url(); + + //First we split directories until we reach to the top, + //since we need to create directories one by one + + QStringList dirList; + while ( surl != kurl.upURL().url() ) + { + dirList.prepend( surl ); + kurl = kurl.upURL(); + surl = kurl.url(); + } + + //Now we create the directories + + QStringList::ConstIterator it; + for ( it=dirList.begin() ; it!=dirList.end() ; ++it ) + if ( !KIO::NetAccess::exists( *it, true, NULL ) ) + if ( !KIO::NetAccess::mkdir( *it, NULL, -1 ) ) + return false; + + return true; +} + +void DccTransferRecv::slotLocalCanResume( KIO::Job* job, KIO::filesize_t size ) +{ + kdDebug() << "DccTransferRecv::slotLocalCanResume() [BEGIN]" << endl + << "DccTransferRecv::slotLocalCanResume(): size: " << QString::number( size ) << endl; + + if ( size != 0 ) + { + KIO::TransferJob* transferJob = static_cast( job ); + + disconnect( transferJob, 0, 0, 0 ); + transferJob->kill(); + + if ( KonversationApplication::instance()->getDccTransferManager()->isLocalFileInWritingProcess( m_fileURL ) ) + { + askAndPrepareLocalKio( i18n( "The file is used by another transfer.
" + "%1
" ) + .arg( m_fileURL.prettyURL() ), + DccResumeDialog::RA_Rename | DccResumeDialog::RA_Cancel, + DccResumeDialog::RA_Rename ); + } + else if ( Preferences::dccAutoResume() ) + { + prepareLocalKio( false, true, size ); + } + else + { + askAndPrepareLocalKio( i18n( "A partial file exists.
" + "%1
" + "Size of the partial file: %2 bytes
" ) + .arg( m_fileURL.prettyURL() ) + .arg( KGlobal::locale()->formatNumber( size, 0 ) ), + DccResumeDialog::RA_Resume | DccResumeDialog::RA_Overwrite | DccResumeDialog::RA_Rename | DccResumeDialog::RA_Cancel, + DccResumeDialog::RA_Resume, + size ); + } + } + + kdDebug() << "DccTransferRecv::slotLocalCanResume() [END]" << endl; +} + +void DccTransferRecv::slotLocalGotResult( KIO::Job* job ) +{ + kdDebug() << "DccTransferRecv::slotLocalGotResult() [BEGIN]" << endl; + + KIO::TransferJob* transferJob = static_cast( job ); + disconnect( transferJob, 0, 0, 0 ); + + switch ( transferJob->error() ) + { + case 0: // no error + kdDebug() << "DccTransferRecv::slotLocalGotResult(): job->error() returned 0." << endl + << "DccTransferRecv::slotLocalGotResult(): Why was I called in spite of no error?" << endl; + break; + case KIO::ERR_FILE_ALREADY_EXIST: + askAndPrepareLocalKio( i18n( "The file already exists.
" + "%1
" ) + .arg( m_fileURL.prettyURL() ), + DccResumeDialog::RA_Overwrite | DccResumeDialog::RA_Rename | DccResumeDialog::RA_Cancel, + DccResumeDialog::RA_Overwrite ); + break; + default: + askAndPrepareLocalKio( i18n( "Could not open the file.
" + "Error: %1

" + "%2
" ) + .arg( transferJob->error() ) + .arg( m_fileURL.prettyURL() ), + DccResumeDialog::RA_Rename | DccResumeDialog::RA_Cancel, + DccResumeDialog::RA_Rename ); + } + + kdDebug() << "DccTransferRecv::slotLocalGotResult() [END]" << endl; +} + +void DccTransferRecv::slotLocalReady( KIO::Job* job ) +{ + kdDebug() << "DccTransferRecv::slotLocalReady()" << endl; + + KIO::TransferJob* transferJob = static_cast( job ); + + disconnect( transferJob, 0, 0, 0 ); // WriteCacheHandler will control the job after this + + m_writeCacheHandler = new DccTransferRecvWriteCacheHandler( transferJob ); + + connect( m_writeCacheHandler, SIGNAL( done() ), this, SLOT( slotLocalWriteDone() ) ); + connect( m_writeCacheHandler, SIGNAL( gotError( const QString& ) ), this, SLOT( slotLocalGotWriteError( const QString& ) ) ); + + if ( !m_resumed ) + connectWithSender(); + else + requestResume(); +} + +void DccTransferRecv::connectWithSender() +{ + if ( m_reverse ) + { + if ( !startListeningForSender() ) + return; + + Server* server = KonversationApplication::instance()->getConnectionManager()->getServerByConnectionId( m_connectionId ); + if ( !server ) + { + failed( i18n( "Could not send Reverse DCC SEND acknowledgement to the partner via the IRC server." ) ); + } + + m_ownIp = DccCommon::getOwnIp( server ); + m_ownPort = QString::number( DccCommon::getServerSocketPort( m_serverSocket ) ); + + setStatus( WaitingRemote, i18n( "Waiting for connection" ) ); + + server->dccReverseSendAck( m_partnerNick, m_fileName, DccCommon::textIpToNumericalIp( m_ownIp ), m_ownPort, m_fileSize, m_reverseToken ); + + //FIXME: add connection timer here + } + else + { + connectToSendServer(); + } +} + +void DccTransferRecv::requestResume() +{ + kdDebug() << "DccTransferRecv::requestResume()" << endl; + + setStatus( WaitingRemote, i18n( "Waiting for remote host's acceptance" ) ); + + startConnectionTimer( 30 ); + + kdDebug() << "DccTransferRecv::requestResume(): requesting resume for " << m_partnerNick << " file " << m_fileName << " partner " << m_partnerPort << endl; + + //TODO m_filename could have been sanitized - will this effect this? + Server* server = KonversationApplication::instance()->getConnectionManager()->getServerByConnectionId( m_connectionId ); + if ( !server ) + { + kdDebug() << "DccTransferSend::start(): could not retrieve the instance of Server. Connection id: " << m_connectionId << endl; + failed( i18n( "Could not send DCC RECV resume request to the partner via the IRC server." ) ); + return; + } + + server->dccResumeGetRequest( m_partnerNick, m_fileName, m_partnerPort, m_transferringPosition ); +} + + // public slot +void DccTransferRecv::startResume( unsigned long position ) +{ + kdDebug() << "DccTransferRecv::startResume(): position: " << position << endl; + + stopConnectionTimer(); + + if ( (unsigned long)m_transferringPosition != position ) + { + kdDebug() << "DccTransferRecv::startResume(): remote responsed an unexpected position" << endl + << "DccTransferRecv::startResume(): expected: " << QString::number( m_transferringPosition ) << endl + << "DccTransferRecv::startResume(): remote response: " << position << endl; + failed( i18n( "Unexpected response from remote host" ) ); + return; + } + + connectWithSender(); +} + +void DccTransferRecv::connectToSendServer() +{ + kdDebug() << "DccTransferRecv::connectToSendServer()" << endl; + + // connect to sender + + setStatus( Connecting ); + + m_recvSocket = new KNetwork::KStreamSocket( m_partnerIp, m_partnerPort, this); + + m_recvSocket->setBlocking( false ); // asynchronous mode + m_recvSocket->setFamily( KNetwork::KResolver::InetFamily ); + m_recvSocket->setResolutionEnabled( false ); + m_recvSocket->setTimeout( 30000 ); + + m_recvSocket->enableRead( false ); + m_recvSocket->enableWrite( false ); + + connect( m_recvSocket, SIGNAL( connected( const KResolverEntry& ) ), this, SLOT( startReceiving() ) ); + connect( m_recvSocket, SIGNAL( gotError( int ) ), this, SLOT( connectionFailed( int ) ) ); + + kdDebug() << "DccTransferRecv::connectToServer(): attempting to connect to " << m_partnerIp << ":" << m_partnerPort << endl; + + m_recvSocket->connect(); +} + +bool DccTransferRecv::startListeningForSender() +{ + // Set up server socket + QString failedReason; + if ( Preferences::dccSpecificSendPorts() ) + m_serverSocket = DccCommon::createServerSocketAndListen( this, &failedReason, Preferences::dccSendPortsFirst(), Preferences::dccSendPortsLast() ); + else + m_serverSocket = DccCommon::createServerSocketAndListen( this, &failedReason ); + if ( !m_serverSocket ) + { + failed( failedReason ); + return false; + } + + connect( m_serverSocket, SIGNAL( readyAccept() ), this, SLOT( slotServerSocketReadyAccept() ) ); + connect( m_serverSocket, SIGNAL( gotError( int ) ), this, SLOT( slotServerSocketGotError( int ) ) ); + + return true; +} + +void DccTransferRecv::slotServerSocketReadyAccept() +{ + //stopConnectionTimer() + + m_recvSocket = static_cast( m_serverSocket->accept() ); + if ( !m_recvSocket ) + { + failed( i18n( "Could not accept the connection. (Socket Error)" ) ); + return; + } + + connect( m_recvSocket, SIGNAL( gotError( int ) ), this, SLOT( connectionFailed( int ) ) ); + + // we don't need ServerSocket anymore + m_serverSocket->close(); + + startReceiving(); +} + +void DccTransferRecv::slotServerSocketGotError( int /* errorCode*/ ) +{ + failed( i18n( "Socket error: %1" ).arg( m_serverSocket->errorString() ) ); +} + +void DccTransferRecv::startReceiving() +{ + kdDebug() << "DccTransferRecv::startReceiving()" << endl; + + m_recvSocket->setBlocking( false ); // asynchronous mode + + connect( m_recvSocket, SIGNAL( readyRead() ), this, SLOT( readData() ) ); + connect( m_recvSocket, SIGNAL( readyWrite() ), this, SLOT( sendAck() ) ); + connect( m_recvSocket, SIGNAL( closed() ), this, SLOT( slotSocketClosed() ) ); + + setStatus( Transferring ); + + m_transferStartPosition = m_transferringPosition; + + m_recvSocket->enableRead( true ); + m_recvSocket->enableWrite( false ); + + startTransferLogger(); // initialize CPS counter, ETA counter, etc... +} + + // slot +void DccTransferRecv::connectionFailed( int errorCode ) +{ + kdDebug() << "DccTransferRecv::connectionFailed(): code = " << errorCode << ", string = " << m_recvSocket->errorString() << endl; + failed( i18n( "Connection failure: %1" ).arg( m_recvSocket->errorString() ) ); +} + +void DccTransferRecv::readData() // slot +{ + //kdDebug() << "readData()" << endl; + int actual = m_recvSocket->readBlock( m_buffer, m_bufferSize ); + if ( actual > 0 ) + { + //actual is the size we read in, and is guaranteed to be less than m_bufferSize + m_transferringPosition += actual; + m_writeCacheHandler->append( m_buffer, actual ); + m_writeCacheHandler->write( false ); + m_recvSocket->enableWrite( true ); + } +} + +void DccTransferRecv::sendAck() // slot +{ + //kdDebug() << "sendAck()" << endl; + KIO::fileoffset_t pos = intel( m_transferringPosition ); + + m_recvSocket->enableWrite( false ); + m_recvSocket->writeBlock( (char*)&pos, 4 ); + if ( m_transferringPosition == (KIO::fileoffset_t)m_fileSize ) + { + kdDebug() << "DccTransferRecv::sendAck(): Sent final ACK." << endl; + m_recvSocket->enableRead( false ); + disconnect( m_recvSocket, 0, 0, 0 ); + finishTransferLogger(); + m_writeCacheHandler->close(); // WriteCacheHandler will send the signal done() + } + else if ( m_transferringPosition > (KIO::fileoffset_t)m_fileSize ) + { + kdDebug() << "DccTransferRecv::sendAck(): the remote host sent larger data than expected: " << QString::number( m_transferringPosition ) << endl; + failed( i18n( "Transferring error" ) ); + } +} + +void DccTransferRecv::slotLocalWriteDone() // <-WriteCacheHandler::done() +{ + kdDebug() << "DccTransferRecv::slotLocalWriteDone()" << endl; + setStatus( Done ); + cleanUp(); + emit done( this ); +} + + // <- WriteCacheHandler::gotError() +void DccTransferRecv::slotLocalGotWriteError( const QString& errorString ) +{ + kdDebug() << "DccTransferRecv::slotLocalGotWriteError()" << endl; + failed( i18n( "KIO error: %1" ).arg( errorString ) ); +} + +void DccTransferRecv::startConnectionTimer( int sec ) +{ + stopConnectionTimer(); + kdDebug() << "DccTransferRecv::startConnectionTimer()" << endl; + m_connectionTimer->start( sec*1000, true ); +} + +void DccTransferRecv::stopConnectionTimer() +{ + if ( m_connectionTimer->isActive() ) + { + m_connectionTimer->stop(); + kdDebug() << "DccTransferRecv::stopConnectionTimer(): stop" << endl; + } +} + +void DccTransferRecv::connectionTimeout() // slot +{ + kdDebug() << "DccTransferRecv::connectionTimeout()" << endl; + failed( i18n( "Timed out" ) ); +} + +void DccTransferRecv::slotSocketClosed() +{ + finishTransferLogger(); + if ( getStatus() == Transferring ) + failed( i18n( "Remote user disconnected" ) ); +} + +// WriteCacheHandler + +DccTransferRecvWriteCacheHandler::DccTransferRecvWriteCacheHandler( KIO::TransferJob* transferJob ) +: m_transferJob( transferJob ) +{ + m_writeReady = true; + m_cacheStream = 0; + + connect( this, SIGNAL( dataFinished() ), m_transferJob, SLOT( slotFinished() ) ); + connect( m_transferJob, SIGNAL( dataReq( KIO::Job*, QByteArray& ) ), this, SLOT( slotKIODataReq( KIO::Job*, QByteArray& ) ) ); + connect( m_transferJob, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotKIOResult( KIO::Job* ) ) ); + + m_transferJob->setAsyncDataEnabled( m_writeAsyncMode = true ); +} + +DccTransferRecvWriteCacheHandler::~DccTransferRecvWriteCacheHandler() +{ + closeNow(); +} + + // public +void DccTransferRecvWriteCacheHandler::append( char* data, int size ) +{ + // sendAsyncData() and dataReq() cost a lot of time, so we should pack some caches. + + // 1meg + static const unsigned int maxWritePacketSize = 1 * 1024 * 1024; + + if ( m_cacheList.isEmpty() || m_cacheList.back().size() + size > maxWritePacketSize ) + { + m_cacheList.append( QByteArray() ); + delete m_cacheStream; + m_cacheStream = new QDataStream( m_cacheList.back(), IO_WriteOnly ); + } + + m_cacheStream->writeRawBytes( data, size ); +} + + // public +bool DccTransferRecvWriteCacheHandler::write( bool force ) +{ + // force == false: return without doing anything when the whole cache size is smaller than maxWritePacketSize + + if ( m_cacheList.isEmpty() || !m_transferJob || !m_writeReady || !m_writeAsyncMode ) + return false; + + if ( !force && m_cacheList.count() < 2 ) + return false; + + // do write + + m_writeReady = false; + m_transferJob->sendAsyncData( m_cacheList.front() ); + //kdDebug() << "DTRWriteCacheHandler::write(): wrote " << m_cacheList.front().size() << " bytes." << endl; + m_cacheList.pop_front(); + + return true; +} + +void DccTransferRecvWriteCacheHandler::close() // public +{ + kdDebug() << "DTRWriteCacheHandler::close()" << endl; + write( true ); // write once if kio is ready to write + m_transferJob->setAsyncDataEnabled( m_writeAsyncMode = false ); + kdDebug() << "DTRWriteCacheHandler::close(): switched to synchronized mode." << endl; + kdDebug() << "DTRWriteCacheHandler::close(): flushing... (remaining caches: " << m_cacheList.count() << ")" << endl; +} + +void DccTransferRecvWriteCacheHandler::closeNow() // public +{ + write( true ); // flush + if ( m_transferJob ) + { + m_transferJob->kill(); + m_transferJob = 0; + } + m_cacheList.clear(); + delete m_cacheStream; + m_cacheStream = 0; +} + +void DccTransferRecvWriteCacheHandler::slotKIODataReq( KIO::Job*, QByteArray& data ) +{ + // We are in writeAsyncMode if there is more data to be read in from dcc + if ( m_writeAsyncMode ) + m_writeReady = true; + else + { + // No more data left to read from incoming dcctransfer + if ( !m_cacheList.isEmpty() ) + { + // once we write everything in cache, the file is complete. + // This function will be called once more after this last data is written. + data = m_cacheList.front(); + kdDebug() << "DccTransferRecvWriteCacheHandler::slotKIODataReq(): will write " << m_cacheList.front().size() << " bytes." << endl; + m_cacheList.pop_front(); + } + else + { + // finally, no data left to write or read. + kdDebug() << "DTRWriteCacheHandler::slotKIODataReq(): flushing done." << endl; + m_transferJob = 0; + emit done(); // -> DccTransferRecv::slotLocalWriteDone() + } + } +} + +void DccTransferRecvWriteCacheHandler::slotKIOResult( KIO::Job* job ) +{ + Q_ASSERT( m_transferJob ); + + disconnect( m_transferJob, 0, 0, 0 ); + m_transferJob = 0; + + if ( job->error() ) + { + QString errorString = job->errorString(); + closeNow(); + emit gotError( errorString ); // -> DccTransferRecv::slotLocalGotWriteError() + } +} + +#include "dcctransferrecv.moc" diff --git a/konversation/src/dcctransferrecv.h b/konversation/src/dcctransferrecv.h new file mode 100644 index 0000000..557b61d --- /dev/null +++ b/konversation/src/dcctransferrecv.h @@ -0,0 +1,184 @@ +/* + receive a file on DCC protocol + begin: Mit Aug 7 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ +// Copyright (C) 2004-2007 Shintaro Matsuoka +// Copyright (C) 2004,2005 John Tapsell + +/* + 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. +*/ + +#ifndef DCCTRANSFERRECV_H +#define DCCTRANSFERRECV_H + +#include "dcctransfer.h" +// TODO: remove the dependence +#include "dccresumedialog.h" + +#include + + +class QFile; +class QTimer; + +namespace KIO +{ + class Job; + class TransferJob; +} + +namespace KNetwork +{ + class KServerSocket; + class KStreamSocket; +} + +class DccTransferRecvWriteCacheHandler; + +class DccTransferRecv : public DccTransfer +{ + Q_OBJECT + + public: + DccTransferRecv(QObject* parent); + virtual ~DccTransferRecv(); + + // REQUIRED + void setPartnerIp( const QString& ip ); + // REQUIRED + void setPartnerPort( const QString& port ); + // REQUIRED + void setFileSize( unsigned long fileSize ); + // OPTIONAL, if not specified, "unnamed_file" + // TODO: "$sendername-$receiveddate" is better + void setFileName( const QString& fileName ); + // OPTIONAL, if not specified, default folder + the file name + void setFileURL( const KURL& url ); + // OPTIONAL + void setReverse( bool reverse, const QString& reverseToken ); + + public slots: + virtual bool queue(); + + /** The user has accepted the download. + * Check we are saving it somewhere valid, create any directories needed, and + * connect to remote host. + */ + virtual void start(); + /** The user has chosen to abort. + * Either by chosen to abort directly, or by choosing cancel when + * prompted for information on where to save etc. + * Not called when it fails due to another problem. + */ + virtual void abort(); + void startResume( unsigned long position ); + + protected slots: + // Local KIO + void slotLocalCanResume( KIO::Job* job, KIO::filesize_t size ); + void slotLocalGotResult( KIO::Job* job ); + void slotLocalReady( KIO::Job* job ); + void slotLocalWriteDone(); + void slotLocalGotWriteError( const QString& errorString ); + + // Remote DCC + void connectWithSender(); + void startReceiving(); + void connectionFailed( int errorCode ); + void readData(); + void sendAck(); + void connectionTimeout(); + void slotSocketClosed(); + + // Reverse DCC + void slotServerSocketReadyAccept(); + void slotServerSocketGotError( int errorCode ); + + protected: + void cleanUp(); + void failed(const QString& errorMessage = QString() ); + + // (startPosition == 0) means "don't resume" + void prepareLocalKio( bool overwrite, bool resume, KIO::fileoffset_t startPosition = 0 ); + void askAndPrepareLocalKio( const QString& message, int enabledActions, DccResumeDialog::ReceiveAction defaultAction, KIO::fileoffset_t startPosition = 0 ); + + /** + * This calls KIO::NetAccess::mkdir on all the subdirectories of dirURL, to + * create the given directory. Note that a url like file:/foo/bar will + * make sure both foo and bar are created. It assumes everything in the path is + * a directory. + * Note: If the directory already exists, returns true. + * + * @param dirURL A url for the directory to create. + * @return True if the directory now exists. False if there was a problem and the directory doesn't exist. + */ + bool createDirs(const KURL &dirURL) const; + + void requestResume(); + // for non-reverse DCC + void connectToSendServer(); + // for reverse DCC + bool startListeningForSender(); + + void startConnectionTimer( int sec ); + void stopConnectionTimer(); + + protected: + KURL m_saveToTmpFileURL; + ///Current filesize of the file saved on the disk. + KIO::filesize_t m_saveToFileSize; + ///Current filesize of the file+".part" saved on the disk. + KIO::filesize_t m_partialFileSize; + DccTransferRecvWriteCacheHandler* m_writeCacheHandler; + bool m_saveToFileExists; + bool m_partialFileExists; + QTimer* m_connectionTimer; + + KNetwork::KServerSocket* m_serverSocket; + KNetwork::KStreamSocket* m_recvSocket; + + private: + virtual QString getTypeText() const; + virtual QPixmap getTypeIcon() const; +}; + +class DccTransferRecvWriteCacheHandler : public QObject +{ + Q_OBJECT + + public: + explicit DccTransferRecvWriteCacheHandler( KIO::TransferJob* transferJob ); + virtual ~DccTransferRecvWriteCacheHandler(); + + void append( char* data, int size ); + bool write( bool force ); + void close(); + void closeNow(); + + signals: + void dataFinished(); // -> m_transferJob->slotFinished() + void done(); // -> DccTransferRecv::writeDone() + // -> DccTransferRecv::slotWriteError() + void gotError( const QString& errorString ); + + protected slots: + // <- m_transferJob->dataReq() + void slotKIODataReq( KIO::Job* job, QByteArray& data ); + void slotKIOResult( KIO::Job* job ); // <- m_transferJob->result() + + protected: + KIO::TransferJob* m_transferJob; + bool m_writeAsyncMode; + bool m_writeReady; + + QValueList m_cacheList; + QDataStream* m_cacheStream; +}; + +#endif // DCCTRANSFERRECV_H diff --git a/konversation/src/dcctransfersend.cpp b/konversation/src/dcctransfersend.cpp new file mode 100644 index 0000000..09fc42c --- /dev/null +++ b/konversation/src/dcctransfersend.cpp @@ -0,0 +1,509 @@ +/* + send a file on DCC protocol + begin: Mit Aug 7 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ +// Copyright (C) 2004-2007 Shintaro Matsuoka +// Copyright (C) 2004,2005 John Tapsell + +/* + 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. +*/ + +#include "dcctransfersend.h" +#include "channel.h" +#include "dcccommon.h" +#include "dcctransfermanager.h" +#include "konversationapplication.h" +#include "connectionmanager.h" +#include "server.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// TODO: remove the dependence +#include + + +using namespace KNetwork; + +DccTransferSend::DccTransferSend(QObject* parent) + : DccTransfer( DccTransfer::Send, parent ) +{ + kdDebug() << "DccTransferSend::DccTransferSend()" << endl; + + m_serverSocket = 0; + m_sendSocket = 0; + + m_connectionTimer = new QTimer( this ); + connect( m_connectionTimer, SIGNAL( timeout() ), this, SLOT( slotConnectionTimeout() ) ); + + // set defualt values + m_reverse = Preferences::dccPassiveSend(); +} + +DccTransferSend::~DccTransferSend() +{ + cleanUp(); +} + +void DccTransferSend::cleanUp() +{ + kdDebug() << "DccTransferSend::cleanUp()" << endl; + stopConnectionTimer(); + finishTransferLogger(); + if ( !m_tmpFile.isEmpty() ) + KIO::NetAccess::removeTempFile( m_tmpFile ); + m_tmpFile = QString(); + m_file.close(); + if ( m_sendSocket ) + { + m_sendSocket->close(); + m_sendSocket = 0; // the instance will be deleted automatically by its parent + } + if ( m_serverSocket ) + { + m_serverSocket->close(); + m_serverSocket = 0; // the instance will be deleted automatically by its parent + } +} + +// just for convenience +void DccTransferSend::failed( const QString& errorMessage ) +{ + setStatus( Failed, errorMessage ); + cleanUp(); + emit done( this ); +} + +void DccTransferSend::setFileURL( const KURL& url ) +{ + if ( getStatus() == Configuring ) + m_fileURL = url; +} + +void DccTransferSend::setFileName( const QString& fileName ) +{ + if ( getStatus() == Configuring ) + m_fileName = fileName; +} + +void DccTransferSend::setOwnIp( const QString& ownIp ) +{ + if ( getStatus() == Configuring ) + m_ownIp = ownIp; +} + +void DccTransferSend::setFileSize( KIO::filesize_t fileSize ) +{ + if ( getStatus() == Configuring ) + m_fileSize = fileSize; +} + +void DccTransferSend::setReverse( bool reverse ) +{ + if ( getStatus() == Configuring ) + m_reverse = reverse; +} + +bool DccTransferSend::queue() +{ + kdDebug() << "DccTransferSend::queue()" << endl; + + if ( getStatus() != Configuring ) + return false; + + if ( m_ownIp.isEmpty() ) + m_ownIp = DccCommon::getOwnIp( KonversationApplication::instance()->getConnectionManager()->getServerByConnectionId( m_connectionId ) ); + + if ( !kapp->authorize( "allow_downloading" ) ) + { + //Do not have the rights to send the file. Shouldn't have gotten this far anyway + //Note this is after the initialisation so the view looks correct still + failed(i18n("The admin has restricted the right to send files")); + return false; + } + + if ( m_fileName.isEmpty() ) + m_fileName = sanitizeFileName( m_fileURL.fileName() ); + + if ( Preferences::dccIPv4Fallback() ) + { + KIpAddress ip( m_ownIp ); + if ( ip.isIPv6Addr() ) + { + /* This is fucking ugly but there is no KDE way to do this yet :| -cartman */ + struct ifreq ifr; + const char* address = Preferences::dccIPv4FallbackIface().ascii(); + int sock = socket(AF_INET, SOCK_DGRAM, 0); + strncpy( ifr.ifr_name, address, IF_NAMESIZE ); + ifr.ifr_addr.sa_family = AF_INET; + if ( ioctl( sock, SIOCGIFADDR, &ifr ) >= 0 ) + m_ownIp = inet_ntoa( ( (struct sockaddr_in *)&ifr.ifr_addr )->sin_addr ); + kdDebug() << "Falling back to IPv4 address " << m_ownIp << endl; + } + } + + m_fastSend = Preferences::dccFastSend(); + kdDebug() << "DccTransferSend::DccTransferSend(): Fast DCC send: " << m_fastSend << endl; + + //Check the file exists + if ( !KIO::NetAccess::exists( m_fileURL, true, NULL ) ) + { + failed( i18n( "The url \"%1\" does not exist" ).arg( m_fileURL.prettyURL() ) ); + return false; + } + + //FIXME: KIO::NetAccess::download() is a synchronous function. we should use KIO::get() instead. + //Download the file. Does nothing if it's local (file:/) + if ( !KIO::NetAccess::download( m_fileURL, m_tmpFile, NULL ) ) + { + failed( i18n( "Could not retrieve \"%1\"" ).arg( m_fileURL.prettyURL() ) ); + kdDebug() << "DccTransferSend::DccTransferSend(): KIO::NetAccess::download() failed. reason: " << KIO::NetAccess::lastErrorString() << endl; + return false; + } + + //Some protocols, like http, maybe not return a filename, and altFileName may be empty, So prompt the user for one. + if ( m_fileName.isEmpty() ) + { + bool pressedOk; + m_fileName = KInputDialog::getText( i18n( "Enter Filename" ), i18n( "The file that you are sending to %1 does not have a filename.
Please enter a filename to be presented to the receiver, or cancel the dcc transfer
" ).arg( getPartnerNick() ), "unknown", &pressedOk, NULL ); + + if ( !pressedOk ) + { + failed( i18n( "No filename was given" ) ); + return false; + } + } + + //FIXME: if "\\\"" works well on other IRC clients, replace "\"" with "\\\"" + m_fileName.replace( "\"", "_" ); + if (Preferences::dccSpaceToUnderscore()) + m_fileName.replace( " ", "_" ); + else { + if (m_fileName.contains(" ") > 0) + m_fileName = "\"" + m_fileName + "\""; + } + + m_file.setName( m_tmpFile ); + + if ( m_fileSize == 0 ) + m_fileSize = m_file.size(); + + return DccTransfer::queue(); +} + +void DccTransferSend::abort() // public slot +{ + kdDebug() << "DccTransferSend::abort()" << endl; + + setStatus( Aborted ); + cleanUp(); + emit done( this ); +} + +void DccTransferSend::start() // public slot +{ + kdDebug() << "DccTransferSend::start()" << endl; + + if ( getStatus() != Queued ) + return; + + // common procedure + + Server* server = KonversationApplication::instance()->getConnectionManager()->getServerByConnectionId( m_connectionId ); + if ( !server ) + { + kdDebug() << "DccTransferSend::start(): could not retrieve the instance of Server. Connection id: " << m_connectionId << endl; + failed( i18n( "Could not send a DCC SEND request to the partner via the IRC server." ) ); + return; + } + + if ( !m_reverse ) + { + // Normal DCC SEND + kdDebug() << "DccTransferSend::start(): normal DCC SEND" << endl; + + // Set up server socket + QString failedReason; + if ( Preferences::dccSpecificSendPorts() ) + m_serverSocket = DccCommon::createServerSocketAndListen( this, &failedReason, Preferences::dccSendPortsFirst(), Preferences::dccSendPortsLast() ); + else + m_serverSocket = DccCommon::createServerSocketAndListen( this, &failedReason ); + if ( !m_serverSocket ) + { + failed( failedReason ); + return; + } + + connect( m_serverSocket, SIGNAL( readyAccept() ), this, SLOT( acceptClient() ) ); + connect( m_serverSocket, SIGNAL( gotError( int ) ), this, SLOT( slotGotSocketError( int ) ) ); + connect( m_serverSocket, SIGNAL( closed() ), this, SLOT( slotServerSocketClosed() ) ); + + // Get own port number + m_ownPort = QString::number( DccCommon::getServerSocketPort( m_serverSocket ) ); + + kdDebug() << "DccTransferSend::start(): own Address=" << m_ownIp << ":" << m_ownPort << endl; + + startConnectionTimer( Preferences::dccSendTimeout() ); + + server->dccSendRequest( m_partnerNick, m_fileName, getNumericalIpText( m_ownIp ), m_ownPort, m_fileSize ); + } + else + { + // Passive DCC SEND + kdDebug() << "DccTransferSend::start(): passive DCC SEND" << endl; + + int tokenNumber = KonversationApplication::instance()->getDccTransferManager()->generateReverseTokenNumber(); + // TODO: should we append a letter "T" to this token? + m_reverseToken = QString::number( tokenNumber ); + + kdDebug() << "DccTransferSend::start(): passive DCC key(token): " << m_reverseToken << endl; + + server->dccPassiveSendRequest( m_partnerNick, m_fileName, getNumericalIpText( m_ownIp ), m_fileSize, m_reverseToken ); + } + + setStatus( WaitingRemote, i18n( "Waiting remote user's acceptance" ) ); +} + +void DccTransferSend::connectToReceiver( const QString& partnerHost, const QString& partnerPort ) +{ + // Reverse DCC + + m_partnerIp = partnerHost; + m_partnerPort = partnerPort; + + m_sendSocket = new KNetwork::KStreamSocket( partnerHost, partnerPort, this ); + + m_sendSocket->setBlocking( false ); + + connect( m_sendSocket, SIGNAL( connected( const KResolverEntry& ) ), this, SLOT( startSending() ) ); + connect( m_sendSocket, SIGNAL( gotError( int ) ), this, SLOT( slotConnectionFailed( int ) ) ); + + setStatus( Connecting ); + + m_sendSocket->connect(); +} + // public +bool DccTransferSend::setResume( unsigned long position ) +{ + kdDebug() << "DccTransferSend::setResume(): position=" << position << endl; + + if ( getStatus() > WaitingRemote ) + return false; + + if ( position >= m_fileSize ) + return false; + + m_resumed = true; + m_transferringPosition = position; + return true; +} + +void DccTransferSend::acceptClient() // slot +{ + // Normal DCC + + kdDebug() << "DccTransferSend::acceptClient()" << endl; + + stopConnectionTimer(); + + m_sendSocket = static_cast( m_serverSocket->accept() ); + if ( !m_sendSocket ) + { + failed( i18n( "Could not accept the connection. (Socket Error)" ) ); + return; + } + + // we don't need ServerSocket anymore + m_serverSocket->close(); + + startSending(); +} + +void DccTransferSend::startSending() +{ + connect( m_sendSocket, SIGNAL( readyWrite() ), this, SLOT( writeData() ) ); + connect( m_sendSocket, SIGNAL( readyRead() ), this, SLOT( getAck() ) ); + connect( m_sendSocket, SIGNAL( closed() ), this, SLOT( slotSendSocketClosed() ) ); + + if ( m_sendSocket->peerAddress().asInet().ipAddress().isV4Mapped() ) + m_partnerIp = KNetwork::KIpAddress( m_sendSocket->peerAddress().asInet().ipAddress().IPv4Addr() ).toString(); + else + m_partnerIp = m_sendSocket->peerAddress().asInet().ipAddress().toString(); + m_partnerPort = m_sendSocket->peerAddress().serviceName(); + + if ( m_file.open( IO_ReadOnly ) ) + { + // seek to file position to make resume work + m_file.at( m_transferringPosition ); + m_transferStartPosition = m_transferringPosition; + + setStatus( Transferring ); + m_sendSocket->enableWrite( true ); + m_sendSocket->enableRead( m_fastSend ); + startTransferLogger(); // initialize CPS counter, ETA counter, etc... + } + else + failed( i18n( "Could not open the file: %1" ).arg( getQFileErrorString( m_file.status() ) ) ); +} + +void DccTransferSend::writeData() // slot +{ + //kdDebug() << "DccTransferSend::writeData()" << endl; + if ( !m_fastSend ) + { + m_sendSocket->enableWrite( false ); + m_sendSocket->enableRead( true ); + } + int actual = m_file.readBlock( m_buffer, m_bufferSize ); + if ( actual > 0 ) + { + m_sendSocket->writeBlock( m_buffer, actual ); + m_transferringPosition += actual; + if ( (KIO::fileoffset_t)m_fileSize <= m_transferringPosition ) + { + Q_ASSERT( (KIO::fileoffset_t)m_fileSize == m_transferringPosition ); + kdDebug() << "DccTransferSend::writeData(): Done." << endl; + m_sendSocket->enableWrite( false ); // there is no need to call this function anymore + } + } +} + +void DccTransferSend::getAck() // slot +{ + //kdDebug() << "DccTransferSend::getAck()" << endl; + if ( !m_fastSend && m_transferringPosition < (KIO::fileoffset_t)m_fileSize ) + { + m_sendSocket->enableWrite( true ); + m_sendSocket->enableRead( false ); + } + unsigned long pos; + while ( m_sendSocket->bytesAvailable() >= 4 ) + { + m_sendSocket->readBlock( (char*)&pos, 4 ); + pos = intel( pos ); + if ( pos == m_fileSize ) + { + kdDebug() << "DccTransferSend::getAck(): Received final ACK." << endl; + finishTransferLogger(); + setStatus( Done ); + cleanUp(); + emit done( this ); + break; // for safe + } + } +} + +void DccTransferSend::slotGotSocketError( int errorCode ) +{ + kdDebug() << "DccTransferSend::slotGotSocketError(): code = " << errorCode << " string = " << m_serverSocket->errorString() << endl; + failed( i18n( "Socket error: %1" ).arg( m_serverSocket->errorString() ) ); +} + +void DccTransferSend::startConnectionTimer( int sec ) +{ + kdDebug() << "DccTransferSend::startConnectionTimer()"<< endl; + stopConnectionTimer(); + m_connectionTimer->start( sec*1000, true ); +} + +void DccTransferSend::stopConnectionTimer() +{ + if ( m_connectionTimer->isActive() ) + { + kdDebug() << "DccTransferSend::stopConnectionTimer(): stop" << endl; + m_connectionTimer->stop(); + } +} + +void DccTransferSend::slotConnectionTimeout() // slot +{ + kdDebug() << "DccTransferSend::slotConnectionTimeout()" << endl; + failed( i18n( "Timed out" ) ); +} + +void DccTransferSend::slotConnectionFailed( int /* errorCode */ ) +{ + failed( i18n( "Connection failure: %1" ).arg( m_sendSocket->errorString() ) ); +} + +void DccTransferSend::slotServerSocketClosed() +{ + kdDebug() << "DccTransferSend::slotServerSocketClosed()" << endl; +} + +void DccTransferSend::slotSendSocketClosed() +{ + kdDebug() << "DccTransferSend::slotSendSocketClosed()" << endl; + finishTransferLogger(); + if ( getStatus() == Transferring && m_transferringPosition < (KIO::fileoffset_t)m_fileSize ) + failed( i18n( "Remote user disconnected" ) ); +} + + // protected, static +QString DccTransferSend::getQFileErrorString( int code ) +{ + QString errorString; + + switch(code) + { + case IO_Ok: + errorString=i18n("The operation was successful. Should never happen in an error dialog."); + break; + case IO_ReadError: + errorString=i18n("Could not read from file \"%1\".").arg( m_fileName ); + break; + case IO_WriteError: + errorString=i18n("Could not write to file \"%1\".").arg( m_fileName ); + break; + case IO_FatalError: + errorString=i18n("A fatal unrecoverable error occurred."); + break; + case IO_OpenError: + errorString=i18n("Could not open file \"%1\".").arg( m_fileName ); + break; + + // Same case value? Damn! + // case IO_ConnectError: + // errorString="Could not connect to the device."; + // break; + + case IO_AbortError: + errorString=i18n("The operation was unexpectedly aborted."); + break; + case IO_TimeOutError: + errorString=i18n("The operation timed out."); + break; + case IO_UnspecifiedError: + errorString=i18n("An unspecified error happened on close."); + break; + default: + errorString=i18n("Unknown error. Code %1").arg(code); + break; + } + + return errorString; +} + +#include "dcctransfersend.moc" diff --git a/konversation/src/dcctransfersend.h b/konversation/src/dcctransfersend.h new file mode 100644 index 0000000..dfe6ad6 --- /dev/null +++ b/konversation/src/dcctransfersend.h @@ -0,0 +1,98 @@ +/* + send a file on DCC protocol + begin: Mit Aug 7 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ +// Copyright (C) 2004-2007 Shintaro Matsuoka +// Copyright (C) 2004,2005 John Tapsell + +/* + 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. +*/ + +#ifndef DCCTRANSFERSEND_H +#define DCCTRANSFERSEND_H + +#include "dcctransfer.h" + +#include + + +class QTimer; + +namespace KNetwork +{ + class KServerSocket; + class KStreamSocket; +} + +class DccTransferSend : public DccTransfer +{ + Q_OBJECT + + public: + DccTransferSend(QObject* parent); + virtual ~DccTransferSend(); + + // REQUIRED + void setFileURL( const KURL& url ); + // OPTIONAL + void setFileName( const QString& fileName ); + // REQUIED + // FIXME: this setting should be an optional one or be removed: make DccTransferSend itself read the configuration + void setOwnIp( const QString& ownIp ); + // OPTIONAL + void setFileSize( KIO::filesize_t fileSize ); + // OPTIONAL + void setReverse( bool reverse ); + + bool setResume( unsigned long position ); + + public slots: + virtual bool queue(); + virtual void start(); + virtual void abort(); + + // invoked when the receiver accepts the offer (Reverse DCC) + void connectToReceiver( const QString& partnerHost, const QString& partnerPort ); + + protected slots: + void acceptClient(); + // it must be invoked when m_sendSocket is ready + void startSending(); + void writeData(); + void getAck(); + void slotGotSocketError( int errorCode ); + void slotConnectionTimeout(); + void slotConnectionFailed( int errorCode ); + void slotSendSocketClosed(); + void slotServerSocketClosed(); + + protected: + void cleanUp(); + void failed(const QString& errorMessage = QString() ); + + void startConnectionTimer( int sec ); + void stopConnectionTimer(); + + QString getQFileErrorString( int code ); + + QFile m_file; + + /*The filename of the temporary file that we downloaded. So if send a file ftp://somewhere/file.txt + * Then this will be downloaded to /tmp. + */ + QString m_tmpFile; + + KNetwork::KServerSocket* m_serverSocket; + KNetwork::KStreamSocket* m_sendSocket; + bool m_fastSend; + + QTimer* m_connectionTimer; +}; + +#endif // DCCTRANSFERSEND_H diff --git a/konversation/src/decoder.h b/konversation/src/decoder.h new file mode 100644 index 0000000..578dddb --- /dev/null +++ b/konversation/src/decoder.h @@ -0,0 +1,113 @@ +/* + This file is part of the KDE libraries + + Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef KHTMLDECODER_H +#define KHTMLDECODER_H + +#include + +class QTextCodec; +class QTextDecoder; + +class JapaneseCode; + +/** + * @internal + */ +class Decoder +{ +public: + enum EncodingType { + DefaultEncoding, + AutoDetectedEncoding, + EncodingFromXMLHeader, + EncodingFromMetaTag, + EncodingFromHTTPHeader, + UserChosenEncoding + }; + + Decoder(); + ~Decoder(); + + void setEncoding(const char *encoding, EncodingType type); + const char *encoding() const; + + QString decode(const char *data, int len); + + bool visuallyOrdered() const { return visualRTL; } + + const QTextCodec *codec() const { return m_codec; } + + QString flush() const; + + + enum AutoDetectLanguage { + SemiautomaticDetection, + Arabic, + Baltic, + CentralEuropean, + Chinese, + Greek, + Hebrew, + Japanese, + Korean, + Russian, + Thai, + Turkish, + Ukrainian, + Unicode, + WesternEuropean + }; + + void setAutoDetectLanguage( AutoDetectLanguage _language ) { m_autoDetectLanguage = _language; } + AutoDetectLanguage autoDetectLanguage() { return m_autoDetectLanguage; } + + + +private: + QCString automaticDetectionForArabic( const unsigned char* str, int size ); + QCString automaticDetectionForBaltic( const unsigned char* str, int size ); + QCString automaticDetectionForCentralEuropean( const unsigned char* str, int size ); + QCString automaticDetectionForCyrillic( const unsigned char* str, int size, AutoDetectLanguage _language ); + QCString automaticDetectionForGreek( const unsigned char* str, int size ); + QCString automaticDetectionForHebrew( const unsigned char* str, int size ); + QCString automaticDetectionForJapanese( const unsigned char* str, int size ); + QCString automaticDetectionForTurkish( const unsigned char* str, int size ); + QCString automaticDetectionForWesternEuropean( const unsigned char* str, int size ); + + // codec used for decoding. default is Latin1. + QTextCodec *m_codec; + QTextDecoder *m_decoder; // only used for utf16 + QCString enc; + EncodingType m_type; + + QCString buffer; + + bool body; + bool beginning; + bool visualRTL; + + AutoDetectLanguage m_autoDetectLanguage; + + JapaneseCode *kc; +}; + +#endif diff --git a/konversation/src/editnotifydialog.cpp b/konversation/src/editnotifydialog.cpp new file mode 100644 index 0000000..fe6779c --- /dev/null +++ b/konversation/src/editnotifydialog.cpp @@ -0,0 +1,103 @@ +/* + 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. +*/ + +/* + begin: Wed Sep 1 2004 + copyright: (C) 2004 by Gary Cramblitt + email: garycramblitt@comcast.net +*/ + +#include "editnotifydialog.h" +#include "konversationapplication.h" +#include "servergroupsettings.h" + +#include +#include +#include + +#include +#include +#include +#include + + +EditNotifyDialog::EditNotifyDialog(QWidget* parent, +const QString& network, +const QString& nickname): + +KDialogBase(parent,"editnotify",true,i18n("Edit Watched Nickname"), +KDialogBase::Ok | KDialogBase::Cancel, +KDialogBase::Ok,true) + +{ + QWidget* page=new QWidget(this); + setMainWidget(page); + + QHBoxLayout* layout = new QHBoxLayout(page); + layout->setSpacing(spacingHint()); + + QLabel* networkNameLabel=new QLabel(i18n("&Network name:"),page); + QString networkNameWT = i18n( + "Pick the server network you will connect to here."); + QWhatsThis::add(networkNameLabel, networkNameWT); + m_networkNameCombo=new KComboBox(page,"notify_network_combo"); + QWhatsThis::add(m_networkNameCombo, networkNameWT); + networkNameLabel->setBuddy(m_networkNameCombo); + + QLabel* nicknameLabel=new QLabel(i18n("N&ickname:"),page); + QString nicknameWT = i18n( + "The nickname to watch for when connected to a server in the network."); + QWhatsThis::add(nicknameLabel, nicknameWT); + m_nicknameInput = new KLineEdit(nickname, page); + QWhatsThis::add(m_nicknameInput, nicknameWT); + nicknameLabel->setBuddy(m_nicknameInput); + + // Build a list of unique server network names. + // TODO: The "ServerGroupList type is a misnomer (it is actually networks), which + // should be fixed at some point. + Konversation::ServerGroupList serverNetworks = Preferences::serverGroupList(); + QStringList networkNames; + + for(Konversation::ServerGroupList::iterator it = serverNetworks.begin(); it != serverNetworks.end(); ++it) + { + QString name = (*it)->name(); + + if (!networkNames.contains(name)) + { + networkNames.append(name); + } + } + + networkNames.sort(); + // Add network names to network combobox and select the one corresponding to argument. + for (QStringList::ConstIterator it = networkNames.begin(); it != networkNames.end(); ++it) + { + m_networkNameCombo->insertItem(*it); + if(*it == network) m_networkNameCombo->setCurrentItem(m_networkNameCombo->count()-1); + } + + layout->addWidget(networkNameLabel); + layout->addWidget(m_networkNameCombo); + layout->addWidget(nicknameLabel); + layout->addWidget(m_nicknameInput); + + setButtonOK(KGuiItem(i18n("&OK"),"button_ok",i18n("Change notify information"))); + setButtonCancel(KGuiItem(i18n("&Cancel"),"button_cancel",i18n("Discards all changes made"))); +} + +EditNotifyDialog::~EditNotifyDialog() +{ +} + +void EditNotifyDialog::slotOk() +{ + emit notifyChanged(m_networkNameCombo->currentText(), + m_nicknameInput->text()); + delayedDestruct(); +} + +#include "editnotifydialog.moc" diff --git a/konversation/src/editnotifydialog.h b/konversation/src/editnotifydialog.h new file mode 100644 index 0000000..0070ac9 --- /dev/null +++ b/konversation/src/editnotifydialog.h @@ -0,0 +1,50 @@ +/* + 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. +*/ + +/* + begin: Wed Sep 1 2004 + copyright: (C) 2004 by Gary Cramblitt + email: garycramblitt@comcast.net +*/ + +#ifndef EDITNOTIFYDIALOG_H +#define EDITNOTIFYDIALOG_H + +#include + +/** + The EditNotifyDialog implements the dialog for user to add or edit a + notify. A notify consists of a server network name and a nickname. + User must pick the server network name from existing network names + in the server list. + + @author Gary Cramblitt +*/ + +class KLineEdit; +class KComboBox; + +class EditNotifyDialog : public KDialogBase +{ + Q_OBJECT + + public: + explicit EditNotifyDialog(QWidget* parent=0,const QString& network=QString(), + const QString& nickname=QString()); + ~EditNotifyDialog(); + + signals: + void notifyChanged(const QString& network, + const QString& nickname); + protected slots: + void slotOk(); + + protected: + KComboBox* m_networkNameCombo; + KLineEdit* m_nicknameInput; +}; +#endif diff --git a/konversation/src/emoticon.cpp b/konversation/src/emoticon.cpp new file mode 100644 index 0000000..e193e39 --- /dev/null +++ b/konversation/src/emoticon.cpp @@ -0,0 +1,209 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 Peter Simonsson +*/ + +#include "emoticon.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include "konversationapplication.h" +#include "config/preferences.h" + + +namespace Konversation +{ + + EmotIcon* EmotIcon::s_self = 0; + static KStaticDeleter staticEmotIconDeleter; + + EmotIcon* EmotIcon::self() + { + if(!s_self) + { + staticEmotIconDeleter.setObject(s_self, new EmotIcon()); + } + + return s_self; + } + + EmotIcon::EmotIcon() + { + s_self = this; + + if(Preferences::enableEmotIcons()) + { + changeTheme(Preferences::emotIconTheme()); + } + } + + EmotIcon::~EmotIcon() + { + if(s_self == this) + { + staticEmotIconDeleter.setObject(s_self, 0, false); + } + } + + void EmotIcon::changeTheme(const QString& themeName) + { + if(themeName.isEmpty() || themeName == self()->m_themeName) + { + return; + } + + #if KDE_IS_VERSION(3,3,91) + QString filename = KGlobal::dirs()->findResource("emoticons", themeName + "/emoticons.xml"); + self()->m_themeName = themeName; + #else + QString app = "konversation"; + QString filename = KGlobal::dirs()->findResource("data", app + "/pics/emoticons/" + themeName + "/emoticons.xml"); + + if(filename.isEmpty()) + { + app = "kopete"; + filename = KGlobal::dirs()->findResource("data", app + "/pics/emoticons/" + themeName + "/emoticons.xml"); + } + self()->m_themeName = app + '/' + themeName; + #endif + + if(filename.isEmpty()) + { + return; + } + + QFile file(filename); + file.open(IO_ReadOnly); + QDomDocument doc; + doc.setContent(&file); + + QDomElement docElement = doc.documentElement(); + + if(docElement.tagName() != "messaging-emoticon-map") + { + return; + } + + self()->m_emotIconMap.clear(); + + QDomNode node = docElement.firstChild(); + QDomElement element; + QDomNode stringNode; + QDomElement stringElement; + QString fileAttrib; + QString regExpStr; + + while(!node.isNull()) + { + element = node.toElement(); + + if(!element.isNull() && element.tagName() == "emoticon") + { + fileAttrib = findIcon(element.attribute("file", QString())); + regExpStr = ""; + stringNode = element.firstChild(); + + while(!stringNode.isNull()) + { + stringElement = stringNode.toElement(); + + if(!stringElement.isNull() && stringElement.tagName() == "string") + { + if(regExpStr.isEmpty()) + { + regExpStr = "("; + } + else + { + regExpStr += '|'; + } + + regExpStr += QRegExp::escape(stringElement.text()); + } + + stringNode = stringNode.nextSibling(); + } + + if(!regExpStr.isEmpty() && !fileAttrib.isEmpty()) + { + regExpStr += ')'; + self()->m_emotIconMap[fileAttrib] = regExpStr; + } + } + + node = node.nextSibling(); + } + } + + QString EmotIcon::filter(const QString& txt, const QFontMetrics& fm) + { + if(!Preferences::enableEmotIcons()) + { + return txt; + } + + QString filteredTxt = txt; + + for(EmotIconMap::iterator it = self()->m_emotIconMap.begin(); it != self()->m_emotIconMap.end(); ++it) + { + QRegExp regExp(QString("(^|\\s)%1($|\\s)").arg(it.data())); + filteredTxt.replace(regExp, " \"" "); + } + + return filteredTxt; + } + + QString EmotIcon::findIcon(const QString& filename) + { + // + // This code was copied from void KopeteEmoticons::addIfPossible( const QString& filename, QStringList emoticons ) + // Copyright (c) 2002 by Stefan Gehn + // Copyright (c) 2002 by Olivier Goffart + // + KStandardDirs *dirs = KGlobal::dirs(); + QString pic; + + #if KDE_IS_VERSION(3,3,91) + QString file = self()->m_themeName + '/' + filename; + const char* resource = "emoticons"; + #else + QString app = self()->m_themeName.section('/', 0, 0); + QString dir = self()->m_themeName.section('/', 1); + QString file = app + "/pics/emoticons/" + dir + '/' + filename; + const char* resource = "data"; + #endif + + //maybe an extension was given, so try to find the exact file + pic = dirs->findResource(resource, file); + + if(pic.isEmpty()) + { + pic = dirs->findResource(resource, file + ".mng"); + } + if(pic.isEmpty()) + { + pic = dirs->findResource(resource, file + ".png"); + } + if(pic.isEmpty()) + { + pic = dirs->findResource(resource, file + ".gif"); + } + + return pic; + } + +} diff --git a/konversation/src/emoticon.h b/konversation/src/emoticon.h new file mode 100644 index 0000000..824a25a --- /dev/null +++ b/konversation/src/emoticon.h @@ -0,0 +1,47 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 Peter Simonsson +*/ + +#ifndef KONVERSATIONEMOTICON_H +#define KONVERSATIONEMOTICON_H + +#include +#include + + +class QFontMetrics; + +namespace Konversation +{ + + typedef QMap EmotIconMap; + + class EmotIcon + { + public: + ~EmotIcon(); + static EmotIcon* self(); + + static void changeTheme(const QString& themeName); + static QString filter(const QString& txt, const QFontMetrics& fm); + + protected: + EmotIcon(); + static EmotIcon* s_self; + + static QString findIcon(const QString& filename); + + private: + QString m_themeName; + EmotIconMap m_emotIconMap; + }; + +} +#endif diff --git a/konversation/src/eventsrc b/konversation/src/eventsrc new file mode 100644 index 0000000..5fd65ad --- /dev/null +++ b/konversation/src/eventsrc @@ -0,0 +1,973 @@ +[!Global!] +IconName=konversation +Comment=Konversation +Comment[hi]=कनवर्सेसन +Comment[pa]=ਕੇ-ਗੱਲਬਾਤ +Comment[ta]=உரையாடல் +Comment[xx]=xxKonversationxx + +[message] +Name=New message +Name[ar]=رسالة جديدة +Name[bg]=Ново съобщение +Name[br]=Kemennad nevez +Name[bs]=Nova poruka +Name[ca]=Nou missatge +Name[cs]=Nová zpráva +Name[da]=Ny besked +Name[de]=Neue Nachricht +Name[el]=Νέο μήνυμα +Name[es]=Nuevo mensaje +Name[et]=Uus sõnum +Name[fi]=Uusi viesti +Name[fr]=Nouveau message +Name[ga]=Teachtaireacht nua +Name[gl]=Nova mensaxe +Name[he]=הודעה חדשה +Name[hi]=नया संदेश +Name[hu]=Új üzenet +Name[it]=Nuovo messaggio +Name[ja]=新規メッセージ +Name[ka]=ახალი შეტყობინება +Name[lt]=Nauja žinutė +Name[nl]=Nieuw bericht +Name[pa]=ਨਵਾਂ ਸੁਨੇਹਾ +Name[pt]=Nova mensagem +Name[pt_BR]=Nova mensagem +Name[ru]=Новое сообщение +Name[sr]=Нова порука +Name[sr@Latn]=Nova poruka +Name[sv]=Nytt meddelande +Name[ta]=புதியச் செய்தி +Name[tr]=Yeni ileti +Name[uk]=Нове повідомлення +Name[uz]=Yangi xabar +Name[uz@cyrillic]=Янги хабар +Name[xx]=xxNew messagexx +Name[zh_CN]=新消息 +Name[zh_TW]=新的訊息 +Comment=New message arrived in a channel +Comment[ar]=وصلة رِسالة جديدة في قناة +Comment[bg]=Пристигна ново съобщение в канала +Comment[br]=Deuet eo ur postel nevez en ur c'hanol +Comment[bs]=Nova poruka pristigla na kanal +Comment[ca]=Ha arribat un nou missatge a un canal +Comment[cs]=Na kanálu se objevila nová zpráva +Comment[da]=Ny besked ankom i kanal +Comment[de]=Neue Nachricht in einem Kanal +Comment[el]=Νέο μήνυμα έφτασε στο κανάλι +Comment[es]=Ha llegado un nuevo mensaje a un canal +Comment[et]=Kanalile saabus uus sõnum +Comment[fi]=Kanavalle saapui uusi viesti +Comment[fr]=Un nouveau message est arrivé dans un canal +Comment[ga]=Tháinig teachtaireacht nua i gcainéal +Comment[gl]=Chegou unha mensaxe nova nun canal +Comment[he]=הודעה חדשה הגיעה לחדר +Comment[hi]=चैनल में नया संदेश आया +Comment[hu]=Új üzenet érkezett egy csatornára +Comment[it]=Nuovo messaggio arrivato in un canale +Comment[ja]=新しいメッセージがチャンネルに届きました +Comment[ka]=ახალი შეტყობინება მოვიდა არხზე +Comment[lt]=Kanale gauta nauja žinutė +Comment[nl]=Nieuw bericht gearriveerd in een kanaal +Comment[pa]=ਇੱਕ ਚੈਨਲ 'ਚ ਨਵਾਂ ਸੁਨੇਹਾ ਆਇਆ ਹੈ +Comment[pt]=Nova mensagem chegou ao canal +Comment[pt_BR]=Uma nova mensagem chegou em um canal +Comment[ru]=Получено новое сообщение на канале +Comment[sr]=Нова порука је стигла у каналу +Comment[sr@Latn]=Nova poruka je stigla u kanalu +Comment[sv]=Nytt meddelande anlände i en kanal +Comment[ta]=தடங்களிருந்து புதிய தகவல் வந்தது +Comment[tr]=Kanala yeni ileti geldi +Comment[uk]=В канал надійшло нове повідомлення +Comment[xx]=xxNew message arrived in a channelxx +Comment[zh_CN]=频道中有新消息 +Comment[zh_TW]=新訊息已送達頻道 +default_presentation=0 + +[nick] +Name=Nick written +Name[ar]=كُُتِب الأسم المستعار +Name[bg]=Написан псевдоним +Name[bs]=Nick zapisan +Name[ca]=Escriure sobrenom +Name[cs]=Zapsána přezdívka +Name[da]=Alias skrevet +Name[de]=Spitzname erwähnt +Name[el]=Το ψευδώνυμο γράφτηκε +Name[es]=Apodo escrito +Name[et]=Hüüdnimi kirjutatud +Name[fi]=Nimimerkki kirjoitettiin +Name[fr]=Pseudonyme écrit +Name[ga]=Scríobhadh do leasainm +Name[gl]=Alcume escrito +Name[he]=הכינוי נכתב +Name[hi]=निक लिखा +Name[hu]=becenév kiírva +Name[it]=Nick scritto +Name[ja]=ニックが書かれました +Name[ka]=მეტსახელი დაწერილია +Name[lt]=Paminėtas slapyvardis +Name[nl]=Bijnaam geschreven +Name[pa]=ਨਾਂ ਲਿਖਿਆ +Name[pt]=Alcunha escrita +Name[pt_BR]=Apelido escrito +Name[ru]=Упоминание вашего ника +Name[sr]=Надимак је уписан +Name[sr@Latn]=Nadimak je upisan +Name[sv]=Något skrivet till smeknamnet +Name[ta]=பட்டை எழுத்து +Name[tr]=Takma ad yazıldı +Name[uk]=Написане прізвисько +Name[xx]=xxNick writtenxx +Name[zh_CN]=昵称写入 +Name[zh_TW]=有人提到您的暱稱 +Comment=Someone wrote your nick in a message +Comment[ar]=أحد ما كتب إسمك المستعار في رسالة ما +Comment[bg]=Псевдонимът ви бе написан в съобщение +Comment[bs]=Neko je spomenuo vaš nick u poruci +Comment[ca]=Algú ha escrit el vostre sobrenom en un missatge +Comment[cs]=Někdo ve zprávě napsal vaší přezdívku +Comment[da]=Nogen skrev dit alias i en besked +Comment[de]=Jemand hat Ihren Spitznamen in einer Nachricht erwähnt +Comment[el]=Κάποιος έγραψε το ψευδώνυμο σας σε ένα μήνυμα +Comment[es]=Alguien ha escrito su apodo en un mensaje +Comment[et]=Keegi kasutas sõnumis sinu hüüdnime +Comment[fi]=Joku kirjoitti nimimerkkisi viestiin +Comment[fr]=Quelqu'un a écrit votre pseudonyme dans un message +Comment[ga]=Scríobh duine éigin do leasainm i dteachtaireacht +Comment[gl]=Alguén escrebeu o seu alcume nunha mensaxe +Comment[he]=מישהו כתב את הכינוי שלך בהודעה +Comment[hi]=संदेश मे किसी ने आपका निक लिखा +Comment[hu]=Valaki leírta az Ön becenevét az egyik csatornán +Comment[it]=Qualcuno ha scritto il tuo nick in un messaggio +Comment[ja]=誰かがあなたのニックをメッセージに書きました +Comment[ka]=ვიღაცამ შეტყობინებაში თქვენი მეტსახელი დაწერა +Comment[lt]=Kažkas paminėjo jūsų slapyvardį žinutėje +Comment[nl]=Iemand schreef uw bijnaam in een bericht +Comment[pt]=Alguém escrever a sua alcunha numa mensagem +Comment[pt_BR]=Alguém escreveu o seu nick em uma mensagem +Comment[ru]=Кто-то написал ваше имя в своём собщении +Comment[sr]=Неко је написао ваш надимак у поруци +Comment[sr@Latn]=Neko je napisao vaš nadimak u poruci +Comment[sv]=Någon skrev ett meddelande till ditt smeknamn +Comment[ta]=உங்கள் வடுத் தகவலில் ஒரு சிலர் எழுதியுள்ளனர் +Comment[tr]=Birisi iletisinde sizin takma adınızı yazdı +Comment[uk]=Хтось в повідомленні написав ваше прізвисько +Comment[xx]=xxSomeone wrote your nick in a messagexx +Comment[zh_CN]=有人在消息中输入了你的昵称 +Comment[zh_TW]=有人在訊息中提到您的暱稱 +default_presentation=0 + +[queryMessage] +Name=Private message +Name[bg]=Лично съобщение +Name[cs]=Soukromá zpráva +Name[da]=Provat besked +Name[de]=Private Nachricht +Name[el]=Προσωπικό μήνυμα +Name[es]=Mensaje privado +Name[et]=Privaatsõnum +Name[ga]=Teachtaireacht phríobháideach +Name[it]=Messaggio privato +Name[ja]=プライベートメッセージ +Name[nl]=Privaat bericht +Name[pa]=ਪ੍ਰਾਈਵੇਟ ਸੁਨੇਹਾ +Name[pt]=Mensagem privada +Name[pt_BR]=Mensagem particular +Name[sr]=Приватна порука +Name[sr@Latn]=Privatna poruka +Name[sv]=Privat meddelande +Name[tr]=Özel ileti +Name[uk]=Приватне повідомлення +Name[xx]=xxPrivate messagexx +Name[zh_CN]=私人消息 +Name[zh_TW]=私密訊息 +Comment=You received a private message +Comment[bg]=Получихте лично съобщение +Comment[cs]=Obdrželi jste soukromou zprávu +Comment[da]=Du modtog en privat besked +Comment[de]=Sie haben eine private Nachricht erhalten +Comment[el]=Λάβατε ένα προσωπικό μήνυμα +Comment[es]=Ha recibido un mensaje privado +Comment[et]=Sa said privaatsõnumi +Comment[ga]=Fuair tú teachtaireacht phríobháideach +Comment[it]=Hai ricevuto un messaggio privato +Comment[ja]=プライベートメッセージを受け取りました +Comment[nl]=U ontving een privaat bericht +Comment[pt]=Você recebeu uma mensagem privada +Comment[pt_BR]=Você recebeu uma mensagem particular +Comment[sr]=Примили сте приватну поруку +Comment[sr@Latn]=Primili ste privatnu poruku +Comment[sv]=Du har tagit emot ett privat meddelande +Comment[tr]=Bir özel ileti aldınız +Comment[uk]=Ви отримали приватне повідомлення +Comment[xx]=xxYou received a private messagexx +Comment[zh_CN]=您收到了私人消息 +Comment[zh_TW]=您接收到一個私密訊息 +default_presentation=0 + +[nickchange] +Name=Nick changed +Name[ar]=تغيّر الإسم المستعار +Name[bg]=Псевдонимът е променен +Name[bs]=Nick promijenjen +Name[ca]=Sobrenom canviat +Name[cs]=Přezdívka změněna +Name[da]=Alias ændret +Name[de]=Spitzname geändert +Name[el]=Το ψευδώνυμο άλλαξε +Name[es]=Apodo modificado +Name[et]=Hüüdnimi muudetud +Name[fi]=Nimimerkki muuttui +Name[fr]=Pseudonyme modifié +Name[ga]=Athraíodh leasainm +Name[gl]=Alcume trocado +Name[he]=הכינוי שונה +Name[hi]=निक बदला +Name[hu]=Becenév módosítva +Name[it]=Nick cambiato +Name[ja]=ニック変更 +Name[ka]=მეტსახელი შეიცვალა +Name[lt]=Slapyvardis pakeistas +Name[nl]=Bijnaam gewijzigd +Name[pa]=Nick ਬਦਲਿਆ +Name[pt]=Alcunha alterada +Name[pt_BR]=Apelido modificado +Name[ru]=Изменён ник +Name[sr]=Надимак је промењен +Name[sr@Latn]=Nadimak je promenjen +Name[sv]=Smeknamn ändrat +Name[ta]= மாற்றியப் பட்டை +Name[tr]=Takma ad değişti +Name[uk]=Змінене прізвисько +Name[xx]=xxNick changedxx +Name[zh_CN]=昵称改变 +Name[zh_TW]=變更暱稱 +Comment=Someone changed their nick +Comment[ar]=أحد ما غيّر إسمه المستعار +Comment[bg]=Някой си промени псевдонима +Comment[bs]=Neko je promijenio svoj nick +Comment[ca]=Algú ha canviat el seu sobrenom +Comment[cs]=Někdo změnil svou přezdívku +Comment[da]=Nogen ændrede deres alias +Comment[de]=Jemand hat seinen Spitznamen geändert +Comment[el]=Κάποιος άλλαξε το ψευδώνυμο του +Comment[es]=Alguien ha cambiado su apodo +Comment[et]=Keegi muutis oma hüüdnime +Comment[fi]=Joku muutti nimimerkkiään +Comment[fr]=Quelqu'un a changé de pseudonyme +Comment[ga]=D'athraigh duine éigin a leasainm +Comment[gl]=Alguén trocou de alcume +Comment[he]=מישהו שינה את הכינוי שלו +Comment[hi]=किसी ने अपना निक बदला +Comment[hu]=Valaki megváltoztatta a becenevét +Comment[it]=Qualcuno ha cambiato il proprio nick +Comment[ja]=誰かがニックを変更しました +Comment[ka]=ვიღაცამ მეტსახელი შეიცვალა +Comment[lt]=Kažkas pasikeitė savo slapyvardį +Comment[nl]=Iemand veranderde zijn of haar bijnaam +Comment[pt]=Alguém mudou a sua alcunha +Comment[pt_BR]=Alguém mudou o seu apelido +Comment[ru]=Кто-то сменил своё имя +Comment[sr]=Неко је променио свој надимак +Comment[sr@Latn]=Neko je promenio svoj nadimak +Comment[sv]=Någon ändrade sitt smeknamn +Comment[ta]=வடுவை ஒரு சிலர் மாற்றினர் +Comment[tr]=Birileri takma adlarını değiştirdi +Comment[uk]=Хтось змінив своє прізвисько +Comment[xx]=xxSomeone changed their nickxx +Comment[zh_CN]=有人改变了昵称 +Comment[zh_TW]=有人變更了暱稱 +default_presentation=0 + +[dcc_incoming] +Name=Incoming file +Name[ar]=ملف وارِد +Name[bg]=Пристигащ файл +Name[br]=Restr resev +Name[bs]=Dolazeća datoteka +Name[ca]=Fitxer entrant +Name[cs]=Příchozí soubor +Name[da]=Indkommende fil +Name[de]=Datei angeboten +Name[el]=Εισερχόμενο αρχείο +Name[es]=Fichero entrante +Name[et]=Sisenev fail +Name[fi]=Saapuva tiedosto +Name[fr]=Fichier entrant +Name[ga]=Comhad isteach +Name[gl]=Ficheiro recebido +Name[he]=קובץ נכנס +Name[hi]=आनेवाली फाइल +Name[hu]=Bejövő fájl +Name[it]=File in arrivo +Name[ja]=受信ファイル +Name[ka]=შემომავალი ფაილი +Name[lt]=Atsiunčiama byla +Name[nl]=Bestand aangeboden +Name[pa]=ਆ ਰਹੀ ਫਾਇਲ +Name[pt]=Ficheiro recebido +Name[pt_BR]=Arquivo de entrada +Name[ru]=Входящий файл +Name[sr]=Долазећи фајл +Name[sr@Latn]=Dolazeći fajl +Name[sv]=Inkommande fil +Name[ta]=உள்ளீடு கோப்பு +Name[tr]=Gelen dosya +Name[uk]=Вхідний файл +Name[xx]=xxIncoming filexx +Name[zh_CN]=收到的文件 +Name[zh_TW]=送來檔案 +Comment=Someone wants to transmit a file to you over DCC +Comment[ar]=أحد ما يريد إرسال ملف إليك عبر DCC +Comment[bg]=Някой иска да ви изпрати файл чрез DCC +Comment[bs]=Neko želi da vam pošalje datoteku koristeći DCC +Comment[ca]=Algú desitja enviar-vos un fitxer sobre DCC +Comment[cs]=Někdo vám chce přes DCC poslat soubor +Comment[da]=Nogen ønsker at transmittere en fil til dig over DCC +Comment[de]=Jemand bietet Ihnen eine Datei zum DCC-Download an +Comment[el]=Κάποιος θέλει να σας στείλει ένα αρχείο μέσω DCC +Comment[es]=Alguien quiere transmitirle un fichero a través de DCC +Comment[et]=Keegi tahab sulle faili edastada üle DCC +Comment[fi]=Joku haluaa lähettää DCC-tiedoston sinulle +Comment[fr]=Quelqu'un souhaite vous transmettre un fichier via DCC +Comment[gl]=Alguén quer transmitir-lle un ficheiro por DCC +Comment[he]=משיהו רוצה לשלוח לך קובץ דרך DCC +Comment[hi]=कोई एक फाइल आपके डीसीसी पर ट्रांसमिट करना चाहता है +Comment[hu]=Valaki fájl szeretne küldeni Önnek DCC-n keresztül +Comment[it]=Qualcuno vuole trasmetterti un file via DCC +Comment[ja]=誰かが DCC であなたにファイルを転送したいそうです +Comment[ka]=ვიღაცას სურს DCC-ს მეშვეობით გადმოგცეთ ფაილი +Comment[lt]=Kažkas nori jums atsiųsti bylą per DCC +Comment[nl]=Iemand wil via DCC een bestand naar u sturen +Comment[pt]=Alguém quer transmitir um ficheiro através de DCC +Comment[pt_BR]=Alguém deseja transmitir um arquivo para você via DCC +Comment[ru]=Кто-то хочет передать вам файл +Comment[sr]=Неко жели да вам пошаље фајл преко DCC-а +Comment[sr@Latn]=Neko želi da vam pošalje fajl preko DCC-a +Comment[sv]=Någon vill skicka en fil till dig via direktkommunikation +Comment[ta]= ஒரு சிலர் உங்களுக்குக் கோப்பினை வழங்க DCCலிருந்து விரும்புகின்றனர் +Comment[tr]=Birisi size DCC üzerinden dosya göndermek istiyor +Comment[uk]=Хтось хоче надіслати вам файл через DCC +Comment[xx]=xxSomeone wants to transmit a file to you over DCCxx +Comment[zh_CN]=有人希望通过 DCC 向你传输文件 +Comment[zh_TW]=有人要透過 DCC 傳送檔案給您 +default_presentation=0 + +[join] +Name=Nick joined channel +Name[ar]=الإسم المستعار إنضمّ إلى القناة +Name[bg]=Псевдонимът се присъедини към канала +Name[bs]=Nick se pridružio kanalu +Name[ca]=El sobrenom ha accedit al canal +Name[cs]=Přezdívka se objevila na kanálu +Name[da]=Alias gik med i kanal +Name[de]=Benutzer betritt Kanal +Name[el]=Το ψευδώνυμο συνδέθηκε στο κανάλι +Name[es]=Apodo se ha unido al canal +Name[et]=Hüüdnimi ühines kanaliga +Name[fi]=Nimimerkki liittyi kanavalle +Name[fr]=Un pseudonyme a rejoint le canal +Name[ga]=Chuaigh leasainm le cainéal +Name[gl]=Alguén se uniu ao canal +Name[he]=כינוי התחבר אל החדר +Name[hi]=निक चैनल में शामिल हुआ +Name[hu]=Valaki belépett a csatornára +Name[it]=Nick entrato nel canale +Name[ja]=ニックがチャンネルに入りました +Name[ka]=მეტსახელი არხს შეუერთდა +Name[lt]=Slapyvardis prisijungė kanale +Name[nl]=Bijnaam neemt deel aan kanaal +Name[pa]=Nick ਚੈਨਲ 'ਚ ਦਾਖਲ +Name[pt]=Alcunha juntou-se ao canal +Name[pt_BR]=Apelido entrou no canal +Name[ru]=Пользователь вошёл на канал +Name[sr]=Надимак се прикључио каналу +Name[sr@Latn]=Nadimak se priključio kanalu +Name[sv]=Någon med smeknamnet gick med i en kanal +Name[ta]=இணைத்தத் தடப்பட்டை +Name[tr]=Takma ad kanala girdi +Name[uk]=Прізвисько приєдналось до каналу +Name[xx]=xxNick joined channelxx +Name[zh_CN]=昵称加入频道 +Name[zh_TW]=加入頻道 +Comment=New nick joined a channel +Comment[ar]=إسم مستعار جديد إنضمّ إلى القناة +Comment[bg]=Нов псевдоним се присъедини към канала +Comment[bs]=Novi nick se pridružio kanalu +Comment[ca]=Un nou sobrenom ha accedit a un canal +Comment[cs]=Na kanálu se objevila nová přezdívka +Comment[da]=Nyt alias gik med i en kanal +Comment[de]=Jemand betritt einen Kanal +Comment[el]=Νέο ψευδώνυμο συνδέθηκε σε ένα κανάλι +Comment[es]=Un nuevo usuario se ha unido a un canal +Comment[et]=Kanaliga ühines uus hüüdnimi +Comment[fi]=Uusi nimimerkki liittyi kanavalle +Comment[fr]=Un pseudonyme a rejoint le canal +Comment[ga]=Chuaigh leasainm nua le cainéal +Comment[gl]=Un alcume novo uniu-se ao canal +Comment[he]=כינוי חדש התחבר לחדר +Comment[hi]=नया निक एक चैनल में शामिल हुआ +Comment[hu]=Új felhasználó lépett be az egyik csatornára +Comment[it]=Un nuovo nick è entrato nel canale +Comment[ja]=新しいニックがチャンネルに入りました +Comment[ka]=ახალი მეტსახელი არხს შეუერთდა +Comment[lt]=Naujas slapyvardis prisijungė kanale +Comment[nl]=Nieuwe bijnaam neemt deel aan een kanaal +Comment[pt]=Um novo utilizador juntou-se ao canal +Comment[pt_BR]=Um novo apelido entrou em um canal +Comment[ru]=Новые люди на канале +Comment[sr]=Нови надимак се прикључио каналу +Comment[sr@Latn]=Novi nadimak se priključio kanalu +Comment[sv]=Någon med ett nytt smeknamn gick med i en kanal +Comment[ta]=புதிய வடுத் தடத்தில் சேர்ந்தது +Comment[tr]=Kanala yeni bir kişi girdi +Comment[uk]=Нове прізвисько приєдналось до каналу +Comment[xx]=xxNew nick joined a channelxx +Comment[zh_CN]=新昵称加入了频道 +Comment[zh_TW]=有人加入了頻道 +default_presentation=0 + +[part] +Name=Nick left channel +Name[ar]=الإسم المستعار غادر القناة +Name[bg]=Псевдонимът напусна канала +Name[bs]=Nick napustio kanal +Name[ca]=El sobrenom ha abandonat el canal +Name[cs]=Přezdívka opustila kanál +Name[da]=Alias forlod kanal +Name[de]=Benutzer verlässt Kanal +Name[el]=Το ψευδώνυμο έφυγε από το κανάλι +Name[es]=Apodo ha dejado el canal +Name[et]=Hüüdnimi lahkus kanalilt +Name[fi]=Nimimerkki poistui kanavalta +Name[fr]=Un pseudonyme a quitté le canal +Name[ga]=D'fhág leasainm cainéal +Name[gl]=Alguén deixou o canal +Name[he]=כינוי עזב את החדר +Name[hi]=निक चैनल छोड़ा +Name[hu]=Valaki kilépett a csatornáról +Name[it]=Nick uscito dal canale +Name[ja]=ニック退出 +Name[ka]=მეტსახელმა დატოვა არხი +Name[lt]=Slapyvardis atsijungė nuo kanalo +Name[nl]=Bijnaam verlaat kanaal +Name[pa]=Nick ਨੇ ਚੈਨਲ ਛੱਡਿਆ +Name[pt]=Alcunha saiu do canal +Name[pt_BR]=Apelido deixou o canal +Name[ru]=Пользователь вышел из канала +Name[sr]=Надимак је напустио канал +Name[sr@Latn]=Nadimak je napustio kanal +Name[sv]=Någon med smeknamnet lämnade en kanal +Name[ta]=இடது தடப் பட்டை +Name[tr]=Takma ad kanaldan ayrıldı +Name[uk]=Прізвисько покинуло канал +Name[xx]=xxNick left channelxx +Name[zh_CN]=昵称离开频道 +Name[zh_TW]=離開頻道 +Comment=A nick left a channel +Comment[ar]=إسم مستعار غادر القناة +Comment[bg]=Псевдонимът напусна канала +Comment[bs]=Nick je napustio kanal +Comment[ca]=Un sobrenom ha deixat un canal +Comment[cs]=Přezdívka opustila kanál +Comment[da]=Et alias forlod en kanal +Comment[de]=Jemand verlässt einen Kanal +Comment[el]=Ένα ψευδώνυμο έφυγε από ένα κανάλι +Comment[es]=Un usuario ha abandonado un canal +Comment[et]=Hüüdnimi lahkus kanalilt +Comment[fi]=Nimimerkki poistui kanavalta +Comment[fr]=Un pseudonyme a quitté le canal +Comment[ga]=D'fhág leasainm cainéal +Comment[gl]=Alguén abandonou o canal +Comment[he]=כינוי עזב את החדר +Comment[hu]=Valaki kilépett egy csatornáról +Comment[it]=Un nick è uscito dal canale +Comment[ja]=ニックがチャンネルから退出しました +Comment[ka]=მეტსახელმა დატოვა არხი +Comment[lt]=Slapyvardis atsijungė nuo kanalo +Comment[nl]=Een bijnaam heeft een kanaal verlaten +Comment[pa]=ਇੱਕ ਨਾਂ ਨੇ ਚੈਨਲ ਛੱਡਿਆ +Comment[pt]=Um utilizador abandonou o canal +Comment[pt_BR]=Alguém deixou um canal +Comment[ru]=Пользователь покинул канал +Comment[sr]=Надимак је напустио канал +Comment[sr@Latn]=Nadimak je napustio kanal +Comment[sv]=Någon med ett smeknamn lämnade en kanal +Comment[ta]=தடத்தை விட்டு வடு நீங்கியது +Comment[tr]=Bir takma ad kanaldan ayrıldı +Comment[uk]=Прізвисько покинуло канал +Comment[xx]=xxA nick left a channelxx +Comment[zh_CN]=一个昵称离开了频道 +Comment[zh_TW]=有人離開了頻道 +default_presentation=0 + +[mode] +Name=Mode change +Name[ar]=تغيير النمط +Name[bg]=Смяна на режим +Name[bs]=Promjena režima +Name[ca]=Mode canviat +Name[cs]=Změna režimu +Name[da]=Tilstand ændret +Name[de]=Moduswechsel +Name[el]=Αλλαγή κατάστασης +Name[es]=Cambio de modo +Name[et]=Režiimi muutus +Name[fi]=Tilamuutos +Name[fr]=Changement de mode +Name[ga]=Athrú móid +Name[gl]=Cámbio de modo +Name[he]=שינוי מצב +Name[hi]=मोड बदला +Name[hu]=Módváltás +Name[it]=Cambio di modalità +Name[ja]=モード変更 +Name[ka]=რეჟიმის შეცვლა +Name[lt]=Pasikeitė būsena +Name[nl]=Moduswisseling +Name[pa]=ਢੰਗ ਤਬਦੀਲ +Name[pt]=Mudança de modo +Name[pt_BR]=Mudança de modo +Name[ru]=Смена режима +Name[sr]=Режим је измењен +Name[sr@Latn]=Režim je izmenjen +Name[sv]=Tillståndsändring +Name[ta]=பாங்கை மாற்று +Name[tr]=Kip değiştir +Name[uk]=Зміна режиму +Name[xx]=xxMode changexx +Name[zh_CN]=模式改变 +Name[zh_TW]=模式變更 +Comment=A user or channel mode was changed +Comment[ar]=تغيّر مستخدِم أو قناة ما +Comment[bg]=Променен е потребителски режим или канал +Comment[bs]=Mod korisnika ili kanala je promijenjen +Comment[ca]=A mode d'usuari o de canal ha estat canviat +Comment[cs]=Uživatel nebo kanál byl změněn +Comment[da]=En bruger- eller kanaltilstand blev ændret +Comment[de]=Ein Benutzer- oder Kanal-Modus wurde geändert +Comment[el]=Η κατάσταση ενός χρήστης ή καναλιού άλλαξε +Comment[es]= Un modo de usuario o de canal ha sido modificado +Comment[et]=Kasutaja või kanalirežiim muudeti +Comment[fi]=Käyttäjän tai kanavan tila vaihtui +Comment[fr]=Un utilisateur ou un mode de canal a été changé +Comment[ga]=Athraíodh mód úsáideora nó mód cainéil +Comment[gl]=Foi modificado un modo de usuário ou canal +Comment[he]=משתמש או חדר שינה את המצב שלו +Comment[hi]=एक उपयोगकर्ता या चैनल मोड बदला +Comment[hu]=Egy felhasználó vagy egy csatornamód megváltozott +Comment[it]=Una modalità utente o canale è stata cambiata +Comment[ja]=ユーザまたはチャンネルモードが変更されました +Comment[ka]=მომხმარებლის ან არხის რეჟიმი შეიცვალა +Comment[lt]=Pasikeitė naudotojo arba kanalo būsena +Comment[nl]=Een gebruiker- of kanaalmodus is gewijzigd +Comment[pt]=O modo de um utilizador ou canal foi alterado +Comment[pt_BR]=Um usuário ou modo de canal foi modificado +Comment[ru]=Режим пользователя или канала изменены +Comment[sr]=Корисник или режим канала је промењен +Comment[sr@Latn]=Korisnik ili režim kanala je promenjen +Comment[sv]=Tillståndet för en användare eller kanal ändrades +Comment[ta]=பயனர் அல்லது தடங்கள் மாறியது +Comment[tr]=Bir kullanıcı veya kanal kipi değiştirildi +Comment[uk]=Змінено користувацький або канальний режим +Comment[xx]=xxA user or channel mode was changedxx +Comment[zh_CN]=一个用户或频道模式改变了 +Comment[zh_TW]=某位使用者或某個頻道的模式已被變更 +default_presentation=0 + +[notify] +Name=Notify +Name[ar]=بلِغ +Name[bg]=Известяване +Name[bs]=Obavijesti +Name[ca]=Notificació +Name[da]=Bekendtgør +Name[de]=Benachrichtigung +Name[el]=Ειδοποίηση +Name[es]=Notificar +Name[et]=Märguanne +Name[fi]=Ilmoitus +Name[fr]=Notification +Name[ga]=Cuir Fógra Chugam +Name[gl]=Notificar +Name[he]=הודעה +Name[hi]=नोटिफाई +Name[hu]=Értesítés +Name[it]=Notifica +Name[ja]=通知 +Name[ka]=შეტყობინება +Name[lt]=Perspėti +Name[nl]=Notificatie +Name[pa]=ਸੂਚਨਾ +Name[pt]=Notificação +Name[pt_BR]=Notificar +Name[ru]=Уведомление +Name[sr]=Обавести +Name[sr@Latn]=Obavesti +Name[sv]=Underrättelse +Name[ta]=குறிப்பு +Name[tr]=Bildirim +Name[uk]=Сповіщати +Name[xx]=xxNotifyxx +Name[zh_CN]=通告 +Name[zh_TW]=通知 +Comment=A user on your watched nicks list has come online +Comment[ar]=مستخدِم مِن أفراد لائحتك لِلأسماء المستعارة سجل دخولهُ +Comment[bg]=Потребител от списъка ви с наблюдавани псевдоними влезе в канала +Comment[ca]=S'ha connectat un usuari de la vostra llista de sobrenoms vigilats +Comment[cs]=Uživatel z vašeho seznamu je online +Comment[da]=En bruger på din liste af aliasser gik online +Comment[de]=Ein Benutzer aus Ihrer "Beobachten"-Liste ist online +Comment[el]=Ένας χρήστης από τη λίστα ψευδώνυμων παρακολούθησης συνδέθηκε στο δίκτυο +Comment[es]=Un usuario de su lista de apodos vigilados se ha conectado +Comment[et]=Jälgitavate hüüdnimede nimekirjas olev kasutaja tuli võrku +Comment[fi]=Seurattu nimimerkki tuli paikalle +Comment[fr]=Un utilisateur de votre liste de pseudos surveillés est maintenant en ligne +Comment[gl]=Un usuário da sua lista de seguimento conectou-se +Comment[he]=משתמש ברשימה תצוגה שלך נכנס לרשת +Comment[hi]=आपकी मित्र सूची का एक उपयोक्ता ऑनलाइन हुआ +Comment[hu]=Az értesítési listán szereplő egyik felhasználó online módba váltott +Comment[it]=Si è collegato un utente nella tua lista di nick sorvegliati +Comment[ja]=ニック監視リストのユーザがオンラインになりました +Comment[ka]=მომხმარებელი თქვენი სათვალყურო სიიდან ხაზზე გამოვიდა +Comment[lt]=Prisijungė naudotojas iš stebimų slapyvardžių sąrašo +Comment[nl]=Een gebruiker op uw gevolgdebijnamenlijst is online +Comment[pt]=Um utilizador da sua lista de notificações ligou-se +Comment[pt_BR]=Um usuário de sua lista de apelidos ficou online +Comment[ru]=Наблюдаемый пользователь в сети +Comment[sr]=Корисник са ваше листе праћених надимака је дошао на везу +Comment[sr@Latn]=Korisnik sa vaše liste praćenih nadimaka je došao na vezu +Comment[sv]=En användare i din lista med bevakade smeknamn har kopplat upp +Comment[ta]= உங்கள் வடுகளின் பட்டியலைப் பயனர் கண்காணித்து நிகழ்நிலையில் வருகின்றனர் +Comment[tr]=İzlenen takma adlar listenizdeki bir kullanıcı bağlandı +Comment[uk]=Вийшов у мережу користувач із вашого списку прізвиськ +Comment[xx]=xxA user on your watched nicks list has come onlinexx +Comment[zh_CN]=一名在您的监视昵称列表上的用户已经上线 +Comment[zh_TW]=您監看的暱稱清單中有某人上線了 +default_presentation=0 + +[query] +Name=Query +Name[ar]=أطلب +Name[bg]=Запитване +Name[br]=Goulenn +Name[ca]=Conversa +Name[cs]=Dotaz +Name[cy]=Ymholiad +Name[el]=Ερώτηση +Name[es]=Consulta +Name[et]=Päring +Name[fi]=Kysely +Name[fr]=Requête +Name[ga]=Iarratas +Name[gl]=Procura +Name[he]=שאילתה +Name[hi]=क्वैरी +Name[it]=Conversazione privata +Name[ja]=クエリ +Name[ka]=გამოკითხვა +Name[lt]=Pokalbis +Name[nl]=Aanvraag +Name[pa]=ਕਿਊਰੀ +Name[pt]=Procura +Name[pt_BR]=Busca +Name[ru]=Диалог +Name[sr]=Упит +Name[sr@Latn]=Upit +Name[sv]=Fråga +Name[ta]=கேள்வி +Name[tr]=Sorgu +Name[uk]=Запит +Name[xx]=xxQueryxx +Name[zh_CN]=对话 +Name[zh_TW]=查詢 +Comment=Someone started a conversation (query) with you +Comment[ar]=أحدٌ ما إبتدء مكالمة ( طلب ) معك +Comment[bg]=Някой започна личен разговор с вас +Comment[ca]=Algú ha iniciat una conversa (query) amb vostè +Comment[cs]=Někdo s vámi zahájil rozhovor (dotaz) +Comment[da]=Nogen startede en konversation (query) med dig +Comment[de]=Jemand hat ein Gespräch (query) mit Ihnen begonnen +Comment[el]=Κάποιος ξεκίνησε μια συζήτηση (ερώτηση) μαζί σας +Comment[es]=Alguien empezó una conversación (consulta) con usted +Comment[et]=Keegi alustas sinuga vestlust (esitas päringu) +Comment[fi]=Joku aloitti keskustelun (kyselyn) kanssasi +Comment[fr]=Quelqu'un a commencé une conversation (requête) avec vous +Comment[ga]=Thosaigh duine éigin comhrá (iarratas) leat +Comment[gl]=Alguén comezou una conversa (está a procurá-la) privada +Comment[he]=מישהו יזם שיחה אתך (query) +Comment[hi]=किसी ने आपके साथ वार्तालाप (क्वैरी) प्रारंभ किया +Comment[it]=Qualcuno ha avviato una conversazione privata (query) con te +Comment[ja]=誰かがあなたと会話 (クエリ) を開始しました +Comment[ka]=ვიღაცამ თქვენთან საუბარი (გამოკითხვა) დაიწყო +Comment[lt]=Kažkas pradėjo su jumis pokalbį +Comment[nl]=Iemand begon een conversatie (aanvraag) met u +Comment[pt]=Alguém iniciou uma conversa (procura) consigo +Comment[pt_BR]=Alguém começou a conversa (query) com você +Comment[ru]=Кто-то начал диалог с вами +Comment[sr]=Неко је започео разговор (упит) са вама +Comment[sr@Latn]=Neko je započeo razgovor (upit) sa vama +Comment[sv]=Någon startade en konversation med dig (ställde en fråga till dig) +Comment[ta]=ஒருவர் உங்களுடன் உரையாடலை துவக்கியிருக்கிறார் (கேள்வி) +Comment[tr]=Birisi sizinle sohbet başlattı +Comment[uk]=Хтось почав з вами розмову (запит) +Comment[xx]=xxSomeone started a conversation (query) with youxx +Comment[zh_CN]=有人向您打开了一个对话。 +Comment[zh_TW]=有人開啟了與您的私密對話 +default_presentation=0 + +[kick] +Name=Kick +Name[ar]=ركل +Name[bg]=Изритване +Name[ca]=Expulsió +Name[cs]=Vykopnutí +Name[cy]=Lluchio +Name[el]=Απομάκρυνση +Name[es]=Expulsar +Name[et]=Väljaviskamine +Name[fi]=Ulosheitto +Name[fr]=Bannir +Name[ga]=Ciceáil amach +Name[gl]=Expulsón +Name[he]=בעיטה +Name[it]=Espulsione +Name[ja]=追い出し (Kick) +Name[lt]=Išspirtas +Name[pa]=ਠੁੱਢਾ +Name[pt_BR]=Retirar +Name[sr]=Избачени +Name[sr@Latn]=Izbačeni +Name[tr]=Tekmele +Name[uk]=Виштовхнуто +Name[xx]=xxKickxx +Name[zh_CN]=踢出 +Name[zh_TW]=踢出 +Comment=Someone kicked you out of a channel +Comment[ar]=أحدٌ ما طلب ركلك خارجأً عن القناة +Comment[bg]=Някой ви изрита от канала +Comment[ca]=Algú us ha expulsat d'un canal +Comment[cs]=Někdo vás vykopnul z kanálu +Comment[da]=Nogen sparkede dig ud af kanalen +Comment[de]=Jemand hat Sie aus einem Kanal geworfen +Comment[el]=Κάποιος σας απομάκρυνε από ένα κανάλι +Comment[es]=Alguien le ha expulsado de un canal +Comment[et]=Keegi viskas su kanalilt välja +Comment[fi]=Joku heitti sinut kanavalta ulos +Comment[fr]=Quelqu'un vous a banni du canal +Comment[ga]=Chiceáil duine éigin thú amach as cainéal +Comment[gl]=Foi expulsado do canal por alguén +Comment[he]=מישהו בעט אותך מערוץ +Comment[it]=Qualcuno ti ha espulso da un canale +Comment[ja]=誰かがあなたをチャンネルから追い出しました +Comment[ka]=ვიღაცამ არხიდან გაგაპანღურათ +Comment[lt]=Kažkas jus išspyrė iš kanalo +Comment[nl]=Iemand heeft u van het kanaal gekicked +Comment[pt]=Alguém o expulsou de um canal +Comment[pt_BR]=Alguém retirou você de um canal +Comment[ru]=Кто-то выпнул вас с канала +Comment[sr]=Неко вас је избацио са канала +Comment[sr@Latn]=Neko vas je izbacio sa kanala +Comment[sv]=Någon sparkade ut dig från en kanal +Comment[ta]=யாரோ உங்களை வழிமுறையில் இருந்து வெளித்தள்ளிவிட்டார்கள் +Comment[tr]=Birisi sizi odadan tekmeledi +Comment[uk]=Хтось виштовхнув вас із каналу +Comment[xx]=xxSomeone kicked you out of a channelxx +Comment[zh_CN]=有人把您踢出了频道 +Comment[zh_TW]=有人將您踢出頻道 +default_presentation=0 + +[connectionFailure] +Name=Connection failure +Name[ar]=عطل في الإتصال +Name[bg]=Неуспешно свързване +Name[br]=Sac'het eo ar gevreadenn +Name[ca]=Error de connexió +Name[cs]=Selhání připojení +Name[da]=Forbindelse mislykket +Name[de]=Verbindungsfehler +Name[el]=Αποτυχία σύνδεσης +Name[es]=Fallo de la conexión +Name[et]=Ühenduse viga +Name[fi]=Yhteysvirhe +Name[ga]=Theip ar nascadh +Name[gl]=Erro de conexón +Name[he]=שגיאת התחברות +Name[it]=Errore di connessione +Name[ja]=接続失敗 +Name[ka]=კავშირი ვერ შედგა +Name[lt]=Nepavyko prisijungti +Name[nl]=Verbindingsfout +Name[pa]=ਕੁਨੈਕਸ਼ਨ ਫੇਲ੍ਹ +Name[pt]=Erro na ligação +Name[pt_BR]=Erro na conexão +Name[sr]=Грешка везе +Name[sr@Latn]=Greška veze +Name[sv]=Uppkopplingsfel +Name[tr]=Bağlantı hatası +Name[uk]=Помилка з'єднання +Name[xx]=xxConnection failurexx +Name[zh_CN]=连接失败 +Name[zh_TW]=連線失敗 +Comment=Failed to connect to server +Comment[ar]=فشلتُ في الإتصال بِلخادِم +Comment[bg]=Неуспех при свързване към сървър +Comment[ca]=No s'ha pogut connectar al servidor +Comment[cs]=Chyba při připojení k serveru +Comment[da]=Mislykkedes at forbinde til server +Comment[de]=Fehler beim Verbinden zum Server +Comment[el]=Η σύνδεση με τον εξυπηρετητή απέτυχε +Comment[es]=No ha sido posible conectarse al servidor +Comment[et]=Ühendumine serveriga ebaõnnestus +Comment[fi]=Palvelimeen yhdistäminen epäonnistui +Comment[ga]=Theip ar nascadh le freastalaí +Comment[gl]=Non foi posíbel conectar co servidor +Comment[he]=החיבור לשרת נכשל +Comment[it]=Connessione al server non riuscita +Comment[ja]=サーバへの接続に失敗しました +Comment[ka]=სერვერთან დაკავშირება ვერ განხორციელდა +Comment[lt]=Nepavyko prisijungti prie serverio +Comment[nl]=Verbinden met de server is mislukt +Comment[pt]=Não foi possível ligar ao servidor +Comment[pt_BR]=Falha ao conectar-se ao servidor +Comment[sr]=Неуспело повезивање са сервером +Comment[sr@Latn]=Neuspelo povezivanje sa serverom +Comment[sv]=Misslyckades koppla upp till server +Comment[tr]=Sunucuya bağlanılamadı +Comment[uk]=Не вдалося з'єднатись з сервером +Comment[xx]=xxFailed to connect to serverxx +Comment[zh_CN]=连接服务器失败 +Comment[zh_TW]=連線到伺服器失敗 +default_presentation=64 + +[channelJoin] +Name=You joined a channel +Name[ar]=إنضممت إلى قناة +Name[bg]=Вие се присъединихте към канал +Name[br]=Emellet out bet ur c'hanol +Name[ca]=Heu entrat a un canal +Name[cs]=Připojili jste se ke kanálu +Name[da]=Du gik med i en kanal +Name[de]=Sie haben einen Kanel betreten +Name[el]=Συνδεθήκατε σε ένα κανάλι +Name[es]=Se ha unido a un canal +Name[et]=Sa ühinesid kanaliga +Name[fi]=Liityit kanavalle +Name[ga]=Chuaigh tú le cainéal +Name[gl]=Uniu-se a un canal +Name[he]=אתה הצטרפת אל חדר +Name[it]=Sei entrato in un canale +Name[ja]=チャンネルに入りました +Name[ka]=თქვენ შეუერთდით არხს +Name[lt]=Prisijungėte prie kanalo +Name[nl]=U nam deel aan een kanaal +Name[pa]=ਤੁਸੀਂ ਇੱਕ ਚੈਨਲ 'ਚ ਦਾਖਲ ਹੋ ਗਏ +Name[pt]=Você juntou-se a um canal +Name[pt_BR]=Você entrou no canal +Name[sr]=Прикључили сте се каналу +Name[sr@Latn]=Priključili ste se kanalu +Name[sv]=Du gick med i en kanal +Name[tr]=Bir odaya girdiniz +Name[uk]=Ви приєднались до каналу +Name[xx]=xxYou joined a channelxx +Name[zh_CN]=您加入了一个频道 +Name[zh_TW]=您加入了一個頻道 +Comment=You joined a channel +Comment[ar]=إنضممت إلى قناة +Comment[bg]=Вие се присъединихте към канал +Comment[br]=Emellet out bet ur c'hanol +Comment[ca]=Heu entrat a un canal +Comment[cs]=Připojili jste se ke kanálu +Comment[da]=Du gik med i en kanal +Comment[de]=Sie haben einen Kanal betreten +Comment[el]=Συνδεθήκατε σε ένα κανάλι +Comment[es]=Se ha unido a un canal +Comment[et]=Sa ühinesid kanaliga +Comment[fi]=Liityit kanavalle +Comment[ga]=Chuaigh tú le cainéal +Comment[gl]=Uniu-se a un canal +Comment[he]=אתה הצטרפת אל חדר +Comment[it]=Sei entrato in un canale +Comment[ja]=チャンネルに入りました +Comment[ka]=თქვენ შეუერთდით არხს +Comment[lt]=Prisijungėte prie kanalo +Comment[nl]=U nam deel aan een kanaal +Comment[pa]=ਤੁਸੀਂ ਇੱਕ ਚੈਨਲ 'ਚ ਦਾਖਲ ਹੋ ਗਏ +Comment[pt]=Você juntou-se a um canal +Comment[pt_BR]=Você entrou em um canal +Comment[sr]=Прикључили сте се каналу +Comment[sr@Latn]=Priključili ste se kanalu +Comment[sv]=Du gick med i en kanal +Comment[tr]=Bir odaya girdiniz +Comment[uk]=Ви приєднались до каналу +Comment[xx]=xxYou joined a channelxx +Comment[zh_CN]=您加入了一个频道 +Comment[zh_TW]=您加入了一個頻道 +default_presentation=64 + +[dccChat] +Name=DCC Chat +Name[ar]=مكالمة DCC +Name[bg]=DCC разговор +Name[br]=Flapañ DCC +Name[ca]=Xat DCC +Name[cs]=DCC pokec +Name[cy]=Sgwrs DCC +Name[da]=Dcc-chat +Name[de]=DCC-Chat +Name[el]=Συζήτηση DCC +Name[es]=Charla DCC +Name[et]=DCC vestlus +Name[fi]=DCC-keskustelu +Name[ga]=Comhrá DCC +Name[gl]=Conversa DCC +Name[he]=שיחת DCC +Name[it]=Chat DCC +Name[ja]=DCC チャット +Name[ka]=Dcc საუბარი +Name[lt]=DCC pokalbis +Name[ms]=Chat DCC +Name[nl]=DCC-gesprek +Name[pa]=DCC ਗੱਲਬਾਤ +Name[pt]=Conversa DCC +Name[pt_BR]= Conversa privada (DCC) +Name[sr]=DCC ћаскање +Name[sr@Latn]=DCC ćaskanje +Name[sv]=DCC-chatt +Name[tr]=DCC Sohbeti +Name[uk]=Балачка DCC +Name[xx]=xxDCC Chatxx +Name[zh_CN]=DCC 聊天 +Name[zh_TW]=DCC 聊天 +Comment=Someone started a DCC chat with you +Comment[ar]=أحدٌ ما إبتدء مكالمة DCC معك +Comment[bg]=Някой е започнал разговор с вас в DCC +Comment[ca]=Algú ha iniciat un xat DCC amb vostè +Comment[cs]=Někdo si s vámi chce pokecat přes DCC +Comment[da]=Nogen startede en dcc-chat med dig +Comment[de]=Jemand hat einen DCC-Chat mit Ihnen begonnen +Comment[el]=Κάποιος ξεκίνησε μια συζήτηση DCC μαζί σας +Comment[es]=Alguien empezó una charla de tipo DCC con usted +Comment[et]=Keegi alustas sinuga DCC vestlust +Comment[fi]=Joku aloitti DCC-keskustelun kanssasi +Comment[ga]=Thosaigh duine éigin comhrá DCC leat +Comment[gl]=Alguén comezou unha conversa DCC contigo +Comment[he]=מישהו התחיל שיחת DCC אתך +Comment[it]=Qualcuno ha avviato una conversazione DCC con te +Comment[ja]=誰かがあなたと DCC チャットを開始しました +Comment[ka]=ვიღაცამ თქვენთან dcc საუბარი დაიწყო +Comment[lt]=Kažkas su jumis pradėjo DCC pokalbį +Comment[nl]=Iemand begon een DCC-gesprek met u +Comment[pt]=Alguém iniciou uma conversa DCC consigo +Comment[pt_BR]=Alguém começou uma conversa privada (DCC) com você +Comment[sr]=Неко је започео DCC ћаскање са вама +Comment[sr@Latn]=Neko je započeo DCC ćaskanje sa vama +Comment[sv]=Någon startade en DCC-chatt med dig +Comment[tr]=Birisi sizinle DCC sohbeti başlattı +Comment[uk]=Хтось почав з вами DCC-балачку +Comment[xx]=xxSomeone started a DCC chat with youxx +Comment[zh_CN]=有人向您打开了一个 DCC 聊天对话 +Comment[zh_TW]=有人開啟了與您的 DCC 聊天 +default_presentation=0 diff --git a/konversation/src/fontappearance_preferences.ui b/konversation/src/fontappearance_preferences.ui new file mode 100644 index 0000000..a59c3f7 --- /dev/null +++ b/konversation/src/fontappearance_preferences.ui @@ -0,0 +1,160 @@ + +FontAppearance_Config +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. + +Copyright (C) 2005 Peter Simonsson + + + FontAppearance_Config + + + + 0 + 0 + 454 + 213 + + + + + unnamed + + + 0 + + + + kcfg_FixedMOTD + + + Enable fi&xed font for MOTD messages + + + Show MOTD (Message Of The Day) message in fixed font + + + + + kcfg_UseBoldNicks + + + Show sender nicknames &bold in the chat view + + + + + spacer89 + + + Vertical + + + Expanding + + + + 20 + 161 + + + + + + kcfg_CustomTextFont + + + true + + + Chat text: + + + + + kcfg_TextFont + + + false + + + + + kcfg_ListFont + + + false + + + + + kcfg_TabFont + + + false + + + + + kcfg_CustomListFont + + + true + + + Nickname list: + + + + + kcfg_CustomTabFont + + + true + + + Tab bar: + + + + + + + kcfg_CustomTextFont + toggled(bool) + kcfg_TextFont + setEnabled(bool) + + + kcfg_CustomListFont + toggled(bool) + kcfg_ListFont + setEnabled(bool) + + + kcfg_CustomTabFont + toggled(bool) + kcfg_TabFont + setEnabled(bool) + + + + kcfg_CustomTextFont + kcfg_TextFont + kcfg_CustomListFont + kcfg_ListFont + kcfg_CustomTabFont + kcfg_TabFont + kcfg_FixedMOTD + kcfg_UseBoldNicks + + + + + kfontrequester.h + kfontrequester.h + kfontrequester.h + + diff --git a/konversation/src/generalbehavior_preferences.ui b/konversation/src/generalbehavior_preferences.ui new file mode 100644 index 0000000..2ef5829 --- /dev/null +++ b/konversation/src/generalbehavior_preferences.ui @@ -0,0 +1,360 @@ + +GeneralBehavior_Config +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. + +Copyright (C) 2005 Peter Simonsson + + + GeneralBehavior_Config + + + + 0 + 0 + 448 + 477 + + + + + unnamed + + + 0 + + + + kcfg_ShowTrayIcon + + + Enable System Tray + + + true + + + false + + + + unnamed + + + + kcfg_TrayNotify + + + &Use system tray for new message notification + + + + + spacer51 + + + Horizontal + + + Fixed + + + + 31 + 20 + + + + + + kcfg_TrayNotifyOnlyOwnNick + + + false + + + Only &notify when a highlight is triggered or your current nick is used + + + + + spacer51_2 + + + Horizontal + + + Fixed + + + + 31 + 20 + + + + + + kcfg_TrayNotifyBlink + + + Blin&k the icon + + + + + kcfg_HideToTrayOnStartup + + + Hide window on startup + + + + + + + middleLabel + + + Nickname Completion + + + + unnamed + + + + modeLbl + + + Completion &mode: + + + kcfg_NickCompletionMode + + + + + + Cycle NickList + + + + + Shell-Like + + + + + Shell-Like with Completion Box + + + + kcfg_NickCompletionMode + + + + + kcfg_NickCompleteSuffixStart + + + + + startOfLineLabel + + + Suffi&x at start of line: + + + kcfg_NickCompleteSuffixStart + + + + + kcfg_NickCompleteSuffixMiddle + + + + + textLabel3 + + + &Elsewhere: + + + kcfg_NickCompleteSuffixMiddle + + + + + kcfg_NickCompletionCaseSensitive + + + Case sensitive + + + + + + + + + + miscGBox + + + Miscellaneous + + + + unnamed + + + + kcfg_DisableNotifyWhileAway + + + Disable notifications while &away + + + + + kcfg_CustomVersionReplyEnabled + + + Use custom &version reply: + + + + + kcfg_CustomVersionReply + + + false + + + <qt>Here you can set a custom reply for <b>CTCP <i>VERSION</i></b> requests.</qt> + + + + + kcfg_CommandChar + + + + 0 + 0 + 0 + 0 + + + + 1 + + + + + kcfg_UseMultiRowInputBox + + + Input box expands with text + + + + + kcfg_WebBrowserCmd + + + false + + + + + commandCharLabel + + + Comman&d char: + + + kcfg_CommandChar + + + + + kcfg_UseCustomBrowser + + + Use custom web &browser: + + + + + + + spacer52 + + + Vertical + + + Expanding + + + + 20 + 20 + + + + + + + + + + kcfg_TrayNotify + toggled(bool) + kcfg_TrayNotifyOnlyOwnNick + setEnabled(bool) + + + kcfg_UseCustomBrowser + toggled(bool) + kcfg_WebBrowserCmd + setEnabled(bool) + + + kcfg_CustomVersionReplyEnabled + toggled(bool) + kcfg_CustomVersionReply + setEnabled(bool) + + + + kcfg_ShowTrayIcon + kcfg_TrayNotify + kcfg_TrayNotifyOnlyOwnNick + kcfg_NickCompletionMode + kcfg_NickCompleteSuffixStart + kcfg_NickCompleteSuffixMiddle + kcfg_NickCompletionCaseSensitive + kcfg_DisableNotifyWhileAway + kcfg_UseCustomBrowser + kcfg_WebBrowserCmd + kcfg_CommandChar + kcfg_CustomVersionReplyEnabled + kcfg_CustomVersionReply + kcfg_UseMultiRowInputBox + + + + + klineedit.h + klineedit.h + klineedit.h + klineedit.h + klineedit.h + + diff --git a/konversation/src/guess_ja.cpp b/konversation/src/guess_ja.cpp new file mode 100644 index 0000000..4e35217 --- /dev/null +++ b/konversation/src/guess_ja.cpp @@ -0,0 +1,377 @@ +/* + * This file is part of the KDE libraries + * + * Copyright (c) 2000-2003 Shiro Kawai + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the authors nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * original code is here. + * http://cvs.sourceforge.net/viewcvs.py/gauche/Gauche/ext/charconv/guess.c?view=markup + */ + +/* + * Maybe we should use QTextCodec::heuristicContentMatch() + * But it fails detection. It's not useful. + */ +#include "guess_ja.h" +#include "decoder.h" + +/* DFA tables */ +const dfa_table guess_eucj_st[] = { + { /* state init */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1, + }, + { /* state jis0201_kana */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }, + { /* state jis0213_1 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1, + }, + { /* state jis0213_2 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, -1, + }, +}; + +guess_arc guess_eucj_ar[7] = { + { 0, 1.0 }, /* init -> init */ + { 1, 0.8 }, /* init -> jis0201_kana */ + { 3, 0.95 }, /* init -> jis0213_2 */ + { 2, 1.0 }, /* init -> jis0213_1 */ + { 0, 1.0 }, /* jis0201_kana -> init */ + { 0, 1.0 }, /* jis0213_1 -> init */ + { 0, 1.0 }, /* jis0213_2 -> init */ +}; + +const dfa_table guess_sjis_st[] = { + { /* state init */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, + }, + { /* state jis0213 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1, -1, -1, + }, +}; + +guess_arc guess_sjis_ar[6] = { + { 0, 1.0 }, /* init -> init */ + { 1, 1.0 }, /* init -> jis0213 */ + { 0, 0.8 }, /* init -> init */ + { 1, 0.95 }, /* init -> jis0213 */ + { 0, 0.8 }, /* init -> init */ + { 0, 1.0 }, /* jis0213 -> init */ +}; + +const dfa_table guess_utf8_st[] = { + { /* state init */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, -1, -1, + }, + { /* state 1byte_more */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }, + { /* state 2byte_more */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }, + { /* state 3byte_more */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }, + { /* state 4byte_more */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }, + { /* state 5byte_more */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }, +}; + +guess_arc guess_utf8_ar[11] = { + { 0, 1.0 }, /* init -> init */ + { 1, 1.0 }, /* init -> 1byte_more */ + { 2, 1.0 }, /* init -> 2byte_more */ + { 3, 1.0 }, /* init -> 3byte_more */ + { 4, 1.0 }, /* init -> 4byte_more */ + { 5, 1.0 }, /* init -> 5byte_more */ + { 0, 1.0 }, /* 1byte_more -> init */ + { 1, 1.0 }, /* 2byte_more -> 1byte_more */ + { 2, 1.0 }, /* 3byte_more -> 2byte_more */ + { 3, 1.0 }, /* 4byte_more -> 3byte_more */ + { 4, 1.0 }, /* 5byte_more -> 4byte_more */ +}; + +/* Guessing Routine */ +enum JapaneseCode::Type JapaneseCode::guess_jp(const char *buf, int buflen) +{ + int i; + guess_dfa *top = NULL; + + for (i=0; iscore == 1.0 && sjis->score == 1.0 && utf8->score == 1.0) + return JapaneseCode::ASCII; + + /* Now, we have ambigous code. Pick the highest score. If more than + one candidate tie, pick the default encoding. */ + if (DFA_ALIVE(eucj)) top = eucj; + if (DFA_ALIVE(utf8)) { + if (top) { + if (top->score < utf8->score) top = utf8; + } else { + top = utf8; + } + } + if (DFA_ALIVE(sjis)) { + if (top) { + if (top->score <= sjis->score) top = sjis; + } else { + top = sjis; + } + } + + if (top == eucj) return JapaneseCode::EUC; + if (top == utf8) return JapaneseCode::UTF8; + if (top == sjis) return JapaneseCode::SJIS; + + return JapaneseCode::ASCII; +} diff --git a/konversation/src/guess_ja.h b/konversation/src/guess_ja.h new file mode 100644 index 0000000..3b87b55 --- /dev/null +++ b/konversation/src/guess_ja.h @@ -0,0 +1,116 @@ +/* + * This file is part of the KDE libraries + * + * Copyright (c) 2000-2003 Shiro Kawai + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the authors nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * original code is here. + * http://cvs.sourceforge.net/viewcvs.py/gauche/Gauche/ext/charconv/guess.c?view=markup + */ +#ifndef GUESS_JA_H +#define GUESS_JA_H + +class guess_arc { + public: + unsigned int next; /* next state */ + double score; /* score */ +}; + + +typedef signed char dfa_table[256]; + +/* DFA tables declared in guess_ja.cpp */ +extern const dfa_table guess_eucj_st[]; +extern guess_arc guess_eucj_ar[7]; +extern const dfa_table guess_sjis_st[]; +extern guess_arc guess_sjis_ar[6]; +extern const dfa_table guess_utf8_st[]; +extern guess_arc guess_utf8_ar[11]; + +class guess_dfa { + public: + const dfa_table *states; + const guess_arc *arcs; + int state; + double score; + + guess_dfa (const dfa_table stable[], const guess_arc *atable) : + states(stable), arcs(atable) + { + state = 0; + score = 1.0; + } +}; + +class JapaneseCode +{ + public: + enum Type {ASCII, JIS, EUC, SJIS, UNICODE, UTF8 }; + enum Type guess_jp(const char* buf, int buflen); + + JapaneseCode () { + eucj = new guess_dfa(guess_eucj_st, guess_eucj_ar); + sjis = new guess_dfa(guess_sjis_st, guess_sjis_ar); + utf8 = new guess_dfa(guess_utf8_st, guess_utf8_ar); + last_JIS_escape = false; + } + + ~JapaneseCode () { + if (eucj) delete eucj; + if (sjis) delete sjis; + if (utf8) delete utf8; + } + + protected: + guess_dfa *eucj; + guess_dfa *sjis; + guess_dfa *utf8; + + bool last_JIS_escape; +}; + +#define DFA_NEXT(dfa, ch) \ + do { \ + int arc__; \ + if (dfa->state >= 0) { \ + arc__ = dfa->states[dfa->state][ch]; \ + if (arc__ < 0) { \ + dfa->state = -1; \ + } else { \ + dfa->state = dfa->arcs[arc__].next; \ + dfa->score *= dfa->arcs[arc__].score; \ + } \ + } \ + } while (0) + +#define DFA_ALIVE(dfa) (dfa->state >= 0) + +#endif /* GUESS_JA_H */ diff --git a/konversation/src/highlight.cpp b/konversation/src/highlight.cpp new file mode 100644 index 0000000..275c441 --- /dev/null +++ b/konversation/src/highlight.cpp @@ -0,0 +1,49 @@ +/*************************************************************************** + begin : Sat Jun 15 2002 + copyright : (C) 2002 by Matthias Gierlings + email : gismore@users.sourceforge.net +***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "highlight.h" + + +unsigned int Highlight::s_id = 0; // static + +Highlight::Highlight(const QString& itemPattern, +bool regExp, +const QColor& itemColor, +const KURL& soundURL, +const QString& autoText) +{ + m_itemPattern = itemPattern; + m_autoText = autoText; + m_itemColor = itemColor; + m_soundURL = soundURL; + m_regExp = regExp; + + // unique ID for every Highlight + m_itemID = s_id++; +} + +int Highlight::getID() { return m_itemID; } +QString Highlight::getPattern() { return m_itemPattern; } +QString Highlight::getAutoText() { return m_autoText; } +QColor Highlight::getColor() { return m_itemColor; } +KURL Highlight::getSoundURL() { return m_soundURL; } + +void Highlight::setPattern(const QString& itemPattern) { m_itemPattern = itemPattern; } +void Highlight::setAutoText(const QString& autoText) { m_autoText = autoText; } +void Highlight::setColor(const QColor& itemColor) { m_itemColor = itemColor; } +void Highlight::setSoundURL(const KURL& url) { m_soundURL = url; } + +void Highlight::setRegExp(bool state) { m_regExp=state; } +bool Highlight::getRegExp() { return m_regExp; } diff --git a/konversation/src/highlight.h b/konversation/src/highlight.h new file mode 100644 index 0000000..e843023 --- /dev/null +++ b/konversation/src/highlight.h @@ -0,0 +1,63 @@ +/*************************************************************************** + highlight.cpp - description + ------------------- + begin : Sat Jun 15 2002 + copyright : (C) 2002 by Matthias Gierlings + email : gismore@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef HIGHLIGHT_H +#define HIGHLIGHT_H + +#include +#include + +#include + +/** + *@author Matthias Gierlings + */ + +class Highlight +{ + public: + Highlight(const QString& itemPattern, + bool regExp, + const QColor& itemColor, + const KURL& soundURL, + const QString& autoText); + + QString getPattern(); + QString getAutoText(); + QColor getColor(); + int getID(); + bool getRegExp(); + KURL getSoundURL(); + + void setPattern(const QString& itemPattern); + void setColor(const QColor& itemColor); + void setSoundURL(const KURL& url); + void setAutoText(const QString& autoText); + void setRegExp(bool state); + + protected: + static unsigned int s_id; + + int m_itemID; + bool m_regExp; + + QString m_itemPattern; + QString m_autoText; + QColor m_itemColor; + KURL m_soundURL; +}; +#endif diff --git a/konversation/src/highlight_preferences.cpp b/konversation/src/highlight_preferences.cpp new file mode 100644 index 0000000..be757e6 --- /dev/null +++ b/konversation/src/highlight_preferences.cpp @@ -0,0 +1,352 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006 John Tapsell +*/ + +#include "highlight_preferences.h" +#include "highlightviewitem.h" +#include "konversationapplication.h" +#include "konversationsound.h" +#include "config/preferences.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +Highlight_Config::Highlight_Config(QWidget* parent, const char* name) + : Highlight_ConfigUI(parent,name) +{ + // reset flag to defined state (used to block signals when just selecting a new item) + newItemSelected=false; + + loadSettings(); + + // make list accept drag & drop + highlightListView->setSorting(-1); + highlightListView->header()->setMovingEnabled(false); + + soundPlayBtn->setIconSet(SmallIconSet( "player_play" )); + soundURL->setCaption(i18n("Select Sound File")); + + // This code was copied from KNotifyWidget::openSoundDialog() (knotifydialog.cpp) [it's under LGPL v2] + // find the first "sound"-resource that contains files + QStringList soundDirs = KGlobal::dirs()->findDirs("data", "konversation/sounds"); + soundDirs += KGlobal::dirs()->resourceDirs( "sound" ); + + if ( !soundDirs.isEmpty() ) { + KURL url; + QDir dir; + dir.setFilter( QDir::Files | QDir::Readable ); + QStringList::ConstIterator it = soundDirs.begin(); + while ( it != soundDirs.end() ) { + dir = *it; + if ( dir.isReadable() && dir.count() > 2 ) { + url.setPath( *it ); + soundURL->fileDialog()->setURL( url ); + break; + } + ++it; + } + } + // End copy + + connect(highlightListView,SIGNAL (selectionChanged(QListViewItem*)),this,SLOT (highlightSelected(QListViewItem*)) ); + connect(highlightListView,SIGNAL (clicked(QListViewItem*)),this,SLOT (highlightSelected(QListViewItem*)) ); + connect(highlightListView,SIGNAL (spacePressed(QListViewItem*)),this,SLOT (highlightSelected(QListViewItem*)) ); + + connect(highlightListView,SIGNAL (moved()),this,SIGNAL (modified()) ); + + connect(patternInput,SIGNAL (textChanged(const QString&)),this,SLOT (highlightTextChanged(const QString&)) ); + connect(patternButton,SIGNAL (clicked()),this,SLOT(highlightTextEditButtonClicked())); + connect(patternColor,SIGNAL (changed(const QColor&)),this,SLOT (highlightColorChanged(const QColor&)) ); + + connect(soundURL, SIGNAL(textChanged(const QString&)), this, SLOT(soundURLChanged(const QString&))); + connect(soundPlayBtn, SIGNAL(clicked()), this, SLOT(playSound())); + + connect(autoTextInput,SIGNAL (textChanged(const QString&)),this,SLOT (autoTextChanged(const QString&)) ); + + connect(newButton,SIGNAL (clicked()),this,SLOT (addHighlight()) ); + connect(removeButton,SIGNAL (clicked()),this,SLOT (removeHighlight()) ); + + updateButtons(); +} + +Highlight_Config::~Highlight_Config() +{ +} + +void Highlight_Config::restorePageToDefaults() +{ + if(highlightListView->childCount() != 0) { + highlightListView->clear(); + emit modified(); + } +} + +void Highlight_Config::loadSettings() +{ + QPtrList highlightList=Preferences::highlightList(); + highlightListView->clear(); + // fill in the highlight patterns backwards to keep the right sorting order + for(unsigned int i=highlightList.count();i!=0;i--) + { + Highlight* currentHighlight=highlightList.at(i-1); + new HighlightViewItem(highlightListView,currentHighlight); + } + + highlightListView->setSelected(highlightListView->firstChild(), true); + + // remember current list for hasChanged() + m_oldHighlightList=currentHighlightList(); +} + +bool Highlight_Config::hasChanged() +{ + return(m_oldHighlightList!=currentHighlightList()); +} + +// Slots: + +void Highlight_Config::highlightSelected(QListViewItem* item) +{ + // check if there was a widget selected at all + if(item) + { + // make a highlight item out of the generic qlistviewitem + HighlightViewItem* highlightItem=static_cast(item); + + // check if the checkbox on the item has changed + if(highlightItem->hasChanged()) + { + // tell the prefs system it was changed and acknowledge the change to the listview item + emit modified(); + highlightItem->changeAcknowledged(); + } + + // tell all now emitted signals that we just clicked on a new item, so they should + // not emit the modified() signal. + newItemSelected=true; + patternColor->setColor(highlightItem->getColor()); + patternInput->setText(highlightItem->getPattern()); + soundURL->setURL(highlightItem->getSoundURL().prettyURL()); + autoTextInput->setText(highlightItem->getAutoText()); + // all signals will now emit the modified() signal again + newItemSelected=false; + // remember to enable all edit widgets + } + updateButtons(); + + } + +void Highlight_Config::updateButtons() +{ + bool enabled = highlightListView->selectedItem() != NULL; + // is the kregexpeditor installed? + bool installed = !KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty(); + // enable or disable edit widgets + patternLabel->setEnabled(enabled); + patternInput->setEnabled(enabled); + patternButton->setEnabled(enabled && installed); + colorLabel->setEnabled(enabled); + patternColor->setEnabled(enabled); + soundURL->setEnabled(enabled); + soundLabel->setEnabled(enabled); + soundPlayBtn->setEnabled(enabled); + autoTextLabel->setEnabled(enabled); + autoTextInput->setEnabled(enabled); + + if(installed) + { + QToolTip::add(patternButton, i18n("Click to run Regular Expression Editor (KRegExpEditor)")); + } + else + { + QToolTip::add(patternButton, i18n("The Regular Expression Editor (KRegExpEditor) is not installed")); + } +} + +void Highlight_Config::highlightTextChanged(const QString& newPattern) +{ + HighlightViewItem* item=static_cast(highlightListView->selectedItem()); + + if(!newItemSelected && item) + { + item->setPattern(newPattern); + emit modified(); + } +} + +void Highlight_Config::highlightTextEditButtonClicked() +{ + QDialog *editorDialog = + KParts::ComponentFactory::createInstanceFromQuery( "KRegExpEditor/KRegExpEditor" ); + if (editorDialog) + { + // kdeutils was installed, so the dialog was found. Fetch the editor interface. + KRegExpEditorInterface *reEditor = + static_cast(editorDialog->qt_cast( "KRegExpEditorInterface" ) ); + Q_ASSERT( reEditor ); // This should not fail!// now use the editor. + reEditor->setRegExp(patternInput->text()); + int dlgResult = editorDialog->exec(); + if ( dlgResult == QDialog::Accepted ) + { + QString re = reEditor->regExp(); + patternInput->setText(re); + HighlightViewItem* item=static_cast(highlightListView->selectedItem()); + if(item) item->setPattern(re); + } + delete editorDialog; + } +} + +void Highlight_Config::highlightColorChanged(const QColor& newColor) +{ + HighlightViewItem* item=static_cast(highlightListView->selectedItem()); + + if(!newItemSelected && item) + { + item->setColor(newColor); + item->repaint(); + emit modified(); + } +} + +void Highlight_Config::soundURLChanged(const QString& newURL) +{ + HighlightViewItem* item=static_cast(highlightListView->selectedItem()); + + if(!newItemSelected && item) + { + item->setSoundURL(KURL(newURL)); + emit modified(); + } +} + +void Highlight_Config::autoTextChanged(const QString& newText) +{ + HighlightViewItem* item=static_cast(highlightListView->selectedItem()); + + if(!newItemSelected && item) + { + item->setAutoText(newText); + emit modified(); + } +} + +void Highlight_Config::addHighlight() +{ + Highlight* newHighlight=new Highlight(i18n("New"),false,QColor("#ff0000"),KURL(),QString()); + + HighlightViewItem* item=new HighlightViewItem(highlightListView,newHighlight); + highlightListView->setSelected(item,true); + patternInput->setFocus(); + patternInput->selectAll(); + emit modified(); +} + +void Highlight_Config::removeHighlight() +{ + HighlightViewItem* item=static_cast(highlightListView->selectedItem()); + + if(item) + { + delete item; + + item=static_cast(highlightListView->currentItem()); + + if(item) + highlightListView->setSelected(item,true); + + emit modified(); + } + updateButtons(); +} + +QPtrList Highlight_Config::getHighlightList() +{ + QPtrList newList; + + HighlightViewItem* item=static_cast(highlightListView->firstChild()); + while(item) + { + newList.append(new Highlight(item->getPattern(),item->getRegExp(),item->getColor(),item->getSoundURL(),item->getAutoText())); + item=item->itemBelow(); + } + + return newList; +} + +QStringList Highlight_Config::currentHighlightList() +{ + QStringList newList; + + HighlightViewItem* item=static_cast(highlightListView->firstChild()); + while(item) + { + newList.append(item->getPattern()+item->getRegExp()+item->getColor().name()+item->getSoundURL().url()+item->getAutoText()); + item=item->itemBelow(); + } + + return newList; +} + +void Highlight_Config::playSound() +{ + KonversationApplication *konvApp=static_cast(KApplication::kApplication()); + konvApp->sound()->play(KURL(soundURL->url())); +} + +void Highlight_Config::saveSettings() +{ + KConfig* config = kapp->config(); + + // Write all highlight entries + QPtrList hiList=getHighlightList(); + int i = 0; + for(Highlight* hl = hiList.first(); hl; hl = hiList.next()) + { + config->setGroup(QString("Highlight%1").arg(i)); + config->writeEntry("Pattern", hl->getPattern()); + config->writeEntry("RegExp", hl->getRegExp()); + config->writeEntry("Color", hl->getColor()); + config->writePathEntry("Sound", hl->getSoundURL().prettyURL()); + config->writeEntry("AutoText", hl->getAutoText()); + i++; + } + + Preferences::setHighlightList(hiList); + + // Remove unused entries... + while(config->hasGroup(QString("Highlight%1").arg(i))) + { + config->deleteGroup(QString("Highlight%1").arg(i)); + i++; + } + + // remember current list for hasChanged() + m_oldHighlightList=currentHighlightList(); +} + +#include "highlight_preferences.moc" diff --git a/konversation/src/highlight_preferences.h b/konversation/src/highlight_preferences.h new file mode 100644 index 0000000..997a4c1 --- /dev/null +++ b/konversation/src/highlight_preferences.h @@ -0,0 +1,63 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006 John Tapsell +*/ + +#ifndef KONVERSATIONHIGHLIGHT_CONFIG_H +#define KONVERSATIONHIGHLIGHT_CONFIG_H + +#include "highlight_preferencesui.h" +#include "konvisettingspage.h" + +#include + + +class Highlight_Config; +class Highlight; + +class Highlight_Config : public Highlight_ConfigUI, public KonviSettingsPage +{ + Q_OBJECT + + public: + explicit Highlight_Config(QWidget *parent = 0, const char *name = 0); + ~Highlight_Config(); + + public: + virtual void saveSettings(); + virtual void loadSettings(); + virtual void restorePageToDefaults(); + + virtual bool hasChanged(); + + signals: + void modified(); + + protected slots: + void highlightSelected(QListViewItem* item); + void highlightTextChanged(const QString& newPattern); + void highlightTextEditButtonClicked(); + void highlightColorChanged(const QColor& newColor); + void soundURLChanged(const QString& newURL); + void autoTextChanged(const QString& newText); + void addHighlight(); + void removeHighlight(); + void playSound(); + QPtrList getHighlightList(); // prefs format + QStringList currentHighlightList(); // hasChanged() format + protected: + void updateButtons(); + + bool newItemSelected; + QStringList m_oldHighlightList; +}; + +#endif + diff --git a/konversation/src/highlight_preferencesui.ui b/konversation/src/highlight_preferencesui.ui new file mode 100644 index 0000000..3e617d6 --- /dev/null +++ b/konversation/src/highlight_preferencesui.ui @@ -0,0 +1,453 @@ + +Highlight_ConfigUI + + + Highlight_ConfigUI + + + + 0 + 0 + 614 + 585 + + + + + unnamed + + + 0 + + + + groupBox1 + + + Highlight List + + + + unnamed + + + + + RegEx + + + true + + + true + + + + + Highlights + + + true + + + true + + + + + Sound + + + true + + + true + + + + + Auto Text + + + true + + + true + + + + highlightListView + + + true + + + true + + + true + + + true + + + + + layout13 + + + + unnamed + + + + newButton + + + + 1 + 0 + 0 + 0 + + + + &New + + + + + removeButton + + + + 1 + 0 + 0 + 0 + + + + &Remove + + + + + spacer27 + + + Vertical + + + Expanding + + + + 20 + 250 + + + + + + + + patternButton + + + false + + + + 0 + 0 + 0 + 0 + + + + ... + + + + + + Click to run Regular Expression Editor (KRegExpEditor) + + + + + patternLabel + + + false + + + &Pattern: + + + patternInput + + + + + patternInput + + + false + + + + 7 + 0 + 1 + 0 + + + + + + colorLabel + + + false + + + Color: + + + + + patternColor + + + false + + + + + + + + soundLabel + + + false + + + &Sound: + + + soundURL + + + + + soundURL + + + false + + + + 7 + 0 + 0 + 0 + + + + audio/x-wav audio/x-mp3 application/ogg audio/x-adpcm + + + + + soundPlayBtn + + + false + + + + 4 + 5 + 0 + 0 + + + + + + + Test sound + + + + + autoTextLabel + + + false + + + &Auto text: + + + autoTextInput + + + + + autoTextInput + + + false + + + + + + + kcfg_HighlightSoundsEnabled + + + Ena&ble sound for highlights + + + + + kcfg_HighlightNickColor + + + false + + + + + + + + kcfg_HighlightOwnLinesColor + + + false + + + + + + + + kcfg_HighlightNick + + + Alwa&ys highlight own current nick: + + + + + kcfg_HighlightOwnLines + + + Always highlight own &lines: + + + + + spacer11 + + + Horizontal + + + Expanding + + + + 120 + 20 + + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 50 + 20 + + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 50 + 21 + + + + + + + + kcfg_HighlightNick + toggled(bool) + kcfg_HighlightNickColor + setEnabled(bool) + + + kcfg_HighlightOwnLines + toggled(bool) + kcfg_HighlightOwnLinesColor + setEnabled(bool) + + + + highlightListView + patternInput + patternButton + patternColor + soundURL + soundPlayBtn + autoTextInput + kcfg_HighlightSoundsEnabled + kcfg_HighlightNick + kcfg_HighlightNickColor + kcfg_HighlightOwnLines + kcfg_HighlightOwnLinesColor + newButton + removeButton + + + + klistview.h + kpushbutton.h + kpushbutton.h + kpushbutton.h + klineedit.h + klineedit.h + kcolorbutton.h + kurlrequester.h + klineedit.h + kpushbutton.h + kcolorbutton.h + kcolorbutton.h + + diff --git a/konversation/src/highlightviewitem.cpp b/konversation/src/highlightviewitem.cpp new file mode 100644 index 0000000..49c9789 --- /dev/null +++ b/konversation/src/highlightviewitem.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + begin : Sat Jun 15 2002 + copyright : (C) 2002 by Matthias Gierlings + email : gismore@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "highlightviewitem.h" + +#include +#include + + +HighlightViewItem::HighlightViewItem(KListView* parent, Highlight* passed_Highlight) +: QCheckListItem(parent, QString(), QCheckListItem::CheckBox) +{ + setText(1,passed_Highlight->getPattern()); + itemColor = passed_Highlight->getColor(); + itemID = passed_Highlight->getID(); + setSoundURL(passed_Highlight->getSoundURL()); + setAutoText(passed_Highlight->getAutoText()); + setOn(passed_Highlight->getRegExp()); + m_changed=false; +} + +HighlightViewItem::~HighlightViewItem() +{ +} + +void HighlightViewItem::paintCell(QPainter* p, const QColorGroup &cg, int column, int width, int alignment) +{ + // copy all colors from cg and only then change needed colors + itemColorGroup=cg; + itemColorGroup.setColor(QColorGroup::Text, itemColor); + QCheckListItem::paintCell(p, itemColorGroup, column, width, alignment); +} + +HighlightViewItem* HighlightViewItem::itemBelow() +{ + return (HighlightViewItem*) QCheckListItem::itemBelow(); +} + +void HighlightViewItem::setPattern(const QString& newPattern) { setText(1,newPattern); } +QString HighlightViewItem::getPattern() { return text(1); } + +void HighlightViewItem::setSoundURL(const KURL& url) +{ + soundURL = url; + setText(2, soundURL.prettyURL()); +} + +void HighlightViewItem::setAutoText(const QString& newAutoText) +{ + autoText = newAutoText; + setText(3,newAutoText); +} + +bool HighlightViewItem::getRegExp() +{ + return isOn(); +} + +QString HighlightViewItem::getAutoText() +{ + return autoText; +} + +// override default method to store the change +void HighlightViewItem::stateChange(bool /* newState */) +{ + // remember that the check box has been changed + m_changed=true; +} + +// returns true, if the checkbox has been changed +bool HighlightViewItem::hasChanged() +{ + return m_changed; +} + +// tells us that the program has seen us changing +void HighlightViewItem::changeAcknowledged() +{ + m_changed=false; +} diff --git a/konversation/src/highlightviewitem.h b/konversation/src/highlightviewitem.h new file mode 100644 index 0000000..89d4ce0 --- /dev/null +++ b/konversation/src/highlightviewitem.h @@ -0,0 +1,72 @@ +/*************************************************************************** + begin : Sat Jun 15 2002 + copyright : (C) 2002 by Matthias Gierlings + email : gismore@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef HIGHLIGHTVIEWITEM_H +#define HIGHLIGHTVIEWITEM_H + +#include "highlight.h" + +#include + + +class KURL; +class KListView; + +class HighlightViewItem : public QCheckListItem +{ + public: + HighlightViewItem(KListView* parent, Highlight* passed_Highlight); + ~HighlightViewItem(); + + QString getPattern(); + QString getAutoText(); + QColor getColor() { return itemColor; } + int getID() { return itemID; } + bool getRegExp(); + KURL getSoundURL() { return soundURL; } + + void setPattern(const QString& newPattern); + void setAutoText(const QString& newAutoText); + void setColor(QColor passed_itemColor) { itemColor = passed_itemColor; } + void setID(int passed_itemID) { itemID = passed_itemID; } + void setSoundURL(const KURL& url); + + /** checks if the checkbox has been changed by the user + * stored internally by m_changed + * + * @return true when the checkbox has been changed + */ + bool hasChanged(); + + /** reset the change state of the listview item + * call this when you have seen the change and acted upon it properly + */ + void changeAcknowledged(); + + HighlightViewItem* itemBelow(); + + protected: + QColor itemColor; + QColorGroup itemColorGroup; + int itemID; + KURL soundURL; + QString autoText; + + bool m_changed; // true if the checkbox has been changed + + void stateChange(bool newState); // reimplemented to store changed value + void paintCell(QPainter* p, const QColorGroup &cg, int column, int width, int alignment); +}; +#endif diff --git a/konversation/src/identity.cpp b/konversation/src/identity.cpp new file mode 100644 index 0000000..01697dd --- /dev/null +++ b/konversation/src/identity.cpp @@ -0,0 +1,177 @@ +/* + 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 class holds the various user identities + begin: Son Feb 9 2003 + copyright: (C) 2003 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include "identity.h" +#include "irccharsets.h" + +#include + +#include +#include + + +int Identity::s_availableId = 0; + +Identity::Identity() : KShared() +{ + m_id = s_availableId; + s_availableId++; + + init(); +} + +Identity::Identity(int id) : KShared() +{ + if (id < 0) + { + m_id = s_availableId; + s_availableId++; + } + else + { + m_id = id; + } + + init(); +} + +Identity::Identity(const Identity& original) : KShared() +{ + copy(original); + m_id = original.id(); +} + +Identity::~Identity() +{ +} + +void Identity::init() +{ + setCodecName(Konversation::IRCCharsets::self()->encodingForLocale()); + + setInsertRememberLineOnAway(false); + + setQuitReason("Konversation terminated!"); + setPartReason("Konversation terminated!"); + setKickReason("User terminated!"); + + setShowAwayMessage(false); + setAwayMessage("/me is away: %s"); + setReturnMessage("/me is back."); + + setAutomaticAway(false); + setAwayInactivity(10); + setAutomaticUnaway(false); +} + +void Identity::copy(const Identity& original) +{ + setName(original.getName()); + setRealName(original.getRealName()); + setIdent(original.getIdent()); + setNicknameList(original.getNicknameList()); + setBot(original.getBot()); + setPassword(original.getPassword()); + setQuitReason(original.getQuitReason()); + setPartReason(original.getPartReason()); + setKickReason(original.getKickReason()); + setInsertRememberLineOnAway(original.getInsertRememberLineOnAway()); + setShowAwayMessage(original.getShowAwayMessage()); + setAwayMessage(original.getAwayMessage()); + setAwayNick(original.getAwayNick()); + setReturnMessage(original.getReturnMessage()); + setAutomaticAway(original.getAutomaticAway()); + setAwayInactivity(original.getAwayInactivity()); + setAutomaticUnaway(original.getAutomaticUnaway()); + setShellCommand(original.getShellCommand()); + setCodecName(original.getCodecName()); +} + +void Identity::setName(const QString& newName) { name=newName; } +QString Identity::getName() const { return name; } + +void Identity::setRealName(const QString& name) { realName=name; } +QString Identity::getRealName() const { return realName; } +void Identity::setIdent(const QString& newIdent) { ident=newIdent; } +QString Identity::getIdent() const { return ident; } + +void Identity::setNickname(uint index,const QString& newName) { nicknameList[index]=newName; } + +QString Identity::getNickname(uint index) const +{ + if(index < nicknameList.count()) + return nicknameList[index]; + else + return QString(); +} + +void Identity::setBot(const QString& newBot) { bot=newBot; } +QString Identity::getBot() const { return bot; } + +void Identity::setPassword(const QString& newPassword) { password=newPassword; } +QString Identity::getPassword() const { return password; } + +void Identity::setQuitReason(const QString& reason) { quitReason=reason; } +QString Identity::getQuitReason() const { return quitReason; } +void Identity::setPartReason(const QString& reason) { partReason=reason; } +QString Identity::getPartReason() const { return partReason; } +void Identity::setKickReason(const QString& reason) { kickReason=reason; } +QString Identity::getKickReason() const { return kickReason; } + +void Identity::setInsertRememberLineOnAway(bool state) { insertRememberLineOnAway = state; } +bool Identity::getInsertRememberLineOnAway() const { return insertRememberLineOnAway; } +void Identity::setShowAwayMessage(bool state) { showAwayMessages=state; } +bool Identity::getShowAwayMessage() const { return showAwayMessages; } + +void Identity::setAwayMessage(const QString& message) { awayMessage=message; } +QString Identity::getAwayMessage() const { return awayMessage; } +void Identity::setReturnMessage(const QString& message) { returnMessage=message; } +QString Identity::getReturnMessage() const { return returnMessage; } + +void Identity::setAutomaticAway(bool automaticAway) { m_automaticAway = automaticAway; } +bool Identity::getAutomaticAway() const { return m_automaticAway; } +void Identity::setAwayInactivity(int awayInactivity) { m_awayInactivity = awayInactivity; } +int Identity::getAwayInactivity() const { return m_awayInactivity; } +void Identity::setAutomaticUnaway(bool automaticUnaway) { m_automaticUnaway = automaticUnaway; } +bool Identity::getAutomaticUnaway() const { return m_automaticUnaway; } + +void Identity::setNicknameList(const QStringList& newList) +{ + nicknameList.clear(); + nicknameList = newList; +} + +QStringList Identity::getNicknameList() const { return nicknameList; } + +QString Identity::getShellCommand() const { return m_shellCommand;} +void Identity::setShellCommand(const QString& command) { m_shellCommand=command;} + +QTextCodec* Identity::getCodec() const { return m_codec; } +QString Identity::getCodecName() const { return m_codecName; } +void Identity::setCodecName(const QString &newCodecName) +{ + // NOTE: codecName should be based on KCharsets::availableEncodingNames() / descriptiveEncodingNames() + // We can get a QTextCodec from QString based on them, but can't do the reverse of that. + + // never set an empty or borked codec! + QString codecName=newCodecName.lower(); + if(!Konversation::IRCCharsets::self()->isValidEncoding(codecName)) + codecName=Konversation::IRCCharsets::self()->encodingForLocale(); + + m_codecName=codecName; + m_codec=Konversation::IRCCharsets::self()->codecForName(codecName); +} + +QString Identity::getAwayNick() const { return awayNick; } +void Identity::setAwayNick(const QString& n) { awayNick = n; } diff --git a/konversation/src/identity.h b/konversation/src/identity.h new file mode 100644 index 0000000..8fdec49 --- /dev/null +++ b/konversation/src/identity.h @@ -0,0 +1,133 @@ +/* + 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 class holds the various user identities + begin: Son Feb 9 2003 + copyright: (C) 2003 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#ifndef IDENTITY_H +#define IDENTITY_H + +#include +#include + + +class QTextCodec; + +class Identity : public KShared +{ + public: + /// Create an Identity with a new id. + Identity(); + /// Create a new Identity with a set id. + explicit Identity(int id); + /// Copy all of @param original including the id. + Identity(const Identity& original); + ~Identity(); + + /// This function copies all of @param original but the id + void copy(const Identity& original); + + void setName(const QString& name); // the name of this identity + QString getName() const; + + void setRealName(const QString& name); + QString getRealName() const; + void setIdent(const QString& ident); + QString getIdent() const; + + void setNickname(uint index,const QString& nick); + QString getNickname(uint index) const; + + void setBot(const QString& bot); + QString getBot() const; + void setPassword(const QString& password); + QString getPassword() const; + + void setNicknameList(const QStringList& newList); + QStringList getNicknameList() const; + + void setQuitReason(const QString& reason); + QString getQuitReason() const; + void setPartReason(const QString& reason); + QString getPartReason() const; + void setKickReason(const QString& reason); + QString getKickReason() const; + + void setInsertRememberLineOnAway(bool state); + bool getInsertRememberLineOnAway() const; + void setShowAwayMessage(bool state); + bool getShowAwayMessage() const; + + void setAwayMessage(const QString& message); + QString getAwayMessage() const; + void setReturnMessage(const QString& message); + QString getReturnMessage() const; + + void setAutomaticAway(bool automaticAway); + bool getAutomaticAway() const; + void setAwayInactivity(int awayInactivity); + int getAwayInactivity() const; + void setAutomaticUnaway(bool automaticUnaway); + bool getAutomaticUnaway() const; + + void setShellCommand(const QString &command); + QString getShellCommand() const; + + void setCodecName(const QString &newCodecName); + QString getCodecName() const; + QTextCodec* getCodec() const; + + QString getAwayNick() const; + void setAwayNick(const QString& n); + + int id() const { return m_id; } + + protected: + QString name; + + QString bot; + QString password; + + QString realName; + QString ident; + + QStringList nicknameList; + + QString partReason; + QString quitReason; + QString kickReason; + + bool insertRememberLineOnAway; + bool showAwayMessages; + QString awayMessage; + QString returnMessage; + + bool m_automaticAway; + int m_awayInactivity; + bool m_automaticUnaway; + + QString m_codecName; + QTextCodec* m_codec; + + QString m_shellCommand; + + QString awayNick; + + private: + int m_id; + static int s_availableId; + void init(); +}; + +typedef KSharedPtr IdentityPtr; +typedef QValueList IdentityList; + +#endif diff --git a/konversation/src/identitydialog.cpp b/konversation/src/identitydialog.cpp new file mode 100644 index 0000000..aa054b3 --- /dev/null +++ b/konversation/src/identitydialog.cpp @@ -0,0 +1,642 @@ +/* + 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. +*/ + +/* + copyright: (C) 2004 by Peter Simonsson + email: psn@linux.se +*/ +#include "identitydialog.h" +#include "konversationapplication.h" +#include "awaymanager.h" +#include "irccharsets.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace Konversation +{ + + IdentityDialog::IdentityDialog(QWidget *parent, const char *name) + : KDialogBase(Plain, i18n("Identities"), Ok|Cancel, Ok, parent, name) + { + QFrame* mainWidget = plainPage(); + QGridLayout* mainLayout = new QGridLayout(mainWidget, 1, 2, 0, spacingHint()); + + QLabel* identityLabel = new QLabel(i18n("&Identity:"), mainWidget); + m_identityCBox = new KComboBox(mainWidget, "identity_combo"); + m_identityCBox->setEditable(false); + identityLabel->setBuddy(m_identityCBox); + + IdentityList tmpList = Preferences::identityList(); + + for(IdentityList::ConstIterator it = tmpList.begin(); it != tmpList.end(); ++it) + { + m_identityCBox->insertItem((*it)->getName()); + m_identityList.append(new Identity(*(*it))); + } + + QToolButton* newBtn = new QToolButton(mainWidget); + newBtn->setIconSet(SmallIconSet("add")); + newBtn->setTextLabel(i18n("Add")); + connect(newBtn, SIGNAL(clicked()), this, SLOT(newIdentity())); + + QToolButton* copyBtn = new QToolButton(mainWidget); + copyBtn->setIconSet(SmallIconSet("editcopy")); + copyBtn->setTextLabel(i18n("Duplicate")); + connect(copyBtn, SIGNAL(clicked()), this, SLOT(copyIdentity())); + + m_editBtn = new QToolButton(mainWidget); + m_editBtn->setIconSet(SmallIconSet("edit")); + m_editBtn->setTextLabel(i18n("Rename")); + connect(m_editBtn, SIGNAL(clicked()), this, SLOT(renameIdentity())); + + m_delBtn = new QToolButton(mainWidget); + m_delBtn->setIconSet(SmallIconSet("editdelete")); + m_delBtn->setTextLabel(i18n("Remove")); + connect(m_delBtn, SIGNAL(clicked()), this, SLOT(deleteIdentity())); + + QTabWidget* tabWidget = new QTabWidget(mainWidget); + QWidget* generalWidget = new QWidget(tabWidget); + tabWidget->addTab(generalWidget, i18n("General")); + QGridLayout* generalLayout = new QGridLayout(generalWidget, 1, 2, marginHint(), spacingHint()); + + QLabel* realNameLabel = new QLabel(i18n("&Real name:"), generalWidget); + m_realNameEdit = new KLineEdit(generalWidget); + QWhatsThis::add(m_realNameEdit, i18n("Enter your real name here. IRC is not intended to keep you hidden from your friends or enemies. Keep this in mind if you are tempted to behave maliciously. A fake \"real name\" can be a good way to mask your gender from all the nerds out there, but the PC you use can always be traced so you will never be truly anonymous.")); + realNameLabel->setBuddy(m_realNameEdit); + + QGroupBox* nicknameGBox = new QGroupBox(0, Qt::Horizontal, i18n("Nickname"), generalWidget); + nicknameGBox->setMargin(marginHint()); + QGridLayout* nicknameLayout = new QGridLayout(nicknameGBox->layout(), 1, 2, spacingHint()); + + m_nicknameLBox = new QListBox(nicknameGBox); + QWhatsThis::add(m_nicknameLBox, i18n("This is your list of nicknames. A nickname is the name that other users will know you by. You may use any name you desire. The first character must be a letter.\n\nSince nicknames must be unique across an entire IRC network, your desired name may be rejected by the server because someone else is already using that nickname. Enter alternate nicknames for yourself. If your first choice is rejected by the server, Konversation will try the alternate nicknames.")); + m_addNicknameBtn = new QPushButton(i18n("Add..."), nicknameGBox); + m_changeNicknameBtn = new QPushButton(i18n("Edit..."), nicknameGBox); + m_changeNicknameBtn->setEnabled(false); + m_removeNicknameBtn = new QPushButton(i18n("Delete"), nicknameGBox); + m_removeNicknameBtn->setEnabled(false); + m_upNicknameBtn = new QToolButton(nicknameGBox); + m_upNicknameBtn->setIconSet(SmallIconSet("up")); + m_upNicknameBtn->setAutoRepeat(true); + m_upNicknameBtn->setEnabled(false); + m_downNicknameBtn = new QToolButton(nicknameGBox); + m_downNicknameBtn->setIconSet(SmallIconSet("down")); + m_downNicknameBtn->setAutoRepeat(true); + m_downNicknameBtn->setEnabled(false); + + connect(m_addNicknameBtn, SIGNAL(clicked()), this, SLOT(addNickname())); + connect(m_changeNicknameBtn, SIGNAL(clicked()), this, SLOT(editNickname())); + connect(m_removeNicknameBtn, SIGNAL(clicked()), this, SLOT(deleteNickname())); + connect(m_nicknameLBox, SIGNAL(selectionChanged()), this, SLOT(updateButtons())); + connect(m_upNicknameBtn, SIGNAL(clicked()), this, SLOT(moveNicknameUp())); + connect(m_downNicknameBtn, SIGNAL(clicked()), this, SLOT(moveNicknameDown())); + + nicknameLayout->setColStretch(0, 10); + nicknameLayout->setRowStretch(4, 10); + nicknameLayout->addMultiCellWidget(m_nicknameLBox, 0, 4, 0, 0); + nicknameLayout->addMultiCellWidget(m_addNicknameBtn, 0, 0, 1, 4); + nicknameLayout->addMultiCellWidget(m_changeNicknameBtn, 1, 1, 1, 4); + nicknameLayout->addMultiCellWidget(m_removeNicknameBtn, 2, 2, 1, 4); + nicknameLayout->addWidget(m_upNicknameBtn, 3, 2); + nicknameLayout->addWidget(m_downNicknameBtn, 3, 3); + + QGroupBox* autoIdentifyGBox = new QGroupBox(0, Qt::Horizontal, i18n("Auto Identify"), generalWidget); + autoIdentifyGBox->setMargin(marginHint()); + QGridLayout* autoIdentifyLayout = new QGridLayout(autoIdentifyGBox->layout(), 1, 2, spacingHint()); + + QLabel* botLabel=new QLabel(i18n("Ser&vice:"), autoIdentifyGBox); + QWhatsThis::add(botLabel,i18n("Service name can be nickserv or a network dependant name like nickserv@services.dal.net")); + m_botEdit = new KLineEdit(autoIdentifyGBox); + botLabel->setBuddy(m_botEdit); + + QLabel* passwordLabel = new QLabel(i18n("Pa&ssword:"), autoIdentifyGBox); + m_passwordEdit = new KLineEdit(autoIdentifyGBox); + m_passwordEdit->setEchoMode(QLineEdit::Password); + passwordLabel->setBuddy(m_passwordEdit); + + autoIdentifyLayout->addWidget(botLabel, 0, 0); + autoIdentifyLayout->addWidget(m_botEdit, 0, 1); + autoIdentifyLayout->addWidget(passwordLabel, 0, 2); + autoIdentifyLayout->addWidget(m_passwordEdit, 0, 3); + + int row = 0; + generalLayout->addWidget(realNameLabel, row, 0); + generalLayout->addWidget(m_realNameEdit, row, 1); + row++; + generalLayout->addMultiCellWidget(nicknameGBox, row, row, 0, 1); + row++; + generalLayout->addMultiCellWidget(autoIdentifyGBox, row, row, 0, 1); + + QWidget* awayWidget = new QWidget(tabWidget); + tabWidget->addTab(awayWidget, i18n("Tab name", "Away")); + QGridLayout* awayLayout = new QGridLayout(awayWidget, 1, 2, marginHint(), spacingHint()); + + m_insertRememberLineOnAwayChBox = new QCheckBox(i18n("Mark the last position in chat windows when going away"), awayWidget); + QWhatsThis::add(m_insertRememberLineOnAwayChBox, i18n("If you check this box, whenever you perform an /away command, a horizontal line will appear in the channel, marking the point where you went away. Other IRC users do not see this horizontal line.")); + + QLabel* awayNickLabel = new QLabel(i18n("Away nickname:"), awayWidget); + m_awayNickEdit = new KLineEdit(awayWidget); + QWhatsThis::add(m_awayNickEdit, i18n("Enter a nickname that indicates you are away. Whenever you perform an /away msg command in any channel joined with this Identity, Konversation will automatically change your nickname to the Away nickname. Other users will be able to tell you are away from your computer. Whenever you perform an /away command in any channel in which you are away, Konversation will automatically change your nickname back to the original. If you do not wish to automatically change your nickname when going away, leave blank.")); + awayNickLabel->setBuddy(m_awayNickEdit); + + m_automaticAwayGBox = new QGroupBox(i18n("Automatic Away"), awayWidget); + m_automaticAwayGBox->setCheckable(true); + m_automaticAwayGBox->setColumnLayout(0, Qt::Horizontal); + m_automaticAwayGBox->setMargin(marginHint()); + QGridLayout* automaticAwayLayout = new QGridLayout(m_automaticAwayGBox->layout(), 1, 2, spacingHint()); + + QWhatsThis::add(m_automaticAwayGBox, i18n("If you check this box, Konversation will automatically set all connections using this Identity away when the screensaver starts or after a period of user inactivity configured below.")); + + QLabel* autoAwayLabel1 = new QLabel(i18n("Set away after"), m_automaticAwayGBox); + m_awayInactivitySpin = new QSpinBox(1, 999, 1, m_automaticAwayGBox); + m_awayInactivitySpin->setSuffix(i18n(" minutes")); + QLabel* autoAwayLabel2 = new QLabel(i18n("of user inactivity"), m_automaticAwayGBox); + autoAwayLabel1->setBuddy(m_awayInactivitySpin); + autoAwayLabel2->setBuddy(m_awayInactivitySpin); + m_automaticUnawayChBox = new QCheckBox(i18n("Automatically return on activity"), m_automaticAwayGBox); + QWhatsThis::add(m_automaticUnawayChBox, i18n("If you check this box, Konversation will automatically cancel away for all connections using this Identity when the screensaver stops or new user activity is detected.")); + + connect(m_automaticAwayGBox, SIGNAL(toggled(bool)), autoAwayLabel1, SLOT(setEnabled(bool))); + connect(m_automaticAwayGBox, SIGNAL(toggled(bool)), autoAwayLabel2, SLOT(setEnabled(bool))); + connect(m_automaticAwayGBox, SIGNAL(toggled(bool)), m_awayInactivitySpin, SLOT(setEnabled(bool))); + connect(m_automaticAwayGBox, SIGNAL(toggled(bool)), m_automaticUnawayChBox, SLOT(setEnabled(bool))); + + row = 0; + automaticAwayLayout->addWidget(autoAwayLabel1, row, 0); + automaticAwayLayout->addWidget(m_awayInactivitySpin, row, 1); + automaticAwayLayout->addWidget(autoAwayLabel2, row, 2); + QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + automaticAwayLayout->addItem(spacer, row, 3); + row++; + automaticAwayLayout->addMultiCellWidget(m_automaticUnawayChBox, row, row, 0, 3); + + m_awayMessageGBox = new QGroupBox(i18n("Away Messages"), awayWidget); + m_awayMessageGBox->setCheckable(true); + m_awayMessageGBox->setColumnLayout(0, Qt::Horizontal); + m_awayMessageGBox->setMargin(marginHint()); + QGridLayout* messagesLayout = new QGridLayout(m_awayMessageGBox->layout(), 1, 2, spacingHint()); + + QWhatsThis::add(m_awayMessageGBox, i18n("If you check this box, Konversation will automatically send the Away message to all channels joined with this Identity. %s is replaced with msg. Whenever you perform an /away command, the Return message will be displayed in all channels joined with this Identity.")); + + QLabel* awayLabel = new QLabel(i18n("Away &message:"), m_awayMessageGBox); + m_awayEdit = new KLineEdit(m_awayMessageGBox); + awayLabel->setBuddy(m_awayEdit); + + QLabel* unAwayLabel = new QLabel(i18n("Re&turn message:"), m_awayMessageGBox); + m_unAwayEdit = new KLineEdit(m_awayMessageGBox); + unAwayLabel->setBuddy(m_unAwayEdit); + + connect(m_awayMessageGBox, SIGNAL(toggled(bool)), awayLabel, SLOT(setEnabled(bool))); + connect(m_awayMessageGBox, SIGNAL(toggled(bool)), m_awayEdit, SLOT(setEnabled(bool))); + connect(m_awayMessageGBox, SIGNAL(toggled(bool)), unAwayLabel, SLOT(setEnabled(bool))); + connect(m_awayMessageGBox, SIGNAL(toggled(bool)), m_unAwayEdit, SLOT(setEnabled(bool))); + + row = 0; + messagesLayout->addWidget(awayLabel, row, 0); + messagesLayout->addWidget(m_awayEdit, row, 1); + row++; + messagesLayout->addWidget(unAwayLabel, row, 0); + messagesLayout->addWidget(m_unAwayEdit, row, 1); + + row = 0; + awayLayout->addMultiCellWidget(m_insertRememberLineOnAwayChBox, row, row, 0, 1); + row++; + awayLayout->addWidget(awayNickLabel, row, 0); + awayLayout->addWidget(m_awayNickEdit, row, 1); + row++; + awayLayout->addMultiCellWidget(m_automaticAwayGBox, row, row, 0, 1); + row++; + awayLayout->addMultiCellWidget(m_awayMessageGBox, row, row, 0, 1); + row++; + awayLayout->setRowStretch(row, 10); + + QWidget* advancedWidget = new QWidget(tabWidget); + tabWidget->addTab(advancedWidget, i18n("Advanced")); + QGridLayout* advancedLayout = new QGridLayout(advancedWidget, 1, 2, marginHint(), spacingHint()); + + QLabel* commandLabel = new QLabel(i18n("&Pre-shell command:"), advancedWidget); + m_sCommandEdit = new KLineEdit(advancedWidget); + QWhatsThis::add(m_sCommandEdit,i18n("Here you can enter a command to be executed before connection to server starts
If you have multiple servers in this identity this command will be executed for each server")); + commandLabel->setBuddy(m_sCommandEdit); + + QLabel* loginLabel = new QLabel(i18n("I&dent:"), advancedWidget); + m_loginEdit = new KLineEdit(advancedWidget); + QWhatsThis::add(m_loginEdit, i18n("When you connect, many servers query your computer for an IDENT response. If you computer is not running an IDENT server, this response is sent by Konversation. No spaces are allowed.")); + loginLabel->setBuddy(m_loginEdit); + + // encoding combo box + QLabel* codecLabel = new QLabel(i18n("&Encoding:"), advancedWidget); + m_codecCBox = new KComboBox(advancedWidget,"codec_combo_box"); + QWhatsThis::add(m_codecCBox, i18n("This setting affects how characters you type are encoded for sending to the server. It also affects how messages are displayed. When you first open Konversation, it automatically retrieves this setting from the operating system. If you seem to be having trouble seeing other user's messages correctly, try changing this setting.")); + codecLabel->setBuddy(m_codecCBox); + // add encodings to combo box + m_codecCBox->insertStringList(Konversation::IRCCharsets::self()->availableEncodingDescriptiveNames()); + + QLabel* quitLabel = new QLabel(i18n("&Quit reason:"), advancedWidget); + m_quitEdit = new KLineEdit(advancedWidget); + QWhatsThis::add(m_quitEdit, i18n("Whenever you leave a server, this message is shown to others.")); + quitLabel->setBuddy(m_quitEdit); + + QLabel* partLabel = new QLabel(i18n("&Part reason:"), advancedWidget); + m_partEdit = new KLineEdit(advancedWidget); + QWhatsThis::add(m_partEdit, i18n("Whenever you leave a channel, this message is sent to the channel.")); + partLabel->setBuddy(m_partEdit); + + QLabel* kickLabel = new QLabel(i18n("&Kick reason:"), advancedWidget); + m_kickEdit = new KLineEdit(advancedWidget); + QWhatsThis::add(m_kickEdit, i18n("Whenever you are kicked from a channel (usually by an IRC operator), this message is sent to the channel.")); + kickLabel->setBuddy(m_kickEdit); + + row = 0; + advancedLayout->addWidget(commandLabel,row,0); + advancedLayout->addWidget(m_sCommandEdit, row, 1); + row++; + advancedLayout->addWidget(codecLabel,row,0); + advancedLayout->addWidget(m_codecCBox, row, 1); + row++; + advancedLayout->addWidget(loginLabel,row,0); + advancedLayout->addWidget(m_loginEdit, row, 1); + row++; + advancedLayout->addWidget(quitLabel, row, 0); + advancedLayout->addWidget(m_quitEdit, row, 1); + row++; + advancedLayout->addWidget(partLabel, row, 0); + advancedLayout->addWidget(m_partEdit, row, 1); + row++; + advancedLayout->addWidget(kickLabel, row, 0); + advancedLayout->addWidget(m_kickEdit, row, 1); + row++; + advancedLayout->setRowStretch(row, 10); + + row = 0; + mainLayout->addWidget(identityLabel, row, 0); + mainLayout->addMultiCellWidget(m_identityCBox, row, row, 1, 2); + mainLayout->addWidget(newBtn, row, 3); + mainLayout->addWidget(copyBtn, row, 4); + mainLayout->addWidget(m_editBtn, row, 5); + mainLayout->addWidget(m_delBtn, row, 6); + mainLayout->setColStretch(1, 10); + row++; + mainLayout->addMultiCellWidget(tabWidget, row, row, 0, 6); + + // set values for the widgets + updateIdentity(0); + + // Set up signals / slots for identity page + connect(m_identityCBox, SIGNAL(activated(int)), this, SLOT(updateIdentity(int))); + + setButtonOK(KGuiItem(i18n("&OK"), "button_ok", i18n("Change identity information"))); + setButtonCancel(KGuiItem(i18n("&Cancel"), "button_cancel", i18n("Discards all changes made"))); + + AwayManager* awayManager = static_cast(kapp)->getAwayManager(); + connect(this, SIGNAL(identitiesChanged()), awayManager, SLOT(identitiesChanged())); + } + + IdentityDialog::~IdentityDialog() + { + } + + void IdentityDialog::updateIdentity(int index) + { + if(m_currentIdentity && (m_nicknameLBox->count() == 0)) + { + KMessageBox::error(this, i18n("You must add at least one nick to the identity.")); + m_identityCBox->setCurrentText(m_currentIdentity->getName()); + return; + } + + if (isShown() && m_currentIdentity && m_realNameEdit->text().isEmpty()) + { + KMessageBox::error(this, i18n("Please enter a real name.")); + m_identityCBox->setCurrentText(m_currentIdentity->getName()); + return; + } + + refreshCurrentIdentity(); + + m_currentIdentity = m_identityList[index]; + + m_realNameEdit->setText(m_currentIdentity->getRealName()); + m_nicknameLBox->clear(); + m_nicknameLBox->insertStringList(m_currentIdentity->getNicknameList()); + m_botEdit->setText(m_currentIdentity->getBot()); + m_passwordEdit->setText(m_currentIdentity->getPassword()); + + m_insertRememberLineOnAwayChBox->setChecked(m_currentIdentity->getInsertRememberLineOnAway()); + m_awayNickEdit->setText(m_currentIdentity->getAwayNick()); + m_awayMessageGBox->setChecked(m_currentIdentity->getShowAwayMessage()); + m_awayEdit->setText(m_currentIdentity->getAwayMessage()); + m_unAwayEdit->setText(m_currentIdentity->getReturnMessage()); + m_automaticAwayGBox->setChecked(m_currentIdentity->getAutomaticAway()); + m_awayInactivitySpin->setValue(m_currentIdentity->getAwayInactivity()); + m_automaticUnawayChBox->setChecked(m_currentIdentity->getAutomaticUnaway()); + + m_sCommandEdit->setText(m_currentIdentity->getShellCommand()); + m_codecCBox->setCurrentItem(Konversation::IRCCharsets::self()->shortNameToIndex(m_currentIdentity->getCodecName())); + m_loginEdit->setText(m_currentIdentity->getIdent()); + m_quitEdit->setText(m_currentIdentity->getQuitReason()); + m_partEdit->setText(m_currentIdentity->getPartReason()); + m_kickEdit->setText(m_currentIdentity->getKickReason()); + + if(index == 0) + { + m_editBtn->setEnabled(false); + m_delBtn->setEnabled(false); + } + else + { + m_editBtn->setEnabled(true); + m_delBtn->setEnabled(true); + } + } + + void IdentityDialog::addNickname() + { + bool ok = false; + QString txt = KInputDialog::getText(i18n("Add Nickname"), i18n("Nickname:"), QString(), &ok, this); + + if(ok && !txt.isEmpty()) + { + m_nicknameLBox->insertItem(txt); + updateButtons(); + } + } + + void IdentityDialog::editNickname() + { + bool ok = false; + QString txt = KInputDialog::getText(i18n("Edit Nickname"), i18n("Nickname:"), m_nicknameLBox->currentText(), &ok, this); + + if(ok && !txt.isEmpty()) + { + m_nicknameLBox->changeItem(txt, m_nicknameLBox->currentItem()); + } + } + + void IdentityDialog::deleteNickname() + { + m_nicknameLBox->removeItem(m_nicknameLBox->currentItem()); + updateButtons(); + } + + void IdentityDialog::updateButtons() + { + m_changeNicknameBtn->setEnabled(m_nicknameLBox->selectedItem()); + m_removeNicknameBtn->setEnabled(m_nicknameLBox->selectedItem()); + + m_upNicknameBtn->setEnabled(m_nicknameLBox->selectedItem() && m_nicknameLBox->count()>1 + && m_nicknameLBox->currentItem()>0); + + m_downNicknameBtn->setEnabled(m_nicknameLBox->selectedItem() && m_nicknameLBox->count()>1 + && m_nicknameLBox->currentItem()numRows()-1 ); + + } + + void IdentityDialog::moveNicknameUp() + { + uint current = m_nicknameLBox->currentItem(); + + if(current > 0) + { + QString txt = m_nicknameLBox->text(current); + m_nicknameLBox->removeItem(current); + m_nicknameLBox->insertItem(txt, current - 1); + m_nicknameLBox->setCurrentItem(current - 1); + } + + updateButtons(); + } + + void IdentityDialog::moveNicknameDown() + { + uint current = m_nicknameLBox->currentItem(); + + if(current < (m_nicknameLBox->count() - 1)) + { + QString txt = m_nicknameLBox->text(current); + m_nicknameLBox->removeItem(current); + m_nicknameLBox->insertItem(txt, current + 1); + m_nicknameLBox->setCurrentItem(current + 1); + } + + updateButtons(); + } + + void IdentityDialog::refreshCurrentIdentity() + { + if(!m_currentIdentity) + { + return; + } + + m_currentIdentity->setRealName(m_realNameEdit->text()); + QStringList nicks; + + for(unsigned int i = 0; i < m_nicknameLBox->count(); ++i) + { + nicks.append(m_nicknameLBox->text(i)); + } + + m_currentIdentity->setNicknameList(nicks); + m_currentIdentity->setBot(m_botEdit->text()); + m_currentIdentity->setPassword(m_passwordEdit->text()); + + m_currentIdentity->setInsertRememberLineOnAway(m_insertRememberLineOnAwayChBox->isChecked()); + m_currentIdentity->setAwayNick(m_awayNickEdit->text()); + m_currentIdentity->setShowAwayMessage(m_awayMessageGBox->isChecked()); + m_currentIdentity->setAwayMessage(m_awayEdit->text()); + m_currentIdentity->setReturnMessage(m_unAwayEdit->text()); + m_currentIdentity->setAutomaticAway(m_automaticAwayGBox->isChecked()); + m_currentIdentity->setAwayInactivity(m_awayInactivitySpin->value()); + m_currentIdentity->setAutomaticUnaway(m_automaticUnawayChBox->isChecked()); + + m_currentIdentity->setShellCommand(m_sCommandEdit->text()); + m_currentIdentity->setCodecName(Konversation::IRCCharsets::self()->availableEncodingShortNames()[m_codecCBox->currentItem()]); + m_currentIdentity->setIdent(m_loginEdit->text()); + m_currentIdentity->setQuitReason(m_quitEdit->text()); + m_currentIdentity->setPartReason(m_partEdit->text()); + m_currentIdentity->setKickReason(m_kickEdit->text()); + } + + void IdentityDialog::slotOk() + { + if(m_nicknameLBox->count() == 0) + { + KMessageBox::error(this, i18n("You must add at least one nick to the identity.")); + m_identityCBox->setCurrentText(m_currentIdentity->getName()); + return; + } + + if(m_realNameEdit->text().isEmpty()) + { + KMessageBox::error(this, i18n("Please enter a real name.")); + m_identityCBox->setCurrentText(m_currentIdentity->getName()); + return; + } + + refreshCurrentIdentity(); + Preferences::setIdentityList(m_identityList); + static_cast(kapp)->saveOptions(true); + emit identitiesChanged(); + accept(); + } + + void IdentityDialog::newIdentity() + { + bool ok = false; + QString txt = KInputDialog::getText(i18n("Add Identity"), i18n("Identity name:"), QString(), &ok, this); + + if(ok && !txt.isEmpty()) + { + KUser user(KUser::UseRealUserID); + IdentityPtr identity = new Identity; + identity->setName(txt); + identity->setIdent(user.loginName()); + m_identityList.append(identity); + m_identityCBox->insertItem(txt); + m_identityCBox->setCurrentItem(m_identityCBox->count() - 1); + updateIdentity(m_identityCBox->currentItem()); + } + else if(ok && txt.isEmpty()) + { + KMessageBox::error(this, i18n("You need to give the identity a name.")); + newIdentity(); + } + updateButtons(); + } + + void IdentityDialog::renameIdentity() + { + bool ok = false; + QString currentTxt = m_identityCBox->currentText(); + QString txt = KInputDialog::getText(i18n("Rename Identity"), i18n("Identity name:"), currentTxt, &ok, this); + + if(ok && !txt.isEmpty()) + { + m_currentIdentity->setName(txt); + m_identityCBox->changeItem(txt, m_identityCBox->currentItem()); + } + else if(ok && txt.isEmpty()) + { + KMessageBox::error(this, i18n("You need to give the identity a name.")); + renameIdentity(); + } + } + + void IdentityDialog::deleteIdentity() + { + int current = m_identityCBox->currentItem(); + + if(current <= 0) + { + return; + } + + ServerGroupList serverGroups = Preferences::serverGroupList(); + ServerGroupList::iterator it = serverGroups.begin(); + bool found = false; + + while((it != serverGroups.end()) && !found) + { + if((*it)->identityId() == m_currentIdentity->id()) + { + found = true; + } + + ++it; + } + + QString warningTxt; + + if(found) + { + warningTxt = i18n("This identity is in use, if you remove it the network settings using it will" + " fall back to the default identity. Should it be deleted anyway?"); + } + else + { + warningTxt = i18n("Are you sure you want to delete all information for this identity?"); + } + + if(KMessageBox::warningContinueCancel(this, warningTxt, i18n("Delete Identity"), + KGuiItem(i18n("Delete"), "editdelete")) == KMessageBox::Continue) + { + m_identityCBox->removeItem(current); + m_identityList.remove(m_currentIdentity); + m_currentIdentity = 0; + updateIdentity(m_identityCBox->currentItem()); + updateButtons(); + } + } + + void IdentityDialog::copyIdentity() + { + bool ok = false; + QString currentTxt = m_identityCBox->currentText(); + QString txt = KInputDialog::getText(i18n("Duplicate Identity"), i18n("Identity name:"), currentTxt, &ok, this); + + if(ok && !txt.isEmpty()) + { + IdentityPtr identity = new Identity; + identity->copy(*m_currentIdentity); + identity->setName(txt); + m_identityList.append(identity); + m_identityCBox->insertItem(txt); + m_identityCBox->setCurrentItem(m_identityCBox->count() - 1); + updateIdentity(m_identityCBox->currentItem()); + } + else if(ok && txt.isEmpty()) + { + KMessageBox::error(this, i18n("You need to give the identity a name.")); + renameIdentity(); + } + } + + void IdentityDialog::setCurrentIdentity(int index) + { + if (index >= m_identityCBox->count()) + index = 0; + + m_identityCBox->setCurrentItem(index); + updateIdentity(index); + } + + IdentityPtr IdentityDialog::setCurrentIdentity(IdentityPtr identity) + { + int index = Preferences::identityList().findIndex(identity); + setCurrentIdentity(index); + + return m_currentIdentity; + } + + IdentityPtr IdentityDialog::currentIdentity() const + { + return m_currentIdentity; + } +} + +#include "identitydialog.moc" diff --git a/konversation/src/identitydialog.h b/konversation/src/identitydialog.h new file mode 100644 index 0000000..e58438f --- /dev/null +++ b/konversation/src/identitydialog.h @@ -0,0 +1,99 @@ +/* + 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. +*/ + +/* + copyright: (C) 2004 by Peter Simonsson + email: psn@linux.se +*/ +#ifndef KONVERSATIONIDENTITYDIALOG_H +#define KONVERSATIONIDENTITYDIALOG_H + +#include "identity.h" + +#include + + +class KComboBox; +class KLineEdit; +class QCheckBox; +class QSpinBox; +class QListBox; +class QGroupBox; +class QToolButton; + +namespace Konversation +{ + + class IdentityDialog : public KDialogBase + { + Q_OBJECT + public: + explicit IdentityDialog(QWidget *parent = 0, const char *name = 0); + ~IdentityDialog(); + void setCurrentIdentity(int index); + IdentityPtr setCurrentIdentity(IdentityPtr identity); + IdentityPtr currentIdentity() const; + + + signals: + void identitiesChanged(); + + + protected slots: + void updateIdentity(int index); + + void addNickname(); + void editNickname(); + void deleteNickname(); + void updateButtons(); + void moveNicknameUp(); + void moveNicknameDown(); + + void refreshCurrentIdentity(); + + void slotOk(); + + void newIdentity(); + void renameIdentity(); + void deleteIdentity(); + void copyIdentity(); + + + private: + KComboBox* m_identityCBox; + KLineEdit* m_realNameEdit; + KLineEdit* m_sCommandEdit; + KLineEdit* m_loginEdit; + KComboBox* m_codecCBox; + KLineEdit* m_botEdit; + KLineEdit* m_passwordEdit; + KLineEdit* m_quitEdit; + KLineEdit* m_partEdit; + KLineEdit* m_kickEdit; + KLineEdit* m_awayEdit; + KLineEdit* m_unAwayEdit; + KLineEdit* m_awayNickEdit; + QCheckBox* m_insertRememberLineOnAwayChBox; + QListBox* m_nicknameLBox; + QGroupBox* m_awayMessageGBox; + QGroupBox* m_automaticAwayGBox; + QSpinBox* m_awayInactivitySpin; + QCheckBox* m_automaticUnawayChBox; + QToolButton* m_editBtn; + QToolButton* m_delBtn; + QToolButton* m_upNicknameBtn; + QToolButton* m_downNicknameBtn; + QPushButton* m_addNicknameBtn; + QPushButton* m_changeNicknameBtn; + QPushButton* m_removeNicknameBtn; + + IdentityList m_identityList; + IdentityPtr m_currentIdentity; + }; + +} +#endif diff --git a/konversation/src/ignore.cpp b/konversation/src/ignore.cpp new file mode 100644 index 0000000..8ff8304 --- /dev/null +++ b/konversation/src/ignore.cpp @@ -0,0 +1,30 @@ +/* + 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. +*/ + +/* + begin: Mon Jun 24 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include "ignore.h" + + +Ignore::Ignore(const QString &newName,int newFlags) +{ + setFlags(newFlags); + setName(newName); +} + +Ignore::~Ignore() +{ +} + +void Ignore::setName(const QString &newName) { name=newName; } +void Ignore::setFlags(int newFlags) { flags=newFlags; } +QString Ignore::getName() { return name; } +int Ignore::getFlags() { return flags; } diff --git a/konversation/src/ignore.h b/konversation/src/ignore.h new file mode 100644 index 0000000..ec64c9c --- /dev/null +++ b/konversation/src/ignore.h @@ -0,0 +1,46 @@ +/* + 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. +*/ + +/* + begin: Mon Jun 24 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#ifndef IGNORE_H +#define IGNORE_H + +#include + + +class Ignore +{ + public: + enum Type + { + Channel=1, + Query=2, + Notice=4, + CTCP=8, + DCC=16, + Exception=32, + All=31 + }; + + Ignore(const QString &name,int flags); + ~Ignore(); + + void setName(const QString &newName); + void setFlags(int newFlags); + QString getName(); + int getFlags(); + + protected: + QString name; + int flags; +}; +#endif diff --git a/konversation/src/ignore_preferences.cpp b/konversation/src/ignore_preferences.cpp new file mode 100644 index 0000000..825cfb7 --- /dev/null +++ b/konversation/src/ignore_preferences.cpp @@ -0,0 +1,219 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006 John Tapsell +*/ + +#include "ignore_preferences.h" +#include "ignorelistviewitem.h" +#include "ignore.h" +#include "preferences.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +Ignore_Config::Ignore_Config( QWidget* parent, const char* name, WFlags fl ) + : Ignore_ConfigUI( parent, name, fl ) +{ + connect(newButton,SIGNAL(clicked()), + this,SLOT(newIgnore())); + connect(removeButton,SIGNAL(clicked()), + this,SLOT(removeIgnore())); + connect(removeAllButton,SIGNAL(clicked()), + this,SLOT(removeAllIgnore())); + connect(ignoreListView,SIGNAL(selectionChanged(QListViewItem*)), + this,SLOT(select(QListViewItem*))); + connect(chkChannel, SIGNAL(clicked()), this, SLOT(flagCheckboxChanged())); + connect(chkQuery, SIGNAL(clicked()), this, SLOT(flagCheckboxChanged())); + connect(chkNotice, SIGNAL(clicked()), this, SLOT(flagCheckboxChanged())); + connect(chkCTCP, SIGNAL(clicked()), this, SLOT(flagCheckboxChanged())); + connect(chkDCC, SIGNAL(clicked()), this, SLOT(flagCheckboxChanged())); + connect(txtPattern, SIGNAL(textChanged(const QString &)), this, SLOT(flagCheckboxChanged())); +// connect(chkException, SIGNAL(clicked()), this, SLOT(flagCheckboxChanged())); + loadSettings(); + + ignoreListView->header()->setMovingEnabled(false); +} + +Ignore_Config::~Ignore_Config() +{ + +} + +void Ignore_Config::newIgnore() +{ + ignoreListView->setSelected(new IgnoreListViewItem(ignoreListView, + "new!new@new.new", + Ignore::Channel | + Ignore::Query | + Ignore::Notice | + Ignore::CTCP | + Ignore::DCC), true); + txtPattern->setFocus(); + txtPattern->selectAll(); + + updateEnabledness(); + emit modified(); +} +void Ignore_Config::removeAllIgnore() +{ + ignoreListView->clear(); + updateEnabledness(); + emit modified(); +} +void Ignore_Config::removeIgnore() +{ + delete ignoreListView->selectedItem(); + updateEnabledness(); + emit modified(); +} + +QPtrList Ignore_Config::getIgnoreList() +{ + QPtrList newList; + + IgnoreListViewItem* item=static_cast(ignoreListView->firstChild()); + while(item) + { + Ignore* newItem=new Ignore(item->text(0),item->getFlags()); + newList.append(newItem); + item=item->itemBelow(); + } + + return newList; +} + +// returns the currently visible ignore list as QStringList to make comparing easy +QStringList Ignore_Config::currentIgnoreList() +{ + QStringList newList; + + IgnoreListViewItem* item=static_cast(ignoreListView->firstChild()); + while(item) + { + newList.append(item->text(0)+' '+item->getFlags()); + item=item->itemBelow(); + } + + return newList; +} + +// checks if the currently visible ignore list differs from the currently saved one +bool Ignore_Config::hasChanged() +{ + return(m_oldIgnoreList!=currentIgnoreList()); +} + +void Ignore_Config::restorePageToDefaults() +{ + if(ignoreListView->childCount() != 0) { + ignoreListView->clear(); + updateEnabledness(); + emit modified(); + } +} +void Ignore_Config::saveSettings() +{ + Preferences::setIgnoreList(getIgnoreList()); + // remember the list for hasChanged() + m_oldIgnoreList=currentIgnoreList(); +} + +void Ignore_Config::loadSettings() +{ + QPtrList ignoreList=Preferences::ignoreList(); + // Insert Ignore items backwards to get them sorted properly + Ignore* item=ignoreList.last(); + ignoreListView->clear(); + while(item) + { + new IgnoreListViewItem(ignoreListView,item->getName(),item->getFlags()); + item=ignoreList.prev(); + } + // remember the list for hasChanged() + m_oldIgnoreList=currentIgnoreList(); + updateEnabledness(); +} + +void Ignore_Config::updateEnabledness() +{ + IgnoreListViewItem* selectedItem=static_cast(ignoreListView->selectedItem()); + + chkChannel->setEnabled(selectedItem != NULL); + chkQuery->setEnabled(selectedItem != NULL); + chkNotice->setEnabled(selectedItem != NULL); + chkCTCP->setEnabled(selectedItem != NULL); + chkDCC->setEnabled(selectedItem != NULL); +// chkExceptions->setEnabled(selectedItem != NULL); + txtPattern->setEnabled(selectedItem != NULL); + removeButton->setEnabled(selectedItem != NULL); + removeAllButton->setEnabled(ignoreListView->childCount() > 0); + +} + +void Ignore_Config::select(QListViewItem* item) +{ + updateEnabledness(); + // FIXME: Cast to IgnoreListViewItem, maybe derive from KListView some day + IgnoreListViewItem* selectedItem=static_cast(item); + + if(selectedItem) + { + int flags = selectedItem->getFlags(); + chkChannel->setChecked(flags & Ignore::Channel); + chkQuery->setChecked(flags & Ignore::Query); + chkNotice->setChecked(flags & Ignore::Notice); + chkCTCP->setChecked(flags & Ignore::CTCP); + chkDCC->setChecked(flags & Ignore::DCC); + txtPattern->blockSignals(true); + txtPattern->setText(selectedItem->getName()); + txtPattern->blockSignals(false); + +// chkExceptions->setChecked(flags & Ignore::Exception) ; + } +} + +void Ignore_Config::flagCheckboxChanged() +{ + int flags = 0; + if(chkChannel->isChecked()) flags |= Ignore::Channel; + if(chkQuery->isChecked()) flags |= Ignore::Query; + if(chkNotice->isChecked()) flags |= Ignore::Notice; + if(chkCTCP->isChecked()) flags |= Ignore::CTCP; + if(chkDCC->isChecked()) flags |= Ignore::DCC; + +// if(chkExceptions->isChecked()) flags |= Ignore::Exceptions; + IgnoreListViewItem* selectedItem=static_cast(ignoreListView->selectedItem()); + if(selectedItem) { + selectedItem->setFlags(flags); + selectedItem->setName(txtPattern->text()); + } + emit modified(); +} + +/* + * Sets the strings of the subwidgets using the current + * language. + */ +void Ignore_Config::languageChange() +{ + loadSettings(); +} + +#include "ignore_preferences.moc" diff --git a/konversation/src/ignore_preferences.h b/konversation/src/ignore_preferences.h new file mode 100644 index 0000000..2b90bce --- /dev/null +++ b/konversation/src/ignore_preferences.h @@ -0,0 +1,58 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006 John Tapsell +*/ + +#ifndef IGNORE_CONFIG_H +#define IGNORE_CONFIG_H + +#include "ignore_preferencesui.h" +#include "konvisettingspage.h" + +#include + + +class Ignore; +class Ignore_Config : public Ignore_ConfigUI, public KonviSettingsPage +{ + Q_OBJECT + + public: + explicit Ignore_Config( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~Ignore_Config(); + QString flagNames; + + virtual void restorePageToDefaults(); + virtual void saveSettings(); + virtual void loadSettings(); + + virtual bool hasChanged(); + + private: + QStringList m_oldIgnoreList; + + QStringList currentIgnoreList(); // in hasChanged() format + QPtrList getIgnoreList(); // in prefs format + void updateEnabledness(); + + public slots: + virtual void languageChange(); + + protected slots: + void newIgnore(); + void removeIgnore(); + void flagCheckboxChanged(); + void select(QListViewItem* item); + void removeAllIgnore(); + signals: + void modified(); +}; + +#endif // IGNORE_CONFIG_H diff --git a/konversation/src/ignore_preferencesui.ui b/konversation/src/ignore_preferencesui.ui new file mode 100644 index 0000000..bc33198 --- /dev/null +++ b/konversation/src/ignore_preferencesui.ui @@ -0,0 +1,219 @@ + +Ignore_ConfigUI +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. + +Copyright (C) 2005 Peter Simonsson + + + Ignore_ConfigUI + + + + 0 + 0 + 374 + 310 + + + + + 3 + 3 + 0 + 0 + + + + + 300 + 200 + + + + + unnamed + + + 0 + + + + + Pattern + + + true + + + true + + + + + Type + + + true + + + true + + + + ignoreListView + + + true + + + + + textLabel2 + + + Pattern: + + + + + txtPattern + + + + + grpMessageTypes + + + + 7 + 5 + 0 + 0 + + + + Message Types + + + + unnamed + + + + chkCTCP + + + CTCP + + + + + chkChannel + + + Channel + + + + + chkDCC + + + DCC + + + + + chkNotice + + + Notice + + + + + chkQuery + + + Query + + + + + + + layout20 + + + + unnamed + + + + newButton + + + &New + + + + + removeButton + + + &Remove + + + + + removeAllButton + + + Remove &All + + + + + spacer9 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + + + + ignoreListView + txtPattern + chkChannel + chkQuery + chkNotice + chkCTCP + chkDCC + newButton + removeButton + removeAllButton + + + + + klistview.h + kpushbutton.h + kpushbutton.h + kpushbutton.h + + diff --git a/konversation/src/ignorelistviewitem.cpp b/konversation/src/ignorelistviewitem.cpp new file mode 100644 index 0000000..c7ba20a --- /dev/null +++ b/konversation/src/ignorelistviewitem.cpp @@ -0,0 +1,55 @@ +/* + 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. +*/ + +/* + begin: Die Jun 25 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include "ignorelistviewitem.h" +#include "ignore.h" + +#include +#include + + +IgnoreListViewItem::IgnoreListViewItem(QListView* parent,const QString& name,int newFlags): +KListViewItem(parent,name) +{ + setFlags(newFlags); +} + +IgnoreListViewItem::~IgnoreListViewItem() +{ +} + +void IgnoreListViewItem::setFlag(int flag,bool active) +{ + if(active) m_flags|=flag; + else m_flags &= ~flag; //any bits that are set in flag will cause those bits in flags to be set to 0 + setFlags(m_flags); +} + +void IgnoreListViewItem::setFlags(int newFlags) +{ + m_flags=newFlags; + + QString flagsStr; + if(m_flags & Ignore::Channel) flagsStr += i18n("Channel") + ' '; + if(m_flags & Ignore::Query) flagsStr += i18n("Query") + ' '; + if(m_flags & Ignore::Notice) flagsStr += i18n("Notice") + ' '; + if(m_flags & Ignore::CTCP) flagsStr += i18n("CTCP") + ' '; + if(m_flags & Ignore::DCC) flagsStr += i18n("DCC") + ' '; + if(m_flags & Ignore::Exception) flagsStr += i18n("Exception") + ' '; + setText(1,flagsStr); +} + +IgnoreListViewItem* IgnoreListViewItem::itemBelow() +{ + return (IgnoreListViewItem*) QListViewItem::itemBelow(); +} diff --git a/konversation/src/ignorelistviewitem.h b/konversation/src/ignorelistviewitem.h new file mode 100644 index 0000000..c99242a --- /dev/null +++ b/konversation/src/ignorelistviewitem.h @@ -0,0 +1,39 @@ +/* + 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. +*/ + +/* + begin: Die Jun 25 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#ifndef IGNORELISTVIEWITEM_H +#define IGNORELISTVIEWITEM_H + +#include + +#include + + +class IgnoreListViewItem : public KListViewItem +{ + public: + IgnoreListViewItem(QListView* parent,const QString& name,int flags); + ~IgnoreListViewItem(); + + void setFlag(int flag,bool active); + bool getFlag(int flag) { return m_flags & flag; }; + QString getName() { return text(0); }; + void setName(QString name) { setText(0, name); }; + int getFlags() { return m_flags; }; + IgnoreListViewItem* itemBelow(); + + void setFlags(int flags); + protected: + int m_flags; +}; +#endif diff --git a/konversation/src/images.cpp b/konversation/src/images.cpp new file mode 100644 index 0000000..d97f9c7 --- /dev/null +++ b/konversation/src/images.cpp @@ -0,0 +1,319 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2005-2006 Eike Hein +*/ + +#include "images.h" +#include "common.h" +#include "konversationapplication.h" + +#include +#include +#include + +#include +#include +#include + + +using namespace Konversation; + +Images::Images() +{ + initializeLeds(); + initializeNickIcons(); + initializeKimifaceIcons(); + + m_closeIcon = KGlobal::iconLoader()->loadIcon("fileclose",KIcon::Small); + m_disabledCloseIcon = KGlobal::iconLoader()->loadIconSet("fileclose",KIcon::Small).pixmap(QIconSet::Small, false); +} + +Images::~Images() +{ +} + +QIconSet Images::getKimproxyAway() const { return kimproxyAway; } +QIconSet Images::getKimproxyOnline() const { return kimproxyOnline; } +QIconSet Images::getKimproxyOffline() const { return kimproxyOffline; } + +QPixmap Images::getNickIcon(NickPrivilege privilege,bool isAway) const +{ + return nickIcons[privilege][isAway?1:0]; +} + +void Images::initializeLeds() +{ + m_serverColor = "steelblue"; + m_systemColor = Preferences::tabNotificationsSystemColor(); + m_msgsColor = Preferences::tabNotificationsMsgsColor(); + m_privateColor = Preferences::tabNotificationsPrivateColor(); + m_eventsColor = Preferences::tabNotificationsEventsColor(); + m_nickColor = Preferences::tabNotificationsNickColor(); + m_highlightsColor = Preferences::tabNotificationsHighlightsColor(); + + // m_serverLedOn = getLed(m_serverColor,true); + m_serverLedOff = getLed(m_serverColor,false); + m_systemLedOn = getLed(m_systemColor,true); + m_systemLedOff = getLed(m_systemColor,false); + m_msgsLedOn = getLed(m_msgsColor,true); + m_msgsLedOff = getLed(m_msgsColor,false); + m_privateLedOn = getLed(m_privateColor,true); + m_privateLedOff = getLed(m_privateColor,false); + m_eventsLedOn = getLed(m_eventsColor,true); + m_nickLedOn = getLed(m_nickColor,true); + m_highlightsLedOn = getLed(m_highlightsColor,true); +} + +void Images::initializeKimifaceIcons() +{ + kimproxyAway = KGlobal::iconLoader()->loadIconSet("kimproxyaway",KIcon::Small); + kimproxyOnline = KGlobal::iconLoader()->loadIconSet("kimproxyonline",KIcon::Small); + kimproxyOffline = KGlobal::iconLoader()->loadIconSet("kimproxyoffline",KIcon::Small); +} + +// NickIcons + +void Images::initializeNickIcons() +{ + + QString iconTheme = Preferences::iconTheme(); + QStringList icons = KGlobal::dirs()->findAllResources("data","konversation/themes/"+iconTheme+"/*.png"); + + if( icons.count() < 7 ) // Sanity + icons = KGlobal::dirs()->findAllResources("data","konversation/themes/default/*.png"); + + icons.sort(); + QStringList::ConstIterator it = icons.begin(); + + /* The list is sorted alphabetically. */ + + QPixmap elementAdmin(*it); + ++it; + QPixmap elementAway(*it); + ++it; + QPixmap elementHalfOp(*it); + ++it; + QPixmap elementNormal(*it); + ++it; + QPixmap elementOp(*it); + ++it; + QPixmap elementOwner(*it); + ++it; + QPixmap elementVoice(*it); + + nickIcons[Normal][0] = elementNormal; + nickIcons[Normal][1] = overlayPixmaps( nickIcons[Normal][0], elementAway ); + + nickIcons[Voice][0] = overlayPixmaps( elementNormal, elementVoice ); + nickIcons[Voice][1] = overlayPixmaps( nickIcons[Voice][0], elementAway ); + + nickIcons[HalfOp][0] = overlayPixmaps( elementNormal, elementHalfOp ); + nickIcons[HalfOp][1] = overlayPixmaps( nickIcons[HalfOp][0], elementAway ); + + nickIcons[Op][0] = overlayPixmaps( elementNormal, elementOp ); + nickIcons[Op][1] = overlayPixmaps( nickIcons[Op][0], elementAway ); + + nickIcons[Owner][0] = overlayPixmaps( elementNormal, elementOwner ); + nickIcons[Owner][1] = overlayPixmaps( nickIcons[Owner][0], elementAway ); + + nickIcons[Admin][0] = overlayPixmaps( elementNormal, elementAdmin ); + nickIcons[Admin][1] = overlayPixmaps( nickIcons[Admin][0], elementAway ); + + /* + // why doesn't it work? + nickIcons[Op][0] = elementNormal; + bitBlt( &nickIcons[Op][0], 0, 0, &elementOp, 0, 0, -1, -1, Qt::CopyROP ); + nickIcons[Op][1] = nickIcons[Op][0]; + bitBlt( &nickIcons[Op][1], 0, 0, &elementAway, 0, 0, -1, -1, Qt::CopyROP ); + */ +} + +void Images::updateIcons() +{ + m_closeIcon = KGlobal::iconLoader()->loadIcon("fileclose",KIcon::Small); + m_disabledCloseIcon = KGlobal::iconLoader()->loadIconSet("fileclose",KIcon::Small).pixmap(QIconSet::Small, false); +} + +QIconSet Images::getLed(QColor col,bool state) +{ + QColor color; + QPainter paint; + QBrush brush; + QPen pen; + + if (state==false) + color = col.dark(180); + else + color = col; + + int scale = 3; + int width = 12 * scale; + + QPixmap *tmpMap = 0; + + tmpMap = new QPixmap(width + 6, width + 6); + QWidget tmpWidget; + tmpMap->fill(tmpWidget.paletteBackgroundColor()); + paint.begin(tmpMap); + + // Set the brush to SolidPattern, this fills the entire area + // of the ellipse which is drawn first + brush.setStyle( QBrush::SolidPattern ); + brush.setColor( color ); + paint.setBrush( brush ); + + // Draw a "flat" LED with the given color + paint.drawEllipse( scale, scale, width - scale*2, width - scale*2 ); + + // Setting the new width of the pen is essential to avoid "pixelized" + // shadow like it can be observed with the old LED code + pen.setWidth( 2 * scale ); + + // shrink the light on the LED to a size about 2/3 of the complete LED + int pos = width/5 + 1; + int light_width = width; + light_width *= 2; + light_width /= 3; + + // Calculate the LEDs "light factor" + int light_quote = (130*2/(light_width?light_width:1))+100; + + // Draw the bright spot on the LED + while (light_width) + { + color = color.light( light_quote ); // make color lighter + pen.setColor( color ); // set color as pen color + paint.setPen( pen ); // select the pen for drawing + paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle) + light_width--; + if (!light_width) + break; + paint.drawEllipse( pos, pos, light_width, light_width ); + light_width--; + if (!light_width) + break; + paint.drawEllipse( pos, pos, light_width, light_width ); + pos++; light_width--; + } + + // Draw border + pen.setWidth( scale + 1 ); + color = QColor("#7D7D7D"); + pen.setColor( color ); // Set the pen accordingly + paint.setPen( pen ); // Select pen for drawing + brush.setStyle( QBrush::NoBrush ); // Switch off the brush + paint.setBrush( brush ); // This avoids filling of the ellipse + paint.drawEllipse( 2, 2, width, width ); + paint.end(); + + tmpMap->setMask(tmpMap->createHeuristicMask(true)); + + // painting done + QImage i = tmpMap->convertToImage(); + delete tmpMap; + + i.setAlphaBuffer(true); + width /= 3; + i = i.smoothScale(width, width); + + QPixmap dest = i; + + QIconSet result; + result.setPixmap(dest,QIconSet::Automatic); + return dest; +} + +QIconSet Images::getServerLed(bool state) +{ + if (state) + return m_serverLedOn; + else + return m_serverLedOff; +} + +QIconSet Images::getSystemLed(bool state) +{ + if (Preferences::tabNotificationsSystemColor()!=m_systemColor) + { + if (state) + return getLed(Preferences::tabNotificationsSystemColor(),true); + else + return getLed(Preferences::tabNotificationsSystemColor(),false); + } + else + { + if (state) + return m_systemLedOn; + else + return m_systemLedOff; + } +} + +QIconSet Images::getMsgsLed(bool state) +{ + if (Preferences::tabNotificationsMsgsColor()!=m_msgsColor) + { + if (state) + return getLed(Preferences::tabNotificationsMsgsColor(),true); + else + return getLed(Preferences::tabNotificationsMsgsColor(),false); + } + else + { + if (state) + return m_msgsLedOn; + else + return m_msgsLedOff; + } +} + +QIconSet Images::getPrivateLed(bool state) +{ + if (Preferences::tabNotificationsPrivateColor()!=m_privateColor) + { + if (state) + return getLed(Preferences::tabNotificationsPrivateColor(),true); + else + return getLed(Preferences::tabNotificationsPrivateColor(),false); + } + else + { + if (state) + return m_privateLedOn; + else + return m_privateLedOff; + } +} + +QIconSet Images::getEventsLed() +{ + if (Preferences::tabNotificationsEventsColor()!=m_eventsColor) + return getLed(Preferences::tabNotificationsEventsColor(),true); + else + return m_eventsLedOn; +} + +QIconSet Images::getNickLed() +{ + if (Preferences::tabNotificationsNickColor()!=m_nickColor) + return getLed(Preferences::tabNotificationsNickColor(),true); + else + return m_nickLedOn; +} + +QIconSet Images::getHighlightsLed() +{ + if (Preferences::tabNotificationsHighlightsColor()!=m_highlightsColor) + return getLed(Preferences::tabNotificationsHighlightsColor(),true); + else + return m_highlightsLedOn; +} + +#include "images.moc" diff --git a/konversation/src/images.h b/konversation/src/images.h new file mode 100644 index 0000000..119c048 --- /dev/null +++ b/konversation/src/images.h @@ -0,0 +1,102 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2005-2006 Eike Hein +*/ + +#ifndef IMAGES_H +#define IMAGES_H + +#include +#include +#include + + +/** + * Do not create an instance of this class yourself. + * use KonversationApplication::instance()->images(). + */ + +class Images : public QObject +{ + Q_OBJECT + + public: + enum NickPrivilege + { + Normal=0, + Voice, + HalfOp, + Op, + Owner, + Admin, + _NickPrivilege_COUNT + }; + + Images(); + virtual ~Images(); + + QPixmap getCloseIcon() { return m_closeIcon; } + QPixmap getDisabledCloseIcon() { return m_disabledCloseIcon; } + + QIconSet getLed(QColor col,bool state = true); + + QIconSet getServerLed(bool state); + QIconSet getSystemLed(bool state); + QIconSet getMsgsLed(bool state); + QIconSet getPrivateLed(bool state); + QIconSet getEventsLed(); + QIconSet getNickLed(); + QIconSet getHighlightsLed(); + + QIconSet getKimproxyAway() const; + QIconSet getKimproxyOnline() const; + QIconSet getKimproxyOffline() const; + + QPixmap getNickIcon(NickPrivilege privilege,bool isAway=false) const; + void initializeNickIcons(); + + public slots: + void updateIcons(); + + protected: + void initializeLeds(); + void initializeKimifaceIcons(); + + QPixmap m_closeIcon; + QPixmap m_disabledCloseIcon; + + QIconSet m_serverLedOn; + QIconSet m_serverLedOff; + QIconSet m_systemLedOn; + QIconSet m_systemLedOff; + QIconSet m_msgsLedOn; + QIconSet m_msgsLedOff; + QIconSet m_privateLedOn; + QIconSet m_privateLedOff; + QIconSet m_eventsLedOn; + QIconSet m_nickLedOn; + QIconSet m_highlightsLedOn; + + QColor m_serverColor; + QColor m_systemColor; + QColor m_msgsColor; + QColor m_privateColor; + QColor m_eventsColor; + QColor m_nickColor; + QColor m_highlightsColor; + + QIconSet kimproxyAway; + QIconSet kimproxyOnline; + QIconSet kimproxyOffline; + + // [privilege][away] + QPixmap nickIcons[_NickPrivilege_COUNT][2]; +}; +#endif diff --git a/konversation/src/inputfilter.cpp b/konversation/src/inputfilter.cpp new file mode 100644 index 0000000..badbe66 --- /dev/null +++ b/konversation/src/inputfilter.cpp @@ -0,0 +1,1985 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2004 Peter Simonsson + Copyright (C) 2006-2008 Eike Hein +*/ + +#include "inputfilter.h" +#include "server.h" +#include "replycodes.h" +#include "konversationapplication.h" +#include "commit.h" +#include "version.h" +#include "query.h" +#include "channel.h" +#include "statuspanel.h" +#include "common.h" +#include "notificationhandler.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +InputFilter::InputFilter() +{ + m_connecting = false; +} + +InputFilter::~InputFilter() +{ +} + +void InputFilter::setServer(Server* newServer) +{ + server=newServer; +} + +void InputFilter::parseLine(const QString& a_newLine) +{ + QString trailing; + QString newLine(a_newLine); + + // Remove white spaces at the end and beginning + newLine = newLine.stripWhiteSpace(); + // Find end of middle parameter list + int pos = newLine.find(" :"); + // Was there a trailing parameter? + if(pos != -1) + { + // Copy trailing parameter + trailing = newLine.mid(pos + 2); + // Cut trailing parameter from string + newLine = newLine.left(pos); + } + // Remove all unnecessary white spaces to make parsing easier + newLine = newLine.simplifyWhiteSpace(); + + QString prefix; + + // Do we have a prefix? + if(newLine[0] == ':') + { + // Find end of prefix + pos = newLine.find(' '); + // Copy prefix + prefix = newLine.mid(1, pos - 1); + // Remove prefix from line + newLine = newLine.mid(pos + 1); + } + + // Find end of command + pos = newLine.find(' '); + // Copy command (all lowercase to make parsing easier) + QString command = newLine.left(pos).lower(); + // Are there parameters left in the string? + QStringList parameterList; + + if(pos != -1) + { + // Cut out the command + newLine = newLine.mid(pos + 1); + // The rest of the string will be the parameter list + parameterList = QStringList::split(" ", newLine); + } + + Q_ASSERT(server); + + // Server command, if no "!" was found in prefix + if((prefix.find('!') == -1) && (prefix != server->getNickname())) + { + + parseServerCommand(prefix, command, parameterList, trailing); + } + else + { + parseClientCommand(prefix, command, parameterList, trailing); + } +} + +void InputFilter::parseClientCommand(const QString &prefix, const QString &command, const QStringList ¶meterList, const QString &_trailing) +{ + KonversationApplication* konv_app = static_cast(KApplication::kApplication()); + Q_ASSERT(konv_app); + Q_ASSERT(server); + // Extract nickname from prefix + int pos = prefix.find("!"); + QString sourceNick = prefix.left(pos); + QString sourceHostmask = prefix.mid(pos + 1); + // remember hostmask for this nick, it could have changed + server->addHostmaskToNick(sourceNick,sourceHostmask); + QString trailing = _trailing; + + if(command=="privmsg") + { + bool isChan = isAChannel(parameterList[0]); + // CTCP message? + if(server->identifyMsg() && (trailing.at(0) == '+' || trailing.at(0) == '-')) { + trailing = trailing.mid(1); + } + + if(trailing.at(0)==QChar(0x01)) + { + // cut out the CTCP command + QString ctcp = trailing.mid(1,trailing.find(1,1)-1); + + QString ctcpCommand=ctcp.left(ctcp.find(" ")).lower(); + QString ctcpArgument=ctcp.mid(ctcp.find(" ")+1); + ctcpArgument=static_cast(kapp)->doAutoreplace(ctcpArgument,false); + + // If it was a ctcp action, build an action string + if(ctcpCommand=="action" && isChan) + { + if(!isIgnore(prefix,Ignore::Channel)) + { + Channel* channel = server->getChannelByName( parameterList[0] ); + + if(!channel) { + kdError() << "Didn't find the channel " << parameterList[0] << endl; + return; + } + + channel->appendAction(sourceNick,ctcpArgument); + + if(sourceNick != server->getNickname()) + { + if(ctcpArgument.lower().find(QRegExp("(^|[^\\d\\w])" + + QRegExp::escape(server->loweredNickname()) + + "([^\\d\\w]|$)")) !=-1 ) + { + konv_app->notificationHandler()->nick(channel, sourceNick, ctcpArgument); + } + else + { + konv_app->notificationHandler()->message(channel, sourceNick, ctcpArgument); + } + } + } + } + // If it was a ctcp action, build an action string + else if(ctcpCommand=="action" && !isChan) + { + // Check if we ignore queries from this nick + if(!isIgnore(prefix,Ignore::Query)) + { + NickInfoPtr nickinfo = server->obtainNickInfo(sourceNick); + nickinfo->setHostmask(sourceHostmask); + + // create new query (server will check for dupes) + query = server->addQuery(nickinfo, false /* we didn't initiate this*/ ); + + // send action to query + query->appendAction(sourceNick,ctcpArgument); + + if(sourceNick != server->getNickname() && query) + { + konv_app->notificationHandler()->queryMessage(query, sourceNick, ctcpArgument); + } + } + } + + // Answer ping requests + else if(ctcpCommand=="ping") + { + if(!isIgnore(prefix,Ignore::CTCP)) + { + if(isChan) + { + server->appendMessageToFrontmost(i18n("CTCP"), + i18n("Received CTCP-PING request from %1 to channel %2, sending answer.") + .arg(sourceNick).arg(parameterList[0]) + ); + } + else + { + server->appendMessageToFrontmost(i18n("CTCP"), + i18n("Received CTCP-%1 request from %2, sending answer.") + .arg("PING").arg(sourceNick) + ); + } + server->ctcpReply(sourceNick,QString("PING %1").arg(ctcpArgument)); + } + } + + // Maybe it was a version request, so act appropriately + else if(ctcpCommand=="version") + { + if(!isIgnore(prefix,Ignore::CTCP)) + { + if (isChan) + { + server->appendMessageToFrontmost(i18n("CTCP"), + i18n("Received Version request from %1 to channel %2.") + .arg(sourceNick).arg(parameterList[0]) + ); + } + else + { + server->appendMessageToFrontmost(i18n("CTCP"), + i18n("Received Version request from %1.") + .arg(sourceNick) + ); + } + + QString reply; + if(Preferences::customVersionReplyEnabled()) + { + reply = Preferences::customVersionReply().stripWhiteSpace(); + } + else + { + // Do not internationalize the below version string + reply = QString("Konversation %1 (C) 2002-2008 by the Konversation team") + .arg(QString(KONVI_VERSION)); + } + server->ctcpReply(sourceNick,"VERSION "+reply); + } + } + // DCC request? + else if(ctcpCommand=="dcc" && !isChan) + { + if(!isIgnore(prefix,Ignore::DCC)) + { + // Extract DCC type and argument list + QString dccType=ctcpArgument.lower().section(' ',0,0); + + // Support file names with spaces + QString dccArguments = ctcpArgument.mid(ctcpArgument.find(" ")+1); + QStringList dccArgumentList; + + if ((dccArguments.contains('\"') >= 2) && (dccArguments.startsWith("\""))) { + int lastQuotePos = dccArguments.findRev("\""); + if (dccArguments[lastQuotePos+1] == ' ') { + QString fileName = dccArguments.mid(1, lastQuotePos-1); + dccArguments = dccArguments.mid(lastQuotePos+2); + + dccArgumentList.append(fileName); + } + } + dccArgumentList += QStringList::split(' ', dccArguments); + + if(dccType=="send") + { + if(dccArgumentList.count()==4) + { + // incoming file + konv_app->notificationHandler()->dccIncoming(server->getStatusView(), sourceNick); + emit addDccGet(sourceNick,dccArgumentList); + } + else if(dccArgumentList.count()==5) + { + if(dccArgumentList[2]=="0") + { + // incoming file (Reverse DCC) + konv_app->notificationHandler()->dccIncoming(server->getStatusView(), sourceNick); + emit addDccGet(sourceNick,dccArgumentList); + } + else + { + // the receiver accepted the offer for Reverse DCC + emit startReverseDccSendTransfer(sourceNick,dccArgumentList); + } + } + else + { + server->appendMessageToFrontmost(i18n("DCC"), + i18n("Received invalid DCC SEND request from %1.") + .arg(sourceNick) + ); + } + } + else if(dccType=="accept") + { + // resume request was accepted + if(dccArgumentList.count()==3) + { + emit resumeDccGetTransfer(sourceNick,dccArgumentList); + } + else + { + server->appendMessageToFrontmost(i18n("DCC"), + i18n("Received invalid DCC ACCEPT request from %1.") + .arg(sourceNick) + ); + } + } + // Remote client wants our sent file resumed + else if(dccType=="resume") + { + if(dccArgumentList.count()==3) + { + emit resumeDccSendTransfer(sourceNick,dccArgumentList); + } + else + { + server->appendMessageToFrontmost(i18n("DCC"), + i18n("Received invalid DCC RESUME request from %1.") + .arg(sourceNick) + ); + } + } + else if(dccType=="chat") + { + + if(dccArgumentList.count()==3) + { + // will be connected via Server to KonversationMainWindow::addDccChat() + emit addDccChat(server->getNickname(),sourceNick,dccArgumentList,false); + } + else + { + server->appendMessageToFrontmost(i18n("DCC"), + i18n("Received invalid DCC CHAT request from %1.") + .arg(sourceNick) + ); + } + } + else + { + server->appendMessageToFrontmost(i18n("DCC"), + i18n("Unknown DCC command %1 received from %2.") + .arg(ctcpArgument).arg(sourceNick) + ); + } + } + } + else if (ctcpCommand=="clientinfo" && !isChan) + { + server->appendMessageToFrontmost(i18n("CTCP"), + i18n("Received CTCP-%1 request from %2, sending answer.") + .arg("CLIENTINFO").arg(sourceNick) + ); + server->ctcpReply(sourceNick,QString("CLIENTINFO ACTION CLIENTINFO DCC PING TIME VERSION")); + } + else if(ctcpCommand=="time" && !isChan) + { + server->appendMessageToFrontmost(i18n("CTCP"), + i18n("Received CTCP-%1 request from %2, sending answer.") + .arg("TIME").arg(sourceNick) + ); + server->ctcpReply(sourceNick,QString("TIME ")+QDateTime::currentDateTime().toString()); + } + + // No known CTCP request, give a general message + else + { + if(!isIgnore(prefix,Ignore::CTCP)) + { + if (isChan) + server->appendServerMessageToChannel( + parameterList[0], + "CTCP", + i18n("Received unknown CTCP-%1 request from %2 to Channel %3.") + .arg(ctcp).arg(sourceNick).arg(parameterList[0]) + ); + else + server->appendMessageToFrontmost(i18n("CTCP"), + i18n("Received unknown CTCP-%1 request from %2.") + .arg(ctcp).arg(sourceNick) + ); + } + } + } + // No CTCP, so it's an ordinary channel or query message + else + { + parsePrivMsg (prefix, parameterList, trailing); + } + } + else if(command=="notice") + { + if(!isIgnore(prefix,Ignore::Notice)) + { + // Channel notice? + if(isAChannel(parameterList[0])) + { + if(server->identifyMsg()) + { + trailing = trailing.mid(1); + } + + server->appendServerMessageToChannel(parameterList[0], i18n("Notice"), + i18n("-%1 to %2- %3") + .arg(sourceNick).arg(parameterList[0]).arg(trailing) + ); + } + // Private notice + else + { + // Was this a CTCP reply? + if(trailing.at(0)==QChar(0x01)) + { + // cut 0x01 bytes from trailing string + QString ctcp(trailing.mid(1,trailing.length()-2)); + QString replyReason(ctcp.section(' ',0,0)); + QString reply(ctcp.section(' ',1)); + + // pong reply, calculate turnaround time + if(replyReason.lower()=="ping") + { + int dateArrived=QDateTime::currentDateTime().toTime_t(); + int dateSent=reply.toInt(); + int time = dateArrived-dateSent; + QString unit = "seconds"; + + if (time==1) + unit = "second"; + + server->appendMessageToFrontmost(i18n("CTCP"), + i18n("Received CTCP-PING reply from %1: %2 %3.") + .arg(sourceNick) + .arg(time) + .arg(unit) + ); + } + // all other ctcp replies get a general message + else + { + server->appendMessageToFrontmost(i18n("CTCP"), + i18n("Received CTCP-%1 reply from %2: %3.") + .arg(replyReason).arg(sourceNick).arg(reply) + ); + } + } + // No, so it was a normal notice + else + { + // Nickserv + if (trailing.startsWith("If this is your nick")) + { + // Identify command if specified + server->registerWithServices(); + } + else if (server->identifyMsg()) + trailing = trailing.mid(1); + + if(trailing.lower() == "password accepted - you are now recognized" + || trailing.lower() == "you have already identified") + { + NickInfoPtr nickInfo = server->getNickInfo(server->getNickname()); + if(nickInfo) + nickInfo->setIdentified(true); + } + server->appendMessageToFrontmost(i18n("Notice"), i18n("-%1- %2").arg(sourceNick).arg(trailing)); + } + } + } + } + else if(command=="join") + { + QString channelName(trailing); + // Sometimes JOIN comes without ":" in front of the channel name + if(channelName.isEmpty()) + channelName=parameterList[parameterList.count()-1]; + + // Did we join the channel, or was it someone else? + if(server->isNickname(sourceNick)) + { + /* + QString key; + // TODO: Try to remember channel keys for autojoins and manual joins, so + // we can get %k to work + + if(channelName.find(' ')!=-1) + { + key=channelName.section(' ',1,1); + channelName=channelName.section(' ',0,0); + } + */ + + // Join the channel + server->joinChannel(channelName, sourceHostmask); + + server->resetNickList(channelName); + + // Upon JOIN we're going to receive some NAMES input from the server which + // we need to be able to tell apart from manual invocations of /names + setAutomaticRequest("NAMES",channelName,true); + + server->getChannelByName(channelName)->clearModeList(); + + // Request modes for the channel + server->queue("MODE "+channelName, Server::LowPriority); + + // Initiate channel ban list + server->getChannelByName(channelName)->clearBanList(); + setAutomaticRequest("BANLIST",channelName,true); + server->queue("MODE "+channelName+" +b", Server::LowPriority); + } + else + { + Channel* channel = server->nickJoinsChannel(channelName,sourceNick,sourceHostmask); + konv_app->notificationHandler()->join(channel, sourceNick); + } + } + else if(command=="kick") + { + server->nickWasKickedFromChannel(parameterList[0],parameterList[1],sourceNick,trailing); + } + else if(command=="part") + { + /* FIXME: Ugly workaround for a version of the PART line encountered on ircu: + * :Nick!user@host PART :#channel + * Quote: "The final colon is specified as a "last argument" designator, and + * is always valid before the final argument." + */ + + QString channel; + QString reason; + + if (parameterList[0].isEmpty()) + { + channel = trailing; + } + else + { + channel = parameterList[0]; + reason = trailing; + } + + Channel* channelPtr = server->removeNickFromChannel(channel,sourceNick,reason); + + if(sourceNick != server->getNickname()) + { + konv_app->notificationHandler()->part(channelPtr, sourceNick); + } + } + else if(command=="quit") + { + server->removeNickFromServer(sourceNick,trailing); + if(sourceNick != server->getNickname()) + { + konv_app->notificationHandler()->quit(server->getStatusView(), sourceNick); + } + } + else if(command=="nick") + { + QString newNick(trailing); + + // Message may not include ":" in front of the new nickname + if (newNick.isEmpty()) + newNick=parameterList[parameterList.count()-1]; + + server->renameNick(sourceNick,newNick); + + if (sourceNick != server->getNickname()) + { + konv_app->notificationHandler()->nickChange(server->getStatusView(), sourceNick, newNick); + } + } + else if(command=="topic") + { + server->setChannelTopic(sourceNick,parameterList[0],trailing); + } + else if(command=="mode") // mode #channel -/+ mmm params + { + QStringList params=parameterList; + if (!trailing.isEmpty()) + params << trailing; + parseModes(sourceNick, params); + Channel* channel = server->getChannelByName(parameterList[0]); + if(sourceNick != server->getNickname()) + { + konv_app->notificationHandler()->mode(channel, sourceNick); + } + } + else if(command=="invite") + { + QString channel; + + if (parameterList.count() > 1) + channel = parameterList[1]; + else + channel = trailing; + + server->appendMessageToFrontmost(i18n("Invite"), + i18n("%1 invited you to channel %2.") + .arg(sourceNick).arg(channel) + ); + emit invitation(sourceNick,channel); + } + else + { + server->appendMessageToFrontmost(command,parameterList.join(" ")+' '+trailing); + } +} + +void InputFilter::parseServerCommand(const QString &prefix, const QString &command, const QStringList ¶meterList, const QString &trailing) +{ + bool isNumeric; + int numeric = command.toInt(&isNumeric); + + Q_ASSERT(server); if(!server) return; + + if(!isNumeric) + { + if(command=="ping") + { + QString text; + text = (!trailing.isEmpty()) ? trailing : parameterList.join(" "); + + if(!trailing.isEmpty()) + { + text = prefix + " :" + text; + } + + if(!text.startsWith(" ")) + { + text.prepend(' '); + } + + // queue the reply to send it as soon as possible + server->queue("PONG"+text, Server::HighPriority); + + } + else if(command=="error :closing link:") + { + kdDebug() << "link closed" << endl; + } + else if(command=="pong") + { + // double check if we are in lag measuring mode since some servers fail to send + // the LAG cookie back in PONG + if(trailing.startsWith("LAG") || getLagMeasuring()) + { + server->pongReceived(); + } + } + else if(command=="mode") + { + QStringList params=parameterList; + if (!trailing.isEmpty()) + params << trailing; + parseModes(prefix, params); + } + else if(command=="notice") + { + server->appendStatusMessage(i18n("Notice"),i18n("-%1- %2").arg(prefix).arg(trailing)); + } + else if(command=="kick") + { + server->nickWasKickedFromChannel(parameterList[0],parameterList[1],prefix,trailing); + } + else if(command == "privmsg") + { + parsePrivMsg(prefix, parameterList, trailing); + } + // All yet unknown messages go into the frontmost window unaltered + else + { + server->appendMessageToFrontmost(command,parameterList.join(" ")+' '+trailing); + } + } + else + { + switch (numeric) + { + case RPL_WELCOME: + case RPL_YOURHOST: + case RPL_CREATED: + { + if(numeric==RPL_WELCOME) + { + QString host; + + if(trailing.contains("@")) + host = trailing.section("@",1); + + // re-set nickname, since the server may have truncated it + if(parameterList[0]!=server->getNickname()) + server->renameNick(server->getNickname(), parameterList[0]); + + // Send the welcome signal, so the server class knows we are connected properly + emit welcome(host); + m_connecting = true; + } + server->appendStatusMessage(i18n("Welcome"),trailing); + break; + } + case RPL_MYINFO: + { + server->appendStatusMessage(i18n("Welcome"), + i18n("Server %1 (Version %2), User modes: %3, Channel modes: %4") + .arg(parameterList[1]) + .arg(parameterList[2]) + .arg(parameterList[3]) + .arg(parameterList[4]) + ); + server->setAllowedChannelModes(parameterList[4]); + break; + } + //case RPL_BOUNCE: // RFC 1459 name, now seems to be obsoleted by ... + case RPL_ISUPPORT: // ... DALnet RPL_ISUPPORT + { + server->appendStatusMessage(i18n("Support"),parameterList.join(" ")); + + // The following behavoiur is neither documented in RFC 1459 nor in 2810-2813 + // Nowadays, most ircds send server capabilities out via 005 (BOUNCE). + // refer to http://www.irc.org/tech_docs/005.html for a kind of documentation. + // More on http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt + + QStringList::const_iterator it = parameterList.begin(); + // don't want the user name + ++it; + for (; it != parameterList.end(); ++it ) + { + QString property, value; + int pos; + if ((pos=(*it).find( '=' )) !=-1) + { + property = (*it).left(pos); + value = (*it).mid(pos+1); + } + else + { + property = *it; + } + if (property=="PREFIX") + { + pos = value.find(')',1); + if(pos==-1) + { + server->setPrefixes(QString(), value); + // XXX if ) isn't in the string, NOTHING should be there. anyone got a server + if (value.length() || property.length()) + server->appendStatusMessage("","XXX Server sent bad PREFIX in RPL_ISUPPORT, please report."); + } + else + { + server->setPrefixes (value.mid(1, pos-1), value.mid(pos+1)); + } + } + else if (property=="CHANTYPES") + { + server->setChannelTypes(value); + } + else if (property == "CAPAB") + { + // Disable as we don't use this for anything yet + //server->queue("CAPAB IDENTIFY-MSG"); + } + else + { + //kdDebug() << "Ignored server-capability: " << property << " with value '" << value << "'" << endl; + } + } // endfor + break; + } + case RPL_UMODEIS: + { + QString message=QString("%1 %2").arg(i18n("Your personal modes are:")).arg(parameterList.join(" ").section(' ',1) + ' '+trailing); + server->appendMessageToFrontmost("Info", message); + break; + } + case RPL_CHANNELMODEIS: + { + const QString modeString=parameterList[2]; + // This is the string the user will see + QString modesAre; + QString message = i18n("Channel modes: ") + modeString; + + for(unsigned int index=0;indexupdateChannelModeWidgets(parameterList[1],mode,parameter); + } + } // endfor + if(!modesAre.isEmpty() && Preferences::useLiteralModes()) + { + server->appendCommandMessageToChannel(parameterList[1],i18n("Mode"),message); + } + else + { + server->appendCommandMessageToChannel(parameterList[1],i18n("Mode"), + i18n("Channel modes: ") + modesAre + ); + } + break; + } + case RPL_CHANNELURLIS: + {// :niven.freenode.net 328 argonel #channel :http://www.buggeroff.com/ + server->appendCommandMessageToChannel(parameterList[1], i18n("URL"), + i18n("Channel URL: %1").arg(trailing)); + break; + } + case RPL_CHANNELCREATED: + { + QDateTime when; + when.setTime_t(parameterList[2].toUInt()); + server->appendCommandMessageToChannel(parameterList[1],i18n("Created"), + i18n("This channel was created on %1.") + .arg(when.toString(Qt::LocalDate)) + ); + + if(Preferences::autoWhoContinuousEnabled()) + { + emit endOfWho(parameterList[1]); + } + + break; + } + case RPL_WHOISACCOUNT: + { + // Display message only if this was not an automatic request. + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + server->appendMessageToFrontmost(i18n("Whois"),i18n("%1 is logged in as %2.").arg(parameterList[1]).arg(parameterList[2])); + } + break; + } + case RPL_NAMREPLY: + { + QStringList nickList; + + if(!trailing.isEmpty()) + { + nickList = QStringList::split(" ", trailing); + } + else if(parameterList.count() > 3) + { + for(uint i = 3; i < parameterList.count(); i++) { + nickList.append(parameterList[i]); + } + } + else + { + kdDebug() << "Hmm seems something is broken... can't get to the names!" << endl; + } + + // send list to channel + server->addPendingNickList(parameterList[2], nickList); + + // Display message only if this was not an automatic request. + if(!getAutomaticRequest("NAMES",parameterList[2])==1) + { + server->appendMessageToFrontmost(i18n("Names"),trailing); + } + break; + } + case RPL_ENDOFNAMES: + { + if(getAutomaticRequest("NAMES",parameterList[1])==1) + { + // This code path was taken for the automatic NAMES input on JOIN, upcoming + // NAMES input for this channel will be manual invocations of /names + setAutomaticRequest("NAMES",parameterList[1],false); + } + else + { + server->appendMessageToFrontmost(i18n("Names"),i18n("End of NAMES list.")); + } + break; + } + // Topic set messages + case RPL_NOTOPIC: + { + server->appendMessageToFrontmost(i18n("TOPIC"),i18n("The channel %1 has no topic set.").arg(parameterList[1]) /*.arg(parameterList[2])*/); //FIXME ok, whats the second parameter supposed to be? + + break; + } + case RPL_TOPIC: + { + QString topic = Konversation::removeIrcMarkup(trailing); + + // FIXME: This is an abuse of the automaticRequest system: We're + // using it in an inverted manner, i.e. the automaticRequest is + // set to true by a manual invocation of /topic. Bad bad bad - + // needs rethinking of automaticRequest. + if(getAutomaticRequest("TOPIC",parameterList[1])==0) + { + // Update channel window + server->setChannelTopic(parameterList[1],topic); + } + else + { + server->appendMessageToFrontmost(i18n("Topic"),i18n("The channel topic for %1 is: \"%2\"").arg(parameterList[1]).arg(topic)); + } + + break; + } + case RPL_TOPICSETBY: + { + // Inform user who set the topic and when + QDateTime when; + when.setTime_t(parameterList[3].toUInt()); + + // See FIXME in RPL_TOPIC + if(getAutomaticRequest("TOPIC",parameterList[1])==0) + { + server->appendCommandMessageToChannel(parameterList[1],i18n("Topic"), + i18n("The topic was set by %1 on %2.") + .arg(parameterList[2]).arg(when.toString(Qt::LocalDate)), + false); + } + else + { + server->appendMessageToFrontmost(i18n("Topic"),i18n("The topic for %1 was set by %2 on %3.") + .arg(parameterList[1]) + .arg(parameterList[2]) + .arg(when.toString(Qt::LocalDate)) + ); + setAutomaticRequest("TOPIC",parameterList[1],false); + } + emit topicAuthor(parameterList[1], parameterList[2], when); + + break; + } + case RPL_WHOISACTUALLY: + { + // Display message only if this was not an automatic request. + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + server->appendMessageToFrontmost(i18n("Whois"),i18n("%1 is actually using the host %2.").arg(parameterList[1]).arg(parameterList[2])); + } + break; + } + case ERR_NOSUCHNICK: + { + // Display slightly different error message in case we performed a WHOIS for + // IP resolve purposes, and clear it from the automaticRequest list + if(getAutomaticRequest("DNS",parameterList[1])==0) + { + server->appendMessageToFrontmost(i18n("Error"),i18n("%1: No such nick/channel.").arg(parameterList[1])); + } + else if(getAutomaticRequest("WHOIS",parameterList[1])==0) //Display message only if this was not an automatic request. + { + server->appendMessageToFrontmost(i18n("Error"),i18n("No such nick: %1.").arg(parameterList[1])); + setAutomaticRequest("DNS", parameterList[1], false); + } + + break; + } + case ERR_NOSUCHCHANNEL: + { + // Display message only if this was not an automatic request. + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + server->appendMessageToFrontmost(i18n("Error"),i18n("%1: No such channel.").arg(parameterList[1])); + } + break; + } + // Nick already on the server, so try another one + case ERR_NICKNAMEINUSE: + { + // if we are already connected, don't try tro find another nick ourselves + if(server->isConnected()) + { // Show message + server->appendMessageToFrontmost(i18n("Nick"),i18n("Nickname already in use, try a different one.")); + } + else // not connected yet, so try to find a nick that's not in use + { + // Get the next nick from the list or ask for a new one + QString newNick = server->getNextNickname(); + + // The user chose to disconnect + if (newNick.isNull()) + { + server->disconnect(); + } + else + { + // Update Server window + server->obtainNickInfo(server->getNickname()) ; + server->renameNick(server->getNickname(), newNick); + // Show message + server->appendMessageToFrontmost(i18n("Nick"), i18n("Nickname already in use. Trying %1.").arg(newNick)); + // Send nickchange request to the server + server->queue("NICK "+newNick); + } + } + break; + } + case ERR_ERRONEUSNICKNAME: + { + if(server->isConnected()) + { // We are already connected. Just print the error message + server->appendMessageToFrontmost(i18n("Nick"), trailing); + } + else // Find a new nick as in ERR_NICKNAMEINUSE + { + QString newNick = server->getNextNickname(); + + // The user chose to disconnect + if (newNick.isNull()) + { + server->disconnect(); + } + else + { + server->obtainNickInfo(server->getNickname()) ; + server->renameNick(server->getNickname(), newNick); + server->appendMessageToFrontmost(i18n("Nick"), i18n("Erroneus nickname. Changing nick to %1." ).arg(newNick)) ; + server->queue("NICK "+newNick); + } + } + break; + } + case ERR_NOTONCHANNEL: + { + server->appendMessageToFrontmost(i18n("Error"),i18n("You are not on %1.").arg(parameterList[1])); + + break; + } + case RPL_MOTDSTART: + { + if(!m_connecting || !Preferences::skipMOTD()) + server->appendStatusMessage(i18n("MOTD"),i18n("Message of the day:")); + break; + } + case RPL_MOTD: + { + if(!m_connecting || !Preferences::skipMOTD()) + server->appendStatusMessage(i18n("MOTD"),trailing); + break; + } + case RPL_ENDOFMOTD: + { + if(!m_connecting || !Preferences::skipMOTD()) + server->appendStatusMessage(i18n("MOTD"),i18n("End of message of the day")); + + if(m_connecting) + server->autoCommandsAndChannels(); + + m_connecting = false; + break; + } + case ERR_NOMOTD: + { + if(m_connecting) + server->autoCommandsAndChannels(); + + m_connecting = false; + break; + } + case RPL_YOUREOPER: + { + server->appendMessageToFrontmost(i18n("Notice"),i18n("You are now an IRC operator on this server.")); + + break; + } + case RPL_GLOBALUSERS: // Current global users: 589 Max: 845 + { + QString current(trailing.section(' ',3)); + //QString max(trailing.section(' ',5,5)); + server->appendStatusMessage(i18n("Users"),i18n("Current users on the network: %1").arg(current)); + break; + } + case RPL_LOCALUSERS: // Current local users: 589 Max: 845 + { + QString current(trailing.section(' ',3)); + //QString max(trailing.section(' ',5,5)); + server->appendStatusMessage(i18n("Users"),i18n("Current users on %1: %2.").arg(prefix).arg(current)); + break; + } + case RPL_ISON: + { + // Tell server to start the next notify timer round + emit notifyResponse(trailing); + break; + } + case RPL_AWAY: + { + NickInfo* nickInfo = server->getNickInfo(parameterList[1]); + if(nickInfo) + { + nickInfo->setAway(true); + if( nickInfo->getAwayMessage() == trailing ) + break; + nickInfo->setAwayMessage(trailing); + } + + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + server->appendMessageToFrontmost(i18n("Away"),i18n("%1 is away: %2") + .arg(parameterList[1]).arg(trailing) + ); + } + + break; + } + case RPL_INVITING: + { + server->appendMessageToFrontmost(i18n("Invite"), + i18n("You invited %1 to channel %2.") + .arg(parameterList[1]).arg(parameterList[2]) + ); + break; + } + //Sample WHOIS response + //"/WHOIS psn" + //[19:11] :zahn.freenode.net 311 PhantomsDad psn ~psn h106n2fls23o1068.bredband.comhem.se * :Peter Simonsson + //[19:11] :zahn.freenode.net 319 PhantomsDad psn :#kde-devel #koffice + //[19:11] :zahn.freenode.net 312 PhantomsDad psn irc.freenode.net :http://freenode.net/ + //[19:11] :zahn.freenode.net 301 PhantomsDad psn :away + //[19:11] :zahn.freenode.net 320 PhantomsDad psn :is an identified user + //[19:11] :zahn.freenode.net 317 PhantomsDad psn 4921 1074973024 :seconds idle, signon time + //[19:11] :zahn.freenode.net 318 PhantomsDad psn :End of /WHOIS list. + case RPL_WHOISUSER: + { + NickInfo* nickInfo = server->getNickInfo(parameterList[1]); + if(nickInfo) + { + nickInfo->setHostmask(i18n("%1@%2").arg(parameterList[2]).arg(parameterList[3])); + nickInfo->setRealName(trailing); + } + // Display message only if this was not an automatic request. + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + // escape html tags + QString escapedRealName(trailing); + escapedRealName.replace("<","<").replace(">",">"); + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 is %2@%3 (%4)") + .arg(parameterList[1]) + .arg(parameterList[2]) + .arg(parameterList[3]) + .arg(escapedRealName), false); // Don't parse any urls + } + else + { + // This WHOIS was requested by Server for DNS resolve purposes; try to resolve the host + if(getAutomaticRequest("DNS",parameterList[1])==1) + { + KNetwork::KResolverResults resolved = KNetwork::KResolver::resolve(parameterList[3],""); + if(resolved.error() == KResolver::NoError && resolved.size() > 0) + { + QString ip = resolved.first().address().nodeName(); + server->appendMessageToFrontmost(i18n("DNS"), + i18n("Resolved %1 (%2) to address: %3") + .arg(parameterList[1]) + .arg(parameterList[3]) + .arg(ip) + ); + } + else + { + server->appendMessageToFrontmost(i18n("Error"), + i18n("Unable to resolve address for %1 (%2)") + .arg(parameterList[1]) + .arg(parameterList[3]) + ); + } + + // Clear this from the automaticRequest list so it works repeatedly + setAutomaticRequest("DNS", parameterList[1], false); + } + } + break; + } + // From a WHOIS. + //[19:11] :zahn.freenode.net 320 PhantomsDad psn :is an identified user + case RPL_WHOISIDENTIFY: + case RPL_IDENTIFIED: + { + NickInfo* nickInfo = server->getNickInfo(parameterList[1]); + if(nickInfo) + { + nickInfo->setIdentified(true); + } + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + // Prints "psn is an identified user" + //server->appendStatusMessage(i18n("Whois"),parameterList.join(" ").section(' ',1)+' '+trailing); + // The above line works fine, but can't be i18n'ised. So use the below instead.. I hope this is okay. + server->appendMessageToFrontmost(i18n("Whois"), i18n("%1 is an identified user.").arg(parameterList[1])); + } + break; + } + // Sample WHO response + //"/WHO #lounge" + //[21:39] [352] #lounge jasmine bots.worldforge.org irc.worldforge.org jasmine H 0 jasmine + //[21:39] [352] #lounge ~Nottingha worldforge.org irc.worldforge.org SherwoodSpirit H 0 Arboreal Entity + case RPL_WHOREPLY: + { + NickInfo* nickInfo = server->getNickInfo(parameterList[5]); + // G=away G@=away,op G+=away,voice + bool bAway = parameterList[6].upper().startsWith("G"); + if(nickInfo) + { + nickInfo->setHostmask(i18n("%1@%2").arg(parameterList[2]).arg(parameterList[3])); + //Strip off the "0 " + nickInfo->setRealName(trailing.section(" ", 1)); + nickInfo->setAway(bAway); + if(!bAway) + { + nickInfo->setAwayMessage(QString()); + } + } + // Display message only if this was not an automatic request. + if(!whoRequestList.isEmpty()) // for safe + { + if(getAutomaticRequest("WHO",whoRequestList.front())==0) + { + server->appendMessageToFrontmost(i18n("Who"), + i18n("%1 is %2@%3 (%4)%5").arg(parameterList[5]) + .arg(parameterList[2]) + .arg(parameterList[3]) + .arg(trailing.section(" ", 1)) + .arg(bAway?i18n(" (Away)"):QString()) + , false); // Don't parse as url + } + } + break; + } + case RPL_ENDOFWHO: + { + if(!whoRequestList.isEmpty()) + { // for safety + QStringList::iterator it = whoRequestList.find(parameterList[1].lower()); + + if(it != whoRequestList.end()) + { + if(getAutomaticRequest("WHO", *it) == 0) + { + server->appendMessageToFrontmost(i18n("Who"), + i18n("End of /WHO list for %1") + .arg(parameterList[1])); + } + else + { + setAutomaticRequest("WHO", *it, false); + } + + whoRequestList.remove(it); + } + else + { + // whoReauestList seems to be broken. + kdDebug() << "InputFilter::parseServerCommand(): RPL_ENDOFWHO: malformed ENDOFWHO. retrieved: " + << parameterList[1] << " expected: " << whoRequestList.front() + << endl; + whoRequestList.clear(); + } + } + else + { + kdDebug() << "InputFilter::parseServerCommand(): RPL_ENDOFWHO: unexpected ENDOFWHO. retrieved: " + << parameterList[1] + << endl; + } + + emit endOfWho(parameterList[1]); + break; + } + case RPL_WHOISCHANNELS: + { + QStringList userChannels,voiceChannels,opChannels,halfopChannels,ownerChannels,adminChannels; + + // get a list of all channels the user is in + QStringList channelList=QStringList::split(' ',trailing); + channelList.sort(); + + // split up the list in channels where they are operator / user / voice + for(unsigned int index=0; index < channelList.count(); index++) + { + QString lookChannel=channelList[index]; + if(lookChannel.startsWith("*") || lookChannel.startsWith("&")) + { + adminChannels.append(lookChannel.mid(1)); + server->setChannelNick(lookChannel.mid(1), parameterList[1], 16); + } + // See bug #97354 part 2 + else if((lookChannel.startsWith("!") || lookChannel.startsWith("~")) && server->isAChannel(lookChannel.mid(1))) + { + ownerChannels.append(lookChannel.mid(1)); + server->setChannelNick(lookChannel.mid(1), parameterList[1], 8); + } + // See bug #97354 part 1 + else if(lookChannel.startsWith("@+")) + { + opChannels.append(lookChannel.mid(2)); + server->setChannelNick(lookChannel.mid(2), parameterList[1], 4); + } + else if(lookChannel.startsWith("@")) + { + opChannels.append(lookChannel.mid(1)); + server->setChannelNick(lookChannel.mid(1), parameterList[1], 4); + } + else if(lookChannel.startsWith("%")) + { + halfopChannels.append(lookChannel.mid(1)); + server->setChannelNick(lookChannel.mid(1), parameterList[1], 2); + } + else if(lookChannel.startsWith("+")) + { + voiceChannels.append(lookChannel.mid(1)); + server->setChannelNick(lookChannel.mid(1), parameterList[1], 1); + } + else + { + userChannels.append(lookChannel); + server->setChannelNick(lookChannel, parameterList[1], 0); + } + } // endfor + // Display message only if this was not an automatic request. + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + if(userChannels.count()) + { + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 is a user on channels: %2") + .arg(parameterList[1]) + .arg(userChannels.join(" ")) + ); + } + if(voiceChannels.count()) + { + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 has voice on channels: %2") + .arg(parameterList[1]).arg(voiceChannels.join(" ")) + ); + } + if(halfopChannels.count()) + { + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 is a halfop on channels: %2") + .arg(parameterList[1]).arg(halfopChannels.join(" ")) + ); + } + if(opChannels.count()) + { + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 is an operator on channels: %2") + .arg(parameterList[1]).arg(opChannels.join(" ")) + ); + } + if(ownerChannels.count()) + { + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 is owner of channels: %2") + .arg(parameterList[1]).arg(ownerChannels.join(" ")) + ); + } + if(adminChannels.count()) + { + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 is admin on channels: %2") + .arg(parameterList[1]).arg(adminChannels.join(" ")) + ); + } + } + break; + } + case RPL_WHOISSERVER: + { + NickInfo* nickInfo = server->getNickInfo(parameterList[1]); + if(nickInfo) + { + nickInfo->setNetServer(parameterList[2]); + nickInfo->setNetServerInfo(trailing); + // Clear the away state on assumption that if nick is away, this message will be followed + // by a 301 RPL_AWAY message. Not necessary a invalid assumption, but what can we do? + nickInfo->setAway(false); + nickInfo->setAwayMessage(QString()); + } + // Display message only if this was not an automatic request. + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 is online via %2 (%3).").arg(parameterList[1]) + .arg(parameterList[2]).arg(trailing) + ); + } + break; + } + case RPL_WHOISHELPER: + { + // Display message only if this was not an automatic request. + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 is available for help.") + .arg(parameterList[1]) + ); + } + break; + } + case RPL_WHOISOPERATOR: + { + // Display message only if this was not an automatic request. + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + if (trailing.lower().simplifyWhiteSpace().startsWith("is an irc operator")) + server->appendMessageToFrontmost(i18n("Whois"),i18n("%1 is an IRC Operator.").arg(parameterList[1])); + else + server->appendMessageToFrontmost(i18n("Whois"),QString("%1 %2").arg(parameterList[1]).arg(trailing)); + } + break; + } + case RPL_WHOISIDLE: + { + // get idle time in seconds + long seconds=parameterList[2].toLong(); + long minutes=seconds/60; + long hours =minutes/60; + long days =hours/24; + + // if idle time is longer than a day + // Display message only if this was not an automatic request. + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + if(days) + { + const QString daysString = i18n("1 day", "%n days", days); + const QString hoursString = i18n("1 hour", "%n hours", (hours % 24)); + const QString minutesString = i18n("1 minute", "%n minutes", (minutes % 60)); + const QString secondsString = i18n("1 second", "%n seconds", (seconds % 60)); + + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 = name of person, %2 = (x days), %3 = (x hours), %4 = (x minutes), %5 = (x seconds)", + "%1 has been idle for %2, %3, %4, and %5.") + .arg(parameterList[1]) + .arg(daysString).arg(hoursString).arg(minutesString).arg(secondsString) + ); + // or longer than an hour + } + else if(hours) + { + const QString hoursString = i18n("1 hour", "%n hours", hours); + const QString minutesString = i18n("1 minute", "%n minutes", (minutes % 60)); + const QString secondsString = i18n("1 second", "%n seconds", (seconds % 60)); + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 = name of person, %2 = (x hours), %3 = (x minutes), %4 = (x seconds)", + "%1 has been idle for %2, %3, and %4.") + .arg(parameterList[1]) + .arg(hoursString).arg(minutesString).arg(secondsString) + ); + // or longer than a minute + } + else if(minutes) + { + const QString minutesString = i18n("1 minute", "%n minutes", minutes); + const QString secondsString = i18n("1 second", "%n seconds", (seconds % 60)); + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 = name of person, %2 = (x minutes), %3 = (x seconds)", + "%1 has been idle for %2 and %3.") + .arg(parameterList[1]) + .arg(minutesString).arg(secondsString) + ); + // or just some seconds + } + else + { + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 has been idle for 1 second.", "%1 has been idle for %n seconds.", seconds) + .arg(parameterList[1]) + ); + } + } + + if(parameterList.count()==4) + { + QDateTime when; + when.setTime_t(parameterList[3].toUInt()); + NickInfo* nickInfo = server->getNickInfo(parameterList[1]); + if(nickInfo) + { + nickInfo->setOnlineSince(when); + } + // Display message only if this was not an automatic request. + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + server->appendMessageToFrontmost(i18n("Whois"), + i18n("%1 has been online since %2.") + .arg(parameterList[1]).arg(when.toString(Qt::LocalDate)) + ); + } + } + break; + } + case RPL_ENDOFWHOIS: + { + //NickInfo* nickInfo = server->getNickInfo(parameterList[1]); + // Display message only if this was not an automatic request. + if(getAutomaticRequest("WHOIS",parameterList[1])==0) + { + server->appendMessageToFrontmost(i18n("Whois"),i18n("End of WHOIS list.")); + } + // was this an automatic request? + if(getAutomaticRequest("WHOIS",parameterList[1])!=0) + { + setAutomaticRequest("WHOIS",parameterList[1],false); + } + break; + } + case RPL_USERHOST: + { + // iterate over all nick/masks in reply + QStringList uhosts=QStringList::split(" ",trailing); + + for(unsigned int index=0;indexappendMessageToFrontmost(i18n("Userhost"), + i18n("%1 = nick, %2 = shows if nick is op, %3 = hostmask, %4 = shows away", "%1%2 is %3%4.") + .arg(nick) + .arg((ircOp) ? i18n(" (IRC Operator)") : QString()) + .arg(mask) + .arg((away) ? i18n(" (away)") : QString())); + } + + // was this an automatic request? + if(getAutomaticRequest("USERHOST",nick)!=0) + { + setAutomaticRequest("USERHOST",nick,false); + } + } // for + break; + } + case RPL_LISTSTART: //FIXME This reply is obsolete!!! + { + if(getAutomaticRequest("LIST",QString())==0) + { + server->appendMessageToFrontmost(i18n("List"),i18n("List of channels:")); + } + break; + } + case RPL_LIST: + { + if(getAutomaticRequest("LIST",QString())==0) + { + QString message; + message=i18n("%1 (%n user): %2", "%1 (%n users): %2", parameterList[2].toInt()); + server->appendMessageToFrontmost(i18n("List"),message.arg(parameterList[1]).arg(trailing)); + } + else // send them to /LIST window + { + emit addToChannelList(parameterList[1],parameterList[2].toInt(),trailing); + } + + break; + } + case RPL_LISTEND: + { + // was this an automatic request? + if(getAutomaticRequest("LIST",QString())==0) + { + server->appendMessageToFrontmost(i18n("List"),i18n("End of channel list.")); + } + else + { + setAutomaticRequest("LIST",QString(),false); + } + break; + } + case RPL_NOWAWAY: + { + NickInfo* nickInfo = server->getNickInfo(parameterList[0]); + if (nickInfo) nickInfo->setAway(true); + + server->setAway(true); + + break; + } + case RPL_UNAWAY: + { + NickInfo* nickInfo = server->getNickInfo(parameterList[0]); + + if (nickInfo) + { + nickInfo->setAway(false); + nickInfo->setAwayMessage(QString()); + } + + server->setAway(false); + + break; + } + case RPL_BANLIST: + { + if (getAutomaticRequest("BANLIST", parameterList[1])) + { + server->addBan(parameterList[1], parameterList.join(" ").section(' ', 2, 4)); + } else { + QDateTime when; + when.setTime_t(parameterList[4].toUInt()); + + server->appendMessageToFrontmost(i18n("BanList:%1").arg(parameterList[1]), i18n("BanList message: e.g. *!*@aol.com set by MrGrim on ", "%1 set by %2 on %3").arg(parameterList[2]).arg(parameterList[3].section('!', 0, 0)).arg(when.toString(Qt::LocalDate))); + } + break; + } + case RPL_ENDOFBANLIST: + { + if (getAutomaticRequest("BANLIST", parameterList[1])) + { + setAutomaticRequest("BANLIST", parameterList[1], false); + } else { + server->appendMessageToFrontmost(i18n("BanList:%1").arg(parameterList[1]), i18n("End of Ban List.")); + } + break; + } + case ERR_NOCHANMODES: + { + ChatWindow *chatwindow = server->getChannelByName(parameterList[1]); + if(chatwindow) + { + chatwindow->appendServerMessage(i18n("Channel"), trailing); + } + else // We couldn't join the channel , so print the error. with [#channel] : + { + server->appendMessageToFrontmost(i18n("Channel"), trailing); + } + break; + } + case ERR_NOSUCHSERVER: + { + //Some servers don't know their name, so they return an error instead of the PING data + if (getLagMeasuring() && trailing.startsWith(prefix)) + { + server->pongReceived(); + } + break; + } + case ERR_UNAVAILRESOURCE: + { + server->appendMessageToFrontmost(i18n("Error"),i18n("%1 is currently unavailable.").arg(parameterList[1])); + + break; + } + case RPL_HIGHCONNECTCOUNT: + case RPL_LUSERCLIENT: + case RPL_LUSEROP: + case RPL_LUSERUNKNOWN: + case RPL_LUSERCHANNELS: + case RPL_LUSERME: + { + server->appendStatusMessage(i18n("Users"), parameterList.join(" ").section(' ',1) + ' '+trailing); + break; + } + case ERR_UNKNOWNCOMMAND: + { + server->appendMessageToFrontmost(i18n("Error"),i18n("%1: Unknown command.").arg(parameterList[1])); + + break; + } + case ERR_NOTREGISTERED: + { + server->appendMessageToFrontmost(i18n("Error"),i18n("Not registered.")); + + break; + } + case ERR_NEEDMOREPARAMS: + { + server->appendMessageToFrontmost(i18n("Error"),i18n("%1: This command requires more parameters.").arg(parameterList[1])); + + break; + } + case RPL_CAPAB: // Special freenode reply afaik + { + // Disable as we don't use this for anything yet + if(trailing.contains("IDENTIFY-MSG")) + { + server->enableIdentifyMsg(true); + break; + } + + /* don't break; - this is also used as RPL_DATASTR on ircu and some others */ + } + // FALLTHROUGH to default to let the error display otherwise + default: + { + // All yet unknown messages go into the frontmost window without the + // preceding nickname + server->appendMessageToFrontmost(command, parameterList.join(" ").section(' ',1) + ' '+trailing); + } + } // end of numeric switch + } +} + +void InputFilter::parseModes(const QString &sourceNick, const QStringList ¶meterList) +{ + const QString modestring=parameterList[1]; + + if (!isAChannel(parameterList[0])) + { + QString message; + if (parameterList[0] == server->getNickname()) + { + if (sourceNick == server->getNickname()) + { + //XXX someone might care about the potentially unnecessary plural here + message = i18n("You have set personal modes: ") + modestring; + } + else + { //XXX someone might care about the potentially unnecessary plural here + message = QString("%1 %2 %3").arg(sourceNick).arg(i18n("has changed your personal modes:")).arg(modestring); + } + } + if (!message.isEmpty()) + server->appendStatusMessage(i18n("Mode"), message); + return; + } + + bool plus=false; + int parameterIndex=0; + // List of modes that need a parameter (note exception with -k and -l) + // Mode q is quiet on freenode and acts like b... if this is a channel mode on other + // networks then more logic is needed here. --MrGrim + QString parameterModes="aAoOvhkbleIq"; + QString message = sourceNick + i18n(" sets mode: ") + modestring; + + for(unsigned int index=0;indexupdateChannelMode(sourceNick,parameterList[0],mode,plus,parameter); + } + } // endfor + + if (Preferences::useLiteralModes()) + { + server->appendCommandMessageToChannel(parameterList[0],i18n("Mode"),message); + } +} + +// # & + and ! are *often*, but not necessarily, Channel identifiers. + and ! are non-RFC, +// so if a server doesn't offer 005 and supports + and ! channels, I think thats broken behaviour +// on their part - not ours. --Argonel +bool InputFilter::isAChannel(const QString &check) +{ + Q_ASSERT(server); + // if we ever see the assert, we need the ternary + return server? server->isAChannel(check) : QString("#&").contains(check.at(0)); +} + +bool InputFilter::isIgnore(const QString &sender, Ignore::Type type) +{ + bool doIgnore = false; + + QPtrList list = Preferences::ignoreList(); + + for(unsigned int index =0; indexgetName()).replace("\\*", "(.*)"),false); + if (ignoreItem.exactMatch(sender) && (item->getFlags() & type)) + doIgnore = true; + if (ignoreItem.exactMatch(sender) && (item->getFlags() & Ignore::Exception)) + return false; + } + + return doIgnore; +} + +void InputFilter::reset() +{ + automaticRequest.clear(); + whoRequestList.clear(); +} + +void InputFilter::setAutomaticRequest(const QString& command, const QString& name, bool yes) +{ + automaticRequest[command][name.lower()] += (yes) ? 1 : -1; + if(automaticRequest[command][name.lower()]<0) + { + kdDebug() << "InputFilter::automaticRequest( " << command << ", " << name + << " ) was negative! Resetting!" + << endl; + automaticRequest[command][name.lower()]=0; + } +} + +int InputFilter::getAutomaticRequest(const QString& command, const QString& name) +{ + return automaticRequest[command][name.lower()]; +} + +void InputFilter::addWhoRequest(const QString& name) { whoRequestList << name.lower(); } + +bool InputFilter::isWhoRequestUnderProcess(const QString& name) { return (whoRequestList.contains(name.lower())>0); } + +void InputFilter::setLagMeasuring(bool state) { lagMeasuring=state; } + +bool InputFilter::getLagMeasuring() { return lagMeasuring; } + +void InputFilter::parsePrivMsg(const QString& prefix, + const QStringList& parameterList, + const QString& trailing) +{ + int pos = prefix.find("!"); + QString source; + QString sourceHostmask; + QString message(trailing); + + if(pos > 0) + { + source = prefix.left(pos); + sourceHostmask = prefix.mid(pos + 1); + } + else + { + source = prefix; + } + + KonversationApplication* konv_app = static_cast(kapp); + message = konv_app->doAutoreplace(message, false); + + if(isAChannel(parameterList[0])) + { + if(!isIgnore(prefix, Ignore::Channel)) + { + Channel* channel = server->getChannelByName(parameterList[0]); + if(channel) + { + channel->append(source, message); + + if(source != server->getNickname()) + { + QRegExp regexp("(^|[^\\d\\w])" + + QRegExp::escape(server->loweredNickname()) + + "([^\\d\\w]|$)"); + regexp.setCaseSensitive(false); + if(message.find(regexp) !=-1 ) + { + konv_app->notificationHandler()->nick(channel, + source, message); + } + else + { + konv_app->notificationHandler()->message(channel, + source, message); + } + } + } + } + } + else + { + if(!isIgnore(prefix,Ignore::Query)) + { + NickInfoPtr nickinfo = server->obtainNickInfo(source); + nickinfo->setHostmask(sourceHostmask); + + // Create a new query (server will check for dupes) + query = server->addQuery(nickinfo, false /*we didn't initiate this*/ ); + + // send action to query + query->appendQuery(source, message); + + if(source != server->getNickname() && query) + { + QRegExp regexp("(^|[^\\d\\w])" + + QRegExp::escape(server->loweredNickname()) + + "([^\\d\\w]|$)"); + regexp.setCaseSensitive(false); + if(message.find(regexp) !=-1 ) + { + konv_app->notificationHandler()->nick(query, + source, message); + } + else + { + konv_app->notificationHandler()->queryMessage(query, + source, message); + } + } + } + } +} + +#include "inputfilter.moc" + +// kate: space-indent on; tab-width 4; indent-width 4; mixed-indent off; replace-tabs on; +// vim: set et sw=4 ts=4 cino=l1,cs,U1: diff --git a/konversation/src/inputfilter.h b/konversation/src/inputfilter.h new file mode 100644 index 0000000..2edb985 --- /dev/null +++ b/konversation/src/inputfilter.h @@ -0,0 +1,94 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2004 Peter Simonsson + Copyright (C) 2006-2008 Eike Hein +*/ + +#ifndef INPUTFILTER_H +#define INPUTFILTER_H + +#include "ignore.h" + +#include +#include + + +class Server; +class QWidget; +class Query; +class QDateTime; + +class InputFilter : public QObject +{ + Q_OBJECT + + public: + InputFilter(); + ~InputFilter(); + + void setServer(Server* newServer); + void parseLine(const QString &line); + + void reset(); // reset AutomaticRequest, WhoRequestList + + // use this when the client does automatics, like userhost for finding hostmasks + void setAutomaticRequest(const QString& command, const QString& name, bool yes); + int getAutomaticRequest(const QString& command, const QString& name); + void addWhoRequest(const QString& name); // called from Server::send() + // to avoid duplicate requests + bool isWhoRequestUnderProcess(const QString& name); + void setLagMeasuring(bool yes); + bool getLagMeasuring(); + + signals: + void welcome(const QString& ownHost); + void notifyResponse(const QString &nicksOnline); + // will be connected to Server::startReverseDccSendTransfer() + void startReverseDccSendTransfer(const QString &sourceNick, const QStringList &dccArgument); + // will be connected to Server::addDccGet() + void addDccGet(const QString &sourceNick, const QStringList &dccArgument); + // will be connected to Server::resumeDccGetTransfer() + void resumeDccGetTransfer(const QString &sourceNick, const QStringList &dccArgument); + // will be connected to Server::resumeDccSendTransfer() + void resumeDccSendTransfer(const QString &sourceNick, const QStringList &dccArgument); + // will be connected to Server::userhost() + void userhost(const QString& nick,const QString& hostmask,bool away,bool ircOp); + // will be connected to Server::setTopicAuthor() + void topicAuthor(const QString& channel, const QString& author, QDateTime t); + void endOfWho(const QString& target); // for scheduling auto /WHO + void addChannelListPanel(); + void addToChannelList(const QString& channel,int users,const QString& topic); + void invitation(const QString& nick,const QString& channel); + + void addDccChat(const QString& myNick,const QString& nick,const QStringList& arguments,bool listen); + + protected: + void parseClientCommand(const QString &prefix, const QString &command, const QStringList ¶meterList, const QString &trailing); + void parseServerCommand(const QString &prefix, const QString &command, const QStringList ¶meterList, const QString &trailing); + void parseModes(const QString &sourceNick, const QStringList ¶meterList); + void parsePrivMsg(const QString& prefix, const QStringList& parameterList, const QString& trailing); + + bool isAChannel(const QString &check); + bool isIgnore(const QString &pattern, Ignore::Type type); + + Server* server; + // automaticRequest[command][channel or nick]=count + QMap< QString, QMap > automaticRequest; + QStringList whoRequestList; + int lagMeasuring; + + Query* query; + + int m_debugCount; + + /// Used when handling MOTD + bool m_connecting; +}; +#endif diff --git a/konversation/src/insertchardialog.cpp b/konversation/src/insertchardialog.cpp new file mode 100644 index 0000000..3b5c080 --- /dev/null +++ b/konversation/src/insertchardialog.cpp @@ -0,0 +1,57 @@ +/* + 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. +*/ + +/* + copyright: (C) 2004 by Peter Simonsson + email: psn@linux.se +*/ +#include "insertchardialog.h" + +#include +#include +#include + + +namespace Konversation +{ + + InsertCharDialog::InsertCharDialog(const QString& font, QWidget *parent, const char *name) + : KDialogBase(parent, name, false, i18n("Insert Character"), + KDialogBase::Ok | KDialogBase::Close, + KDialogBase::Ok, false) + { + setButtonOK(KGuiItem(i18n("&Insert"), "ok", i18n("Insert a character"))); + + m_charTable = new KCharSelect(this, "charTable", font); + m_charTable->enableFontCombo(false); + setMainWidget(m_charTable); + + connect(m_charTable, SIGNAL(doubleClicked()), this, SLOT(slotOk())); + } + + InsertCharDialog::~InsertCharDialog() + { + } + + void InsertCharDialog::setFont(const QFont &font) + { + m_charTable->setFont(font.family()); + } + + QChar InsertCharDialog::chr() + { + return m_charTable->chr(); + } + + void InsertCharDialog::slotOk() + { + emit insertChar(m_charTable->chr()); + } + +} + +#include "insertchardialog.moc" diff --git a/konversation/src/insertchardialog.h b/konversation/src/insertchardialog.h new file mode 100644 index 0000000..a2c0001 --- /dev/null +++ b/konversation/src/insertchardialog.h @@ -0,0 +1,46 @@ +/* + 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. +*/ + +/* + copyright: (C) 2004 by Peter Simonsson + email: psn@linux.se +*/ +#ifndef KONVERSATIONINSERTCHARDIALOG_H +#define KONVERSATIONINSERTCHARDIALOG_H + +#include + + +class KCharSelect; +class QChar; + +namespace Konversation +{ + + class InsertCharDialog : public KDialogBase + { + Q_OBJECT + + public: + explicit InsertCharDialog(const QString& font = QString(), QWidget *parent = 0, const char *name = 0); + ~InsertCharDialog(); + + void setFont(const QFont &font); + QChar chr(); + + protected slots: + virtual void slotOk(); + + signals: + void insertChar(const QChar&); + + private: + KCharSelect* m_charTable; + }; + +} +#endif diff --git a/konversation/src/irccharsets.cpp b/konversation/src/irccharsets.cpp new file mode 100644 index 0000000..89fdf4f --- /dev/null +++ b/konversation/src/irccharsets.cpp @@ -0,0 +1,177 @@ +// A wrapper for KCharsets +// Copyright (C) 2004, 2006 Shintaro Matsuoka + +/* + 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. +*/ + +#include "irccharsets.h" + +#include +#include +#include +#include +#include +#include +#include + +#if QT_VERSION < 0x030300 +#include +#else +#include +#endif + + +namespace Konversation +{ + + IRCCharsets* IRCCharsets::s_self = 0; + static KStaticDeleter staticIRCCharsetDeleter; + + IRCCharsets *IRCCharsets::self() + { + if(!s_self) + staticIRCCharsetDeleter.setObject(s_self, new IRCCharsets()); + return s_self; + } + + QStringList IRCCharsets::availableEncodingShortNames() + { + return m_shortNames; + } + + QStringList IRCCharsets::availableEncodingDescriptiveNames() + { + return m_descriptiveNames; + } + + int IRCCharsets::availableEncodingsCount() + { + return m_shortNames.count(); + } + + QString IRCCharsets::shortNameToDescriptiveName( const QString& shortName ) + { + return m_descriptiveNames[ shortNameToIndex( shortName ) ]; + } + + QString descriptiveNameToShortName( const QString& descriptiveName ) + { + return KGlobal::charsets()->encodingForName( descriptiveName ); + } + + QString IRCCharsets::ambiguousNameToShortName( const QString& ambiguousName ) + { + // simplify ambiguousName + QString simplifiedAmbiguousName( ambiguousName.lower() ); + simplifiedAmbiguousName.replace( QRegExp( "[^a-z0-9]" ), "" ); + + // search m_simplifiedShortNames + int index = 0; + for ( QStringList::iterator it = m_simplifiedShortNames.begin() ; it != m_simplifiedShortNames.end() ; ++it ) + { + if ( (*it) == simplifiedAmbiguousName ) + return m_shortNames[index]; + ++index; + } + + // search m_shortNameAliases + if ( m_shortNameAliases.contains( simplifiedAmbiguousName ) ) + return m_shortNameAliases[ simplifiedAmbiguousName ]; + + // failed + return QString(); + } + + int IRCCharsets::shortNameToIndex( const QString& shortName ) + { + int index = 0; + for ( QStringList::iterator it = m_shortNames.begin() ; it != m_shortNames.end() ; ++it ) + { + if ( (*it) == shortName ) + return index; + ++index; + } + return -1; + } + + bool IRCCharsets::isValidEncoding( const QString& shortName ) + { + return ( m_shortNames.contains( shortName ) > 0 ); + } + + QString IRCCharsets::encodingForLocale() + { + #if QT_VERSION < 0x030300 + QString locale = KLocale::defaultLanguage(); + #else + QString locale = QLocale::system().name(); + #endif + + // Special cases + // don't add conditions for the languages for which QTextCodec::codecForLocale() returns a correct codec. + if ( locale == "ja_JP" ) + return "jis7"; + + // it's a little hacky.. + for ( QStringList::iterator it = m_shortNames.begin() ; it != m_shortNames.end() ; ++it ) + if ( QTextCodec::codecForName( (*it).ascii() ) == QTextCodec::codecForLocale() ) + return *it; + + return "utf8"; + } + + QTextCodec* IRCCharsets::codecForName( const QString& shortName ) + { + if(shortName == "iso-2022-jp") + return QTextCodec::codecForName( "jis7" ); + else + return QTextCodec::codecForName( shortName.ascii() ); + } + + IRCCharsets::IRCCharsets() + { + s_self = this; + + // setup m_shortNameAliases + // use only [a-z0-9] for keys! + m_shortNameAliases["unicode"] = "utf8"; + m_shortNameAliases["latin1"] = "iso-8859-1"; + + // setup m_shortNames, m_descriptiveNames, m_simplifiedShortNames + QRegExp reSimplify( "[^a-zA-Z0-9]" ); + m_descriptiveNames = KGlobal::charsets()->descriptiveEncodingNames(); + QStringList::Iterator it = m_descriptiveNames.begin(); + while ( it != m_descriptiveNames.end() ) + { + QString encodingName = KGlobal::charsets()->encodingForName( *it ); + // exclude encodings which are not supported on IRC + if ( encodingName == "iso-10646-ucs-2" || + encodingName == "ucs2" || + encodingName == "utf16" || + encodingName == "utf7" ) + { + it = m_descriptiveNames.remove( it ); + } + else + { + m_shortNames.append( encodingName ); + m_simplifiedShortNames.append( encodingName.replace( reSimplify, "" ) ); + + if(encodingName == "jis7") // Add iso-2022-jp which is same as jis7 but not in Qt + { + it = m_descriptiveNames.insert(it, "Japanese ( iso-2022-jp )"); + m_shortNames.append( "iso-2022-jp" ); + m_simplifiedShortNames.append( "ISO-2022-JP" ); + ++it; + } + ++it; + } + + } + } + +} diff --git a/konversation/src/irccharsets.h b/konversation/src/irccharsets.h new file mode 100644 index 0000000..1f7facd --- /dev/null +++ b/konversation/src/irccharsets.h @@ -0,0 +1,106 @@ +// A wrapper for KCharsets +// Copyright (C) 2004 Shintaro Matsuoka + +/* + 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. +*/ + +#ifndef KONVERSATION_IRCCHARSETS_H +#define KONVERSATION_IRCCHARSETS_H + +#include +#include + + +namespace Konversation +{ + + class IRCCharsets + { + private: + IRCCharsets(); + + public: + static IRCCharsets *self(); + + /** + * Lists all available encoding names. + * e.g. "utf8", "iso 8859-1" + * Encodings which don't work on IRC are excluded. (e.g. utf16) + * @note It's guaranteed that the order of this list is same with that of @ref availableEncodingDescriptiveNames() . + */ + QStringList availableEncodingShortNames(); + + /** + * Lists all available encoding descriptions. + * e.g. "Unicode ( utf8 )", "Western European ( iso 8859-1 )" + * Encodings which don't work on IRC are excluded. (e.g. utf16) + */ + QStringList availableEncodingDescriptiveNames(); + + int availableEncodingsCount(); + + QString shortNameToDescriptiveName( const QString& shortName ); + QString descriptiveNameToShortName( const QString& descriptiveName ); + + /** + * Converts the ambiguous encoding name to a short encoding name + * Like : iso8859-9 -> iso 8859-9, iso-8859-9 -> iso 8859-9 + * If the ambiguous name is invalid, returns QString:null. + * @return a short encoding name or QString::null + */ + QString ambiguousNameToShortName( const QString& ambiguousName ); + + /** + * Returns the encoding index in the short names list or the descriptions list. + * If the encoding name is invalid, returns -1. + * @return an index number of the encoding + */ + int shortNameToIndex( const QString& shortName ); + + /** + * Checks if the encoding name is in the short encoding names. + * @see availableEncodingShortNames() + */ + bool isValidEncoding( const QString& shortName ); + + /** + * Returns the short name of the most suitable encoding for this locale. + * @return a short encoding name + */ + QString encodingForLocale(); + + QTextCodec* codecForName( const QString& shortName ); + + private: + QMap m_shortNameAliases; + + /** + * short names list + * you can get this list with @ref availableEncodingShortNames() + * e.g. iso 8859-1 + */ + QStringList m_shortNames; + + /** + * descriptive names list + * you can get this list with @ref availableEncodingDescriptiveNames(); + * e.g. Western European ( iso 8859-1 ) + */ + QStringList m_descriptiveNames; + + /** + * simplified short names list (for internal use) + * e.g. iso88591 + * used in @ref ambiguousNameToShortName() + */ + QStringList m_simplifiedShortNames; + + static IRCCharsets *s_self; + }; + +} +#endif // KONVERSATION_IRCCHARSETS_H diff --git a/konversation/src/irccolorchooser.cpp b/konversation/src/irccolorchooser.cpp new file mode 100644 index 0000000..3cf6ccf --- /dev/null +++ b/konversation/src/irccolorchooser.cpp @@ -0,0 +1,83 @@ +/* + 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. +*/ + +/* + dialog used to add irc colors to your messages + begin: Wed 9 July 2003 + copyright: (C) 2003 by Peter Simonsson + email: psn@linux.se +*/ + +#include "irccolorchooser.h" +#include "irccolorchooserui.h" +#include "config/preferences.h" + +#include +#include + +#include +#include + + +IRCColorChooser::IRCColorChooser(QWidget* parent, const char* name) +: KDialogBase(parent, name, true, i18n("IRC Color Chooser"), Ok|Cancel, Ok) +{ + m_view = new IRCColorChooserUI(this); + setMainWidget(m_view); + initColors(m_view->m_fgColorCBox); + initColors(m_view->m_bgColorCBox); + m_view->m_bgColorCBox->insertItem(i18n("None"), 0); + + connect(m_view->m_fgColorCBox, SIGNAL(activated(int)), this, SLOT(updatePreview())); + connect(m_view->m_bgColorCBox, SIGNAL(activated(int)), this, SLOT(updatePreview())); + m_view->m_fgColorCBox->setCurrentItem(1); + m_view->m_bgColorCBox->setCurrentItem(0); + updatePreview(); +} + +QString IRCColorChooser::color() +{ + QString s; + s = "%C" + QString::number(m_view->m_fgColorCBox->currentItem()); + + if(m_view->m_bgColorCBox->currentItem() > 0) + { + s += ',' + QString::number(m_view->m_bgColorCBox->currentItem() - 1); + } + + return s; +} + +void IRCColorChooser::updatePreview() +{ + QColor bgc; + + if(m_view->m_bgColorCBox->currentItem() > 0) + { + bgc = Preferences::ircColorCode(m_view->m_bgColorCBox->currentItem() - 1); + } + else + { + bgc = Preferences::color(Preferences::TextViewBackground); + } + + m_view->m_previewLbl->setBackgroundColor(bgc); + m_view->m_previewLbl->setPaletteForegroundColor(Preferences::ircColorCode(m_view->m_fgColorCBox->currentItem())); +} + +void IRCColorChooser::initColors(KComboBox* combo) +{ + QPixmap pix(width(), combo->fontMetrics().height() + 4); + + for (int i =0; i < 15; i++) + { + pix.fill(Preferences::ircColorCode(i)); + combo->insertItem(pix, i); + } +} + +#include "irccolorchooser.moc" diff --git a/konversation/src/irccolorchooser.h b/konversation/src/irccolorchooser.h new file mode 100644 index 0000000..d1357fa --- /dev/null +++ b/konversation/src/irccolorchooser.h @@ -0,0 +1,41 @@ +/* + 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. +*/ + +/* + dialog used to add irc colors to your messages + begin: Wed 9 July 2003 + copyright: (C) 2003 by Peter Simonsson + email: psn@linux.se +*/ + +#ifndef IRCCOLORCHOOSER_H +#define IRCCOLORCHOOSER_H + +#include + + +class IRCColorChooserUI; +class KComboBox; +class Preferences; + +class IRCColorChooser : public KDialogBase +{ + Q_OBJECT + public: + explicit IRCColorChooser(QWidget* parent, const char* name = 0); + QString color(); + + protected slots: + void updatePreview(); + + protected: + void initColors(KComboBox* combo); + + protected: + IRCColorChooserUI* m_view; +}; +#endif diff --git a/konversation/src/irccolorchooserui.ui b/konversation/src/irccolorchooserui.ui new file mode 100644 index 0000000..386824c --- /dev/null +++ b/konversation/src/irccolorchooserui.ui @@ -0,0 +1,148 @@ + +IRCColorChooserUI + + + IRCColorChooserUI + + + + 0 + 0 + 249 + 122 + + + + + unnamed + + + 0 + + + + m_previewLbl + + + Panel + + + Sunken + + + Preview + + + AlignCenter + + + This is how your message will look with these colors + + + <qt>This is a preview of how your readers may see view your message if you select these colors.<br> +<b>Note: Not all clients support this, and some users may have chosen to ignore your color changes.</b> +</qt> + + + + + m_fgColorCBox + + + + 5 + 0 + 0 + 0 + + + + The chosen text color is added to the input line. + + + <qt>Here you choose what color you want you the text in the next message you send to be. If you choose a color and click Ok, the chosen color is added to the Input Line. Any text written after this will be in the chosen color, until you change the color again.<br> +<b>Note: Not all users turn on the option to see this.</b></qt> + + + + + m_fgColorLbl + + + + 4 + 5 + 0 + 0 + + + + &Foreground color: + + + m_fgColorCBox + + + The chosen text color is added to the input line. + + + <qt>Here you choose what color you want you the text in the next message you send to be. If you choose a color and click Ok, the chosen color is added to the Input Line. Any text written after this will be in the chosen color, until you change the color again.<br> +<b>Note: Not all users turn on the option to see this.</b></qt> + + + + + m_bgColorCBox + + + true + + + + 5 + 0 + 0 + 0 + + + + The chosen text-background color is added to the input line. + + + <qt>Here you choose what color you want you background for the text in the next message you send to be. +If you choose a color and click Ok, the chosen color is added to the Input Line. +Any text written after this will have the chosen color, until you change the color again.<br> +Choosing the default "<i>None</i>" will not change the background color of your message, so your readers will view your message with their normal background text color.<br> +<b>Note: Not all clients support this, and not all users turn on the option to see this.</b></qt> + + + + + m_bgColorLbl + + + &Background color: + + + m_bgColorCBox + + + The chosen text-background color is added to the input line. + + + <qt>Here you choose what color you want you background for the text in the next message you send to be. +If you choose a color and click Ok, the chosen color is added to the Input Line. +Any text written after this will have the chosen color, until you change the color again.<br> +Choosing the default "<i>None</i>" will not change the background color of your message, so your readers will view your message with their normal background text color.<br> +<b>Note: Not all clients support this, and not all users turn on the option to see this.</b></qt> + + + + + + + + kcombobox.h + kcombobox.h + + diff --git a/konversation/src/ircinput.cpp b/konversation/src/ircinput.cpp new file mode 100644 index 0000000..b69c787 --- /dev/null +++ b/konversation/src/ircinput.cpp @@ -0,0 +1,551 @@ +/* + 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. +*/ + +/* + The line input widget with chat enhanced functions + begin: Tue Mar 5 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include "ircinput.h" +#include "konversationapplication.h" +#include "multilineedit.h" +#include "chatwindow.h" +#include "ircview.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define MAXHISTORY 100 +#define RICHTEXT 0 + + +IRCInput::IRCInput(QWidget* parent) : KTextEdit(parent) +{ + m_lastHeight=document()->height(); + + //I am not terribly interested in finding out where this value comes from + //nor in compensating for it if my guess is incorrect. so, cache it. + m_qtBoxPadding=m_lastHeight-fontMetrics().lineSpacing(); + + connect(KApplication::kApplication(), SIGNAL(appearanceChanged()), this, SLOT(updateAppearance())); + m_multiRow = Preferences::useMultiRowInputBox(); + + m_useSelection = false; + + // connect history signal + connect(this,SIGNAL (history(bool)) ,this,SLOT (getHistory(bool)) ); + // add one empty line to the history (will be overwritten with newest entry) + historyList.prepend(QString()); + // reset history line counter + lineNum=0; + // reset completion mode + setCompletionMode('\0'); + completionBox = new KCompletionBox(this); + connect(completionBox, SIGNAL(activated(const QString&)), this, SLOT(insertCompletion(const QString&))); + + // widget may not be resized vertically + setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Fixed)); + + //NoWrap coupled with the size policy constrains the line edit to be one row high + setWordWrap(m_multiRow ? WidgetWidth : NoWrap); + + setHScrollBarMode(AlwaysOff); + setVScrollBarMode(AlwaysOff); + #if RICHTEXT == 1 + setAutoFormatting(QTextEdit::AutoNone); + setTextFormat(RichText); + #else + setTextFormat(PlainText); + #endif + + QWhatsThis::add(this, i18n("The input line is where you type messages to be sent the channel, query, or server. A message sent to a channel is seen by everyone on the channel, whereas a message in a query is sent only to the person in the query with you.

To automatically complete the nickname you began typing, press Tab. If you have not begun typing, the last successfully completed nickname will be used.

You can also send special commands:
/me actionshows up as an action in the channel or query. For example: /me sings a song will show up in the channel as 'Nick sings a song'.
/whois nicknameshows information about this person, including what channels they are in.

For more commands, see the Konversation Handbook.

A message cannot contain multiple lines.")); + + m_disableSpellCheckTimer = new QTimer(this); + connect(m_disableSpellCheckTimer, SIGNAL(timeout()), this, SLOT(disableSpellChecking())); +} + +IRCInput::~IRCInput() +{ +} + +void IRCInput::showEvent(QShowEvent* /* e */) +{ + m_disableSpellCheckTimer->stop(); + setCheckSpellingEnabled(Preferences::spellChecking()); +} + +void IRCInput::hideEvent(QHideEvent* /* event */) +{ + Preferences::setSpellChecking(checkSpellingEnabled()); + + // If we disable spell-checking here immediately, tab switching will + // be very slow. If we delay it by five seconds, a user would have to + // need more than five seconds to switch between all his tabs before + // the slowdown starts to occur (show event stops the timer, i.e. wrap- + // around is not an issue). Unless he has unlikely amounts of channels, + // needing more than five seconds indicates very slow switching speed, + // which makes the delay a non-issue to begin with. Hence this fixes + // the problem on the surface. In the KDE 4 version, we want to look + // into having only one spell-checker instance instead of starting and + // stopping at all. + m_disableSpellCheckTimer->start(5000, true); +} + +void IRCInput::disableSpellChecking() +{ + setCheckSpellingEnabled(false); +} +void IRCInput::slotSpellCheckDone(const QString& s) +{ + // NOTE: kdelibs 3.5's KSpell stupidly adds newlines to its + // buffer at some point for god-knows-what-reason, and for- + // gets to remove them again before handing the result back. + // There's a FIXME to the effect in KSpell::check. This is + // a workaround. + + if (s == text() || s == (text() + '\n'+'\n')) + return; + + setText(s.simplifyWhiteSpace()); +} + +void IRCInput::updateAppearance() +{ + m_multiRow = Preferences::useMultiRowInputBox(); + setWordWrap(m_multiRow ? WidgetWidth : NoWrap); + m_lastHeight=heightForWidth(sizeHint().width()); + ensureCursorVisible(); //appears to trigger updateGeometry +} + +void IRCInput::resizeContents( int w, int h ) +{ + if (document()->height() != m_lastHeight) { + m_lastHeight=document()->height(); + updateGeometry(); + } + KTextEdit::resizeContents(w,h); +} + +// widget must be only one line high - luckily QT will enforce this via wrappping policy +QSize IRCInput::sizeHint() const +{ + constPolish(); + + int ObscurePadding = 4; + int f=2*frameWidth(); + int w=12 * (kMax(fontMetrics().lineSpacing(),14) + f + ObscurePadding); + int h=m_lastHeight - m_qtBoxPadding + f + ObscurePadding; + return QSize(w,h); +} + +QPopupMenu *IRCInput::createPopupMenu( const QPoint &pos ) +{ + QPopupMenu *menu=KTextEdit::createPopupMenu(pos); + menu->removeItemAt(menu->count()-1); + menu->removeItemAt(menu->count()-1); + return menu; +} + +QString IRCInput::text() const +{ + #if RICHTEXT == 1 + QString content=KTextEdit::text(); + + QDomDocument document; + + document.setContent(content,false); + QDomNodeList nodes=document.elementsByTagName("p"); + if(nodes.count()) + { + QDomElement node=nodes.item(0).toElement(); + return node.text(); + } + return QString(); + + #else + return KTextEdit::text(); + #endif +} + +void IRCInput::setText(const QString& text) +{ + // reimplemented to set cursor at the end of the new text + KTextEdit::setText(text); + setCursorPosition(0,text.length()+1); +} + +// FIXME - find a better way to do this. eventfilters introduce nebulous behaviour +//take text events from IRCView and TopicLabel +bool IRCInput::eventFilter(QObject *object,QEvent *event) +{ + if (object->isA("IRCView") || object->isA("Konversation::TopicLabel")) + { + if (event->type() == QEvent::KeyPress) + { + QKeyEvent* ke = static_cast(event); + + // Allow tab to be handled naturally by the widget. + // Once it runs out of links it goes to the next control. + if (ke->key() == Key_Tab && (ke->state() == 0 || ke->state() == Qt::ShiftButton)) + return false; + + if (!ke->text().isEmpty() && ((ke->state() & (Qt::ShiftButton|Qt::Keypad)) || ke->state() == 0)) + { + setFocus(); + KonversationApplication::sendEvent(this,event); + return true; + } + } + } + + return KTextEdit::eventFilter(object,event); +} + +// Take care of Tab, Cursor and so on +void IRCInput::keyPressEvent(QKeyEvent* e) +{ + switch(e->key()) + { + case Key_Tab: + emit nickCompletion(); + return; + break; + + case Key_Up: + if (m_multiRow && (e->state() != (Qt::ShiftButton|Qt::ControlButton))) + break; + emit history(true); + return; + break; + + case Key_Down: + if (m_multiRow && (e->state() != (Qt::ShiftButton|Qt::ControlButton))) + break; + emit history(false); + return; + break; + + case Key_Enter: + case Key_Return: + { + if(text().length()) addHistory(text()); + if(completionBox->isHidden()) + { + // Reset completion mode + setCompletionMode('\0'); + + // Ctrl+Enter is a special case in which commands should be send as normal messages + if ( e->state() & ControlButton ) + { + emit envelopeCommand(); + } + else + { + setText(static_cast(kapp)->doAutoreplace(text(),true)); + emit submit(); + } + } + else + { + insertCompletion(completionBox->currentText()); + completionBox->hide(); + } + // prevent widget from adding lines + return; + } + break; + + default: + // Check if the keystroke actually produced text. If not it was just a qualifier. + if(!e->text().isEmpty() || ((e->key() >= Qt::Key_Home) && (e->key() <= Qt::Key_Down))) + { + if(getCompletionMode()!='\0') + { + setCompletionMode('\0'); + emit endCompletion(); + } + + completionBox->hide(); + } + + // support ASCII BEL + if(e->ascii() == 7) + insert("%G"); + // support ^U (delete text in input box) + else if(e->ascii() == 21) + setText(""); + } + + KTextEdit::keyPressEvent(e); +} + +void IRCInput::addHistory(const QString& line) +{ + // Only add line if it's not the same as the last was + if(historyList[1]!=line) + { + // Replace empty first entry with line + historyList[0]=line; + // Add new empty entry to history + historyList.prepend(QString()); + // Remove oldest line in history, if the list grows beyond MAXHISTORY + if(historyList.count()>MAXHISTORY) historyList.remove(historyList.last()); + } + // Reset history counter + lineNum=0; +} + +void IRCInput::getHistory(bool up) +{ + // preserve text + historyList[lineNum]=text(); + // Did the user press cursor up? + if(up) + { + // increment the line counter + lineNum++; + // if we are past the end of the list, go to the last entry + if(lineNum==historyList.count()) lineNum--; + } + // no, it was cursor down + else + { + // If we are at the top of the lest, arrow-down shall add the text to the history and clear the field for new input + if(lineNum==0) + { + if(text().length()) addHistory(text()); + setText(""); + } + // If we aren't at the top of the list, decrement the line counter + else + { + lineNum--; + } + } + // replace the text in the input field with history + setText(historyList[lineNum]); +} + +/** + * Work around the fact that while QTextEdit::paste() is virtual, whether we are + * pasting from middle button or control-V is PRIVATE and NO ACCESSOR is given. + */ +void IRCInput::contentsMouseReleaseEvent( QMouseEvent *ev) +{ + if (ev->button() == Qt::MidButton) + { + m_useSelection=true; + } + + // Reset completion + setCompletionMode('\0'); + emit endCompletion(); + + KTextEdit::contentsMouseReleaseEvent(ev); + m_useSelection=false; +} + +void IRCInput::paste(bool useSelection) +{ + m_useSelection = useSelection; + paste(); + m_useSelection = false; +} + +void IRCInput::paste() +{ + QClipboard *cb = KApplication::kApplication()->clipboard(); + setFocus(); + + // Copy text from the clipboard (paste) + QString pasteText; + if(m_useSelection) + { + pasteText = cb->text( QClipboard::Selection); + } + else + { + pasteText = cb->text( QClipboard::Clipboard); + } + + // is there any text in the clipboard? + if(!pasteText.isEmpty()) + { + //End completion on paste + setCompletionMode('\0'); + emit endCompletion(); + + bool signal=false; + + // replace \r with \n to make xterm pastes happy + pasteText.replace("\r","\n"); + // remove blank lines + while(pasteText.contains("\n\n")) + pasteText.replace("\n\n","\n"); + + QRegExp reTopSpace("^ *\n"); + while(pasteText.contains(reTopSpace)) + pasteText.remove(reTopSpace); + + QRegExp reBottomSpace("\n *$"); + while(pasteText.contains(reBottomSpace)) + pasteText.remove(reBottomSpace); + + // Escape % when var expansion is enabled + if (!Preferences::disableExpansion()) + { + pasteText.replace ('%', "%%"); + } + + // does the text contain at least one newline character? + if(pasteText.find('\n')!=-1) + { + // make comparisons easier (avoid signed / unsigned warnings) + unsigned int pos=pasteText.find('\n'); + unsigned int rpos=pasteText.findRev('\n'); + + // emit the signal if there's a line break in the middle of the text + if(pos>0 && pos!=(pasteText.length()-1)) + signal=true; + // emit the signal if there's more than one line break in the text + if(pos!=rpos) + signal=true; + + // Remove the \n from end of the line if there's only one \n + if(!signal) + pasteText.remove('\n'); + } + else + { + insert(pasteText); + return; + } + + // should we signal the application due to newlines in the paste? + if(signal) + { + // if there is text in the input line + if(!text().isEmpty()) + { + // prepend text to the paste + pasteText=text()+'\n'+pasteText; + } + // ask the user on long pastes + if(checkPaste(pasteText)) + { + // signal pasted text + emit textPasted(pasteText); + // remember old line, in case the user does not paste eventually + addHistory(pasteText); + // delete input text + setText(""); + } + } + // otherwise let the KLineEdit handle the pasting + else KTextEdit::paste(); + } +} + +bool IRCInput::checkPaste(QString& text) +{ + int doPaste=KMessageBox::Yes; + + //text is now preconditioned when you get here + int lines=text.contains('\n'); + + if(text.length()>256 || lines) + { + doPaste=KMessageBox::warningYesNoCancel + (this, + i18n("You are attempting to paste a large portion of text (%1 bytes or %2 lines) into " + "the chat. This can cause connection resets or flood kills. " + "Do you really want to continue?").arg(text.length()).arg(lines+1), + i18n("Large Paste Warning"), + i18n("Paste"), + i18n("&Edit..."), + "LargePaste", + KMessageBox::Dangerous); + } + + if (doPaste==KMessageBox::No) + { + QString ret(MultilineEdit::edit(this,text)); + if (ret.isEmpty()) + return false; + text=ret; + return true; + } + + return (doPaste==KMessageBox::Yes); +} + +void IRCInput::showCompletionList(const QStringList& nicks) +{ + completionBox->setItems(nicks); + completionBox->popup(); +} + +void IRCInput::insertCompletion(const QString& nick) +{ + int pos; // = cursorPosition(); + int oldPos; // = cursorPosition(); + + getCursorPosition(&oldPos,&pos); + oldPos=pos; + + QString line = text(); + + while(pos && line[pos-1] != ' ') pos--; + + line.remove(pos, oldPos - pos); + + // did we find the nick in the middle of the line? + if(pos) + { + QString addMiddle(Preferences::nickCompleteSuffixMiddle()); + line.insert(pos, nick + addMiddle); + pos += nick.length() + addMiddle.length(); + } + // no, it was at the beginning + else + { + setLastCompletion(nick); + QString addStart(Preferences::nickCompleteSuffixStart()); + line.insert(pos, nick + addStart); + pos += nick.length() + addStart.length(); + } + + setText(line); + setCursorPosition(0,pos); +} + +void IRCInput::setLastCompletion(const QString& completion) +{ + m_lastCompletion = completion; +} + +// Accessor methods + +void IRCInput::setCompletionMode(char mode) { completionMode=mode; } +char IRCInput::getCompletionMode() { return completionMode; } +void IRCInput::setOldCursorPosition(int pos) { oldPos=pos; } +int IRCInput::getOldCursorPosition() { return oldPos; } + +#include "ircinput.moc" diff --git a/konversation/src/ircinput.h b/konversation/src/ircinput.h new file mode 100644 index 0000000..85e42c1 --- /dev/null +++ b/konversation/src/ircinput.h @@ -0,0 +1,91 @@ +/* + 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. +*/ + +/* + The line input widget with chat enhanced functions + begin: Tue Mar 5 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#ifndef IRCINPUT_H +#define IRCINPUT_H + +#include + +#include + + +class KCompletionBox; +class QMouseEvent; + +class IRCInput : public KTextEdit +{ + Q_OBJECT + + public: + explicit IRCInput(QWidget* parent); + ~IRCInput(); + + void setCompletionMode(char mode); + char getCompletionMode(); + void setOldCursorPosition(int pos); + int getOldCursorPosition(); + QString lastCompletion() const { return m_lastCompletion; } + + virtual QSize sizeHint() const; + QString text() const; + + signals: + void nickCompletion(); + void endCompletion(); // tell channel that completion phase is over + void history(bool up); + void textPasted(const QString& text); + void submit(); + void envelopeCommand(); + + public slots: + void paste(); + void paste(bool useSelection); + void showCompletionList(const QStringList& nicks); + void setText(const QString& text); + void setLastCompletion(const QString& completion); + virtual void setOverwriteMode(bool) { } + virtual void resizeContents( int w, int h ); + virtual void updateAppearance(); + + protected slots: + void getHistory(bool up); + void insertCompletion(const QString& nick); + void disableSpellChecking(); + virtual void slotSpellCheckDone(const QString& s); + + protected: + bool eventFilter(QObject *object,QEvent *event); + void addHistory(const QString& text); + bool checkPaste(QString& text); + void contentsMouseReleaseEvent(QMouseEvent *); + + virtual void keyPressEvent(QKeyEvent* e); + virtual QPopupMenu *createPopupMenu( const QPoint& pos ); + virtual void showEvent(QShowEvent* e); + virtual void hideEvent(QHideEvent* e); + + QStringList historyList; + unsigned int lineNum; + unsigned int oldPos; + char completionMode; + KCompletionBox* completionBox; + QString m_lastCompletion; + bool m_useSelection; + bool m_multiRow; + int m_lastHeight; //essentially corresponds to qtextbrowser::doc->height() + int m_qtBoxPadding; //see comment in constructor + + QTimer* m_disableSpellCheckTimer; +}; +#endif diff --git a/konversation/src/ircqueue.cpp b/konversation/src/ircqueue.cpp new file mode 100644 index 0000000..c80ceca --- /dev/null +++ b/konversation/src/ircqueue.cpp @@ -0,0 +1,209 @@ +/* + 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) version 2. +*/ + +/* + Copyright (C) 2008 Eli J. MacKenzie +*/ + +#include +#include +#include + +#include "ircqueue.h" +#include "server.h" + +//#include "/home/ejm/argnl.h" + +IRCQueue::EmptyingRate staticrates[Server::Howmanyqueuesdoweneedanywayquestionmark]; /*= + { + IRCQueue::EmptyingRate(6,60000) + ,IRCQueue::EmptyingRate(20,60000) + ,IRCQueue::EmptyingRate(1,1000)//,IRCQueue::EmptyingRate::Bytes) + }; +*/ + +int IRCQueue::EmptyingRate::nextInterval(int, int elapsed) +{ + if (!isValid()) + return 0; + //KX << _S(m_interval) << endl; + if (m_type == Lines) + { + int i = m_interval/m_rate; + //KX << _S(i) << endl; + if (iisConnected()); + } +} + +IRCQueue::~IRCQueue() +{ + kdDebug() << "~IRCQueue" << endl; +} + +QString IRCQueue::pop() +{ + if (m_pending.isEmpty()) + return QString(""); + + IRCMessage msg=m_pending.first(); + m_pending.pop_front(); + m_lastWait=msg.age(); + m_lastSent=QTime::currentTime(); + return msg.text(); +} + +int IRCQueue::nextSize() +{ + if (m_pending.isEmpty()) + return 0; + return m_pending.first().text().length(); +} + +int IRCQueue::currentWait() +{ + if (m_pending.isEmpty()) + return 0; + return m_pending.first().age(); +} + +int IRCQueue::elapsed() +{ + if (m_startedAt.isNull()) + return 0; + else + return m_startedAt.elapsed(); //FIXME if its been more than a day since this queue was used, this breaks +} + +int IRCQueue::linesSent() const +{ + return m_linesSent; +} + +int IRCQueue::bytesSent() const +{ + return m_bytesSent; +} + +///Feedback indicating size of data sent to update statistics. Not necessarily data from this queue!!! +void IRCQueue::sent(int, int e, IRCQueue *wq) +{ + //KX << k_funcinfo << _S(m_mine) << endl; + m_globalLinesSent++; + m_globalBytesSent+=e; // we don't care about the unencoded bytes, we want what went to the server + if (wq == this) { + m_linesSent++; + m_bytesSent+=e; + } +} + +void IRCQueue::enqueue(QString line) +{ + m_pending.append(IRCMessage(line)); + if (!m_timer->isActive()) + adjustTimer(); +} + +//starts timer if stopped, adjusts interval if necessary +void IRCQueue::adjustTimer() +{ + int msec; + msec=getRate().nextInterval(nextSize(), elapsed()); + //if (m_myIndex == 0) + // KX << _S(msec) << endl; + m_timer->start(msec,true); + m_startedAt.start(); + return; +} + +bool IRCQueue::doSend() +{ + bool p=!m_pending.isEmpty(); + if (p) + { + // int plw = m_lastWait; + QString s=pop(); + //if (m_myIndex == 0) + // KX << _S(plw) << _S(m_lastWait) << endl; + m_server->toServer(s, this); + m_startedAt.start(); + } + return p;//if we sent something, fire the timer again +} + +///it would probably be better to delete and recreate the queue. +void IRCQueue::reset() +{ + // KX << k_funcinfo << endl; + m_timer->stop(); + m_lastWait=0; + if (m_server) + m_blocked=!(m_server->isConnected()); //FIXME (maybe) "we can't do this anymore because blocked can't correspond to whether the server is online, instead must correspond to whether the socket has become writable (readyWrite)" + + m_startedAt=m_globalLastSent=m_lastSent=QTime(); + m_pending.clear(); + m_linesSent=m_bytesSent=m_globalBytesSent=m_globalLinesSent=0; +} + +//called when the timer fires. +void IRCQueue::sendNow() +{ + if (doSend()) + adjustTimer(); + //else //its a single-shot timer so if we don't adjust it, it won't run :) +} + +///lets us know we should block output +void IRCQueue::serverOnline(bool on) +{ + if (m_blocked!=on) + return; + m_blocked=!on; + if (m_blocked && m_timer->isActive()) + reset(); + else if (!m_blocked && !m_timer->isActive() && nextSize()) + { + adjustTimer(); + } +} + +#include "ircqueue.moc" diff --git a/konversation/src/ircqueue.h b/konversation/src/ircqueue.h new file mode 100644 index 0000000..c80c329 --- /dev/null +++ b/konversation/src/ircqueue.h @@ -0,0 +1,137 @@ +/* + 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) version 2. +*/ + +/* + Copyright (C) 2008 Eli J. MacKenzie +*/ + + +#ifndef IRCQUEUE_H +#define IRCQUEUE_H + +class Server; + +//channel.cpp, outputfilter.cpp, query.cpp, server.cpp, statuspanel.cpp + +/** + * A message from or to an IRC server. + * + * Contains all we know about the message, which currently consists of the text, the time it was created, + * and its original encoding. (Since currently these objects are only used internally, we know the message + * is Unicode.) + */ +struct IRCMessage +{ + IRCMessage() : t(QTime::currentTime()) //, codec(QTextCodec::codecForName("utf8")) + {} ///< this constructor required for QValueList, do not use + + /** + Make a new IRCMessage with timestamp of QTime::currentTime(). + + Note the constructor takes a QString, not a const QString& or a QString *. If you want to modify the + contained text, put it back with setText. + */ + IRCMessage(QString i) : s(i), t(QTime::currentTime()) //, codec(QTextCodec::codecForName("utf8")) + {} + + QString text() { return s; } + int age() { return t.elapsed(); } + QTime time() { return t; } + void setText(QString text) { s=text; } +private: + QString s; + QTime t; + + //FIXME wire this up + //QTextCodec* codec; + //operator const char * () const { return codec->fromUnicode(text()); } + +}; + +/** +* Provides a self-sending queue of IRCMessages. +* +* Messages enqueued in this server can only be erased via reset() or sent to the attached server. +* The server and the emptying rates cannot be changed, if you want to do that construct a new queue. + +*/ +class IRCQueue: public QObject +{ + Q_OBJECT + +public: + struct EmptyingRate + { + enum RateType { + Lines, ///< Lines per interval. + Bytes ///< Bytes per interval. Not implemented. FIXME + }; + EmptyingRate(int rate=6, int msec_interval=50000, RateType type=Lines): + m_rate(rate), m_interval(msec_interval), m_type(type) + { + } + + int nextInterval(int byte_size, int msec_since_last); + + int m_rate; + int m_interval; + RateType m_type; + bool isValid() { return m_rate > 0; } + }; + + IRCQueue(Server *server, EmptyingRate& rate, int myindex=0); + ~IRCQueue(); + + void enqueue(QString line); + void reset(); + EmptyingRate& getRate();// { return &m_rate; } + + bool isValid() { return m_rate.isValid(); } + bool isEmpty() { return m_pending.isEmpty(); } + + //WTF? why are there two of these. + //These are decoupled for a reason, what is it? + int currentWait(); ///< Time in ms that the front has been waiting + int elapsed(); ///< How long has the queue been running since it was last started? + + int nextSize(); ///< Current size of front + int pendingMessages() { return m_pending.count(); } + int linesSent() const; ///< count of lines sent by this queue + int bytesSent() const; ///< count of bytes sent by this queue + + ///Time in milliseconds that the previous message waited + int lastWait() { return m_lastWait; } + +public slots: + void sent(int bytes, int encodedBytes, IRCQueue *); ///< feedback statistics + void sendNow(); ///< dumps a line to the socket + void serverOnline(bool on); ///< server tells us that the socket is ready + +protected: + QString pop(); ///< pops front, sets statistics + void adjustTimer(); ///< sets the next timer interval + bool doSend(); ///< pops front and tells the server to send it. returns true if we sent something + EmptyingRate& m_rate; + +private: + QValueList m_pending; + QTimer *m_timer; + bool m_blocked; + bool m_online; + Server *m_server; + + QTime m_startedAt; + QTime m_lastSent, m_globalLastSent; + int m_linesSent, m_globalLinesSent; + int m_bytesSent, m_globalBytesSent; + int m_lastWait; + int m_myIndex; +}; + +extern IRCQueue::EmptyingRate staticrates[]; + +#endif diff --git a/konversation/src/ircview.cpp b/konversation/src/ircview.cpp new file mode 100644 index 0000000..3b4108a --- /dev/null +++ b/konversation/src/ircview.cpp @@ -0,0 +1,1791 @@ +// -*- mode: c++; c-file-style: "bsd"; c-basic-offset: 4; tabs-width: 4; indent-tabs-mode: nil -*- + +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2005-2007 Peter Simonsson + Copyright (C) 2006-2008 Eike Hein +*/ + +#include "ircview.h" +#include "channel.h" +#include "dccchat.h" +#include "konversationapplication.h" +#include "konversationmainwindow.h" +#include "viewcontainer.h" +#include "connectionmanager.h" +#include "highlight.h" +#include "server.h" +#include "konversationsound.h" +#include "common.h" +#include "emoticon.h" +#include "notificationhandler.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +IRCView::IRCView(QWidget* parent, Server* newServer) : KTextBrowser(parent) +{ + m_copyUrlMenu = false; + m_resetScrollbar = true; + m_offset = 0; + m_mousePressed = false; + m_isOnNick = false; + m_isOnChannel = false; + m_chatWin = 0; + m_findParagraph=0; + m_findIndex=0; + m_nickPopup = 0; + m_channelPopup = 0; + + m_rememberLineParagraph = -1; + m_rememberLineDirtyBit = false; + + m_disableEnsureCursorVisible = false; + m_wasPainted = false; + + setAutoFormatting(QTextEdit::AutoNone); + setUndoRedoEnabled(0); + setLinkUnderline(false); + setVScrollBarMode(AlwaysOn); + setHScrollBarMode(AlwaysOff); + setWrapPolicy(QTextEdit::AtWordOrDocumentBoundary); + setNotifyClick(true); + setFocusPolicy(QWidget::ClickFocus); + + // set basic style sheet for

to make paragraph spacing possible + QStyleSheet* sheet=new QStyleSheet(this,"ircview_style_sheet"); + new QStyleSheetItem(sheet,"p"); + setStyleSheet(sheet); + + m_popup = new QPopupMenu(this,"ircview_context_menu"); + toggleMenuBarSeparator = m_popup->insertSeparator(); + m_popup->setItemVisible(toggleMenuBarSeparator, false); + copyUrlMenuSeparator = m_popup->insertSeparator(); + m_popup->setItemVisible(copyUrlMenuSeparator, false); + m_popup->insertItem(SmallIconSet("editcopy"),i18n("&Copy"),Copy); + m_popup->insertItem(i18n("Select All"),SelectAll); + m_popup->insertItem(SmallIcon("find"),i18n("Find Text..."),Search); + + setServer(newServer); + + setViewBackground(Preferences::color(Preferences::TextViewBackground),QString()); + + if (Preferences::customTextFont()) + setFont(Preferences::textFont()); + else + setFont(KGlobalSettings::generalFont()); + + if (Preferences::useParagraphSpacing()) enableParagraphSpacing(); + + connect(this, SIGNAL(highlighted(const QString&)), this, SLOT(highlightedSlot(const QString&))); +} + +IRCView::~IRCView() +{ + delete m_popup; +} + +void IRCView::enableParagraphSpacing() +{ + // Set style sheet for

to define paragraph spacing. + QStyleSheet* sheet = styleSheet(); + + if (!sheet) return; + + QStyleSheetItem* style = sheet->item("p"); + + if (!style) + { + kdDebug() << "IRCView::updateStyleSheet(): style == 0!" << endl; + + return; + } + + style->setDisplayMode(QStyleSheetItem::DisplayBlock); + style->setMargin(QStyleSheetItem::MarginVertical, Preferences::paragraphSpacing()); + style->setSelfNesting(false); +} + +void IRCView::setViewBackground(const QColor& backgroundColor, const QString& pixmapName) +{ + QPixmap backgroundPixmap; + backgroundPixmap.load(pixmapName); + + if(backgroundPixmap.isNull()) + { + setPaper(backgroundColor); + } + else + { + QBrush backgroundBrush; + backgroundBrush.setColor(backgroundColor); + backgroundBrush.setPixmap(backgroundPixmap); + setPaper(backgroundBrush); + } +} + +void IRCView::setServer(Server* newServer) +{ + m_server = newServer; + + if (newServer) + { + KAction *action = newServer->getViewContainer()->actionCollection()->action("open_logfile"); + Q_ASSERT(action); + if(!action) return; + m_popup->insertSeparator(); + action->plug(m_popup); + } + +} + +const QString& IRCView::getContextNick() const +{ + return m_currentNick; +} + +void IRCView::clearContextNick() +{ + m_currentNick = QString(); +} + +void IRCView::clear() +{ + m_buffer = QString(); + KTextBrowser::setText(""); + wipeLineParagraphs(); +} + +void IRCView::highlightedSlot(const QString& _link) +{ + QString link = _link; + // HACK Replace % with \x03 in the url to keep Qt from doing stupid things + link = link.replace ('\x03', "%"); + //Hack to handle the fact that we get a decoded url + link = KURL::fromPathOrURL(link).url(); + + // HACK:Use space as a placeholder for \ as Qt tries to be clever and does a replace to / in urls in QTextEdit + if(link.startsWith("#")) + { + link = link.replace(' ', "\\"); + } + + //we just saw this a second ago. no need to reemit. + if (link == m_lastStatusText && !link.isEmpty()) + return; + + // remember current URL to overcome link clicking problems in QTextBrowser + m_highlightedURL = link; + + if (link.isEmpty()) + { + if (!m_lastStatusText.isEmpty()) + { + emit clearStatusBarTempText(); + m_lastStatusText = QString(); + } + } else + { + m_lastStatusText = link; + } + + if(!link.startsWith("#")) + { + m_isOnNick = false; + m_isOnChannel = false; + + if (!link.isEmpty()) { + //link therefore != m_lastStatusText so emit with this new text + emit setStatusBarTempText(link); + } + if (link.isEmpty() && m_copyUrlMenu) + { + m_popup->removeItem(CopyUrl); + m_popup->removeItem(Bookmark); + m_popup->removeItem(SaveAs); + m_popup->setItemVisible(copyUrlMenuSeparator, false); + m_copyUrlMenu = false; + + } + else if (!link.isEmpty() && !m_copyUrlMenu) + { + m_popup->setItemVisible(copyUrlMenuSeparator, true); + m_popup->insertItem(SmallIcon("editcopy"), i18n("Copy URL to Clipboard"), CopyUrl, 1); + m_popup->insertItem(SmallIcon("bookmark"), i18n("Add to Bookmarks"), Bookmark, 2); + m_popup->insertItem(SmallIcon("filesaveas"), i18n("Save Link As..."), SaveAs, 3); + m_copyUrlMenu = true; + m_urlToCopy = link; + } + } + else if (link.startsWith("#") && !link.startsWith("##")) + { + m_currentNick = link.mid(1); + m_nickPopup->changeTitle(m_nickPopupId,m_currentNick); + m_isOnNick = true; + emit setStatusBarTempText(i18n("Open a query with %1").arg(m_currentNick)); + } + else + { + // link.startsWith("##") + m_currentChannel = link.mid(1); + + QString prettyId = m_currentChannel; + + if (prettyId.length()>15) + { + prettyId.truncate(15); + prettyId.append("..."); + } + + m_channelPopup->changeTitle(m_channelPopupId,prettyId); + m_isOnChannel = true; + emit setStatusBarTempText(i18n("Join the channel %1").arg(m_currentChannel)); + } +} + +void IRCView::openLink(const QString& url, bool newTab) +{ + if (!url.isEmpty() && !url.startsWith("#")) + { + if (url.startsWith("irc://")) + { + KonversationApplication* konvApp = static_cast(kapp); + konvApp->getConnectionManager()->connectTo(Konversation::SilentlyReuseConnection, url); + } + else if (!Preferences::useCustomBrowser() || url.startsWith("mailto:")) + { + if(newTab && !url.startsWith("mailto:")) + { + QCString foundApp, foundObj; + QByteArray data; + QDataStream str(data, IO_WriteOnly); + if( KApplication::dcopClient()->findObject("konqueror*", "konqueror-mainwindow*", + "windowCanBeUsedForTab()", data, foundApp, foundObj, false, 3000)) + { + DCOPRef ref(foundApp, foundObj); + ref.call("newTab", url); + } else + new KRun(KURL::fromPathOrURL(url)); + } else + new KRun(KURL::fromPathOrURL(url)); + } + else + { + QString cmd = Preferences::webBrowserCmd(); + cmd.replace("%u", url); + KProcess *proc = new KProcess; + QStringList cmdAndArgs = KShell::splitArgs(cmd); + *proc << cmdAndArgs; + // This code will also work, but starts an extra shell process. + // kdDebug() << "IRCView::urlClickSlot(): cmd = " << cmd << endl; + // *proc << cmd; + // proc->setUseShell(true); + proc->start(KProcess::DontCare); + delete proc; + } + } + //FIXME: Don't do channel links in DCC Chats to begin with since they don't have a server. + else if (url.startsWith("##") && m_server && m_server->isConnected()) + { + QString channel(url); + channel.replace("##", "#"); + m_server->sendJoinCommand(channel); + } + //FIXME: Don't do user links in DCC Chats to begin with since they don't have a server. + else if (url.startsWith("#") && m_server && m_server->isConnected()) + { + QString recipient(url); + recipient.remove("#"); + NickInfoPtr nickInfo = m_server->obtainNickInfo(recipient); + m_server->addQuery(nickInfo, true /*we initiated*/); + } +} + +void IRCView::replaceDecoration(QString& line, char decoration, char replacement) +{ + int pos; + bool decorated = false; + + while((pos=line.find(decoration))!=-1) + { + line.replace(pos,1,(decorated) ? QString("").arg(replacement) : QString("<%1>").arg(replacement)); + decorated = !decorated; + } +} + +QString IRCView::filter(const QString& line, const QString& defaultColor, const QString& whoSent, +bool doHighlight, bool parseURL, bool self) +{ + QString filteredLine(line); + KonversationApplication* konvApp = static_cast(kapp); + + //Since we can't turn off whitespace simplification withouteliminating text wrapping, + // if the line starts with a space turn it into a non-breaking space. + // (which magically turns back into a space on copy) + + if (filteredLine[0]==' ') + filteredLine[0]='\xA0'; + + // TODO: Use QStyleSheet::escape() here + // Replace all < with < + filteredLine.replace("<","\x0blt;"); + // Replace all > with > + filteredLine.replace(">", "\x0bgt;"); + + #if 0 + if(!Preferences::disableExpansion()) + { + QRegExp boldRe("\\*\\*([a-zA-Z0-9]+)\\*\\*"); + QRegExp underRe("\\_\\_([a-zA-Z0-9]+)\\_\\_"); + int position = 0; + QString replacement; + + while( position >= 0) + { + position = boldRe.search(filteredLine, position); + if( position > -1) + { + replacement = boldRe.cap(1); + replacement = "\x02"+replacement+"\x02"; + filteredLine.replace(position,replacement.length()+2,replacement); + } + position += boldRe.matchedLength(); + } + + position = 0; + while( position >= 0) + { + position = underRe.search(filteredLine, position); + if( position > -1) + { + replacement = underRe.cap(1); + replacement = "\x1f"+replacement+"\x1f"; + filteredLine.replace(position,replacement.length()+2,replacement); + } + position += underRe.matchedLength(); + } + } + #endif + + if(filteredLine.find("\x07") != -1) + { + if(Preferences::beep()) + { + kapp->beep(); + } + } + + // replace \003 and \017 codes with rich text color codes + // captures 1 2 23 4 4 3 1 + QRegExp colorRegExp("(\003([0-9]|0[0-9]|1[0-5]|)(,([0-9]|0[0-9]|1[0-5])|,|)|\017)"); + + int pos; + bool allowColors = Preferences::allowColorCodes(); + bool firstColor = true; + QString colorString; + + while((pos=colorRegExp.search(filteredLine))!=-1) + { + if(!allowColors) + { + colorString = QString(); + } + else + { + colorString = (firstColor) ? QString::null : QString(""); + + // reset colors on \017 to default value + if(colorRegExp.cap(1) == "\017") + colorString += ""; + else + { + if(!colorRegExp.cap(2).isEmpty()) + { + int foregroundColor = colorRegExp.cap(2).toInt(); + colorString += ""; + } + else + { + colorString += ""; + } + } + + firstColor = false; + } + + filteredLine.replace(pos, colorRegExp.cap(0).length(), colorString); + } + + if(!firstColor) + filteredLine+=""; + + // Replace all text decorations + // TODO: \017 should reset all textt decorations to plain text + replaceDecoration(filteredLine,'\x02','b'); + replaceDecoration(filteredLine,'\x09','i'); + replaceDecoration(filteredLine,'\x13','s'); + replaceDecoration(filteredLine,'\x15','u'); + replaceDecoration(filteredLine,'\x16','b'); // should be inverse + replaceDecoration(filteredLine,'\x1f','u'); + + if(parseURL) + { + filteredLine = Konversation::tagURLs(filteredLine, whoSent); + } + else + { + // Change & to & to prevent html entities to do strange things to the text + filteredLine.replace('&', "&"); + filteredLine.replace("\x0b", "&"); + } + + filteredLine = Konversation::EmotIcon::filter(filteredLine, fontMetrics()); + + // Highlight + QString ownNick; + + if (m_server) + { + ownNick = m_server->getNickname(); + } + else if (m_chatWin->getType() == ChatWindow::DccChat) + { + ownNick = static_cast(m_chatWin)->getOwnNick(); + } + + if(doHighlight && (whoSent != ownNick) && !self) + { + QString highlightColor; + + if(Preferences::highlightNick() && + filteredLine.lower().find(QRegExp("(^|[^\\d\\w])" + + QRegExp::escape(ownNick.lower()) + + "([^\\d\\w]|$)")) != -1) + { + // highlight current nickname + highlightColor = Preferences::highlightNickColor().name(); + m_tabNotification = Konversation::tnfNick; + } + else + { + QPtrList highlightList = Preferences::highlightList(); + QPtrListIterator it(highlightList); + Highlight* highlight = it.current(); + bool patternFound = false; + int index = 0; + + QStringList captures; + while(highlight) + { + if(highlight->getRegExp()) + { + QRegExp needleReg=highlight->getPattern(); + needleReg.setCaseSensitive(false); + // highlight regexp in text + patternFound = ((filteredLine.find(needleReg) != -1) || + // highlight regexp in nickname + (whoSent.find(needleReg) != -1)); + + // remember captured patterns for later + captures=needleReg.capturedTexts(); + + } + else + { + QString needle=highlight->getPattern(); + // highlight patterns in text + patternFound = ((filteredLine.find(needle, 0, false) != -1) || + // highlight patterns in nickname + (whoSent.find(needle, 0, false) != -1)); + } + + if(!patternFound) + { + ++it; + highlight = it.current(); + ++index; + } + else + { + break; + } + } + + if(patternFound) + { + highlightColor = highlight->getColor().name(); + m_highlightColor = highlightColor; + m_tabNotification = Konversation::tnfHighlight; + + if(Preferences::highlightSoundsEnabled() && m_chatWin->notificationsEnabled()) + { + konvApp->sound()->play(highlight->getSoundURL()); + } + + konvApp->notificationHandler()->highlight(m_chatWin, whoSent, line); + m_autoTextToSend = highlight->getAutoText(); + + // replace %0 - %9 in regex groups + for(unsigned int capture=0;capture" + filteredLine + ""; + } + } + else if(doHighlight && (whoSent == ownNick) && Preferences::highlightOwnLines()) + { + // highlight own lines + filteredLine = "" + filteredLine + ""; + } + + // Replace pairs of spaces with " " to preserve some semblance of text wrapping + filteredLine.replace(" "," \xA0"); + return filteredLine; +} + +QString IRCView::createNickLine(const QString& nick, bool encapsulateNick, bool privMsg) +{ + QString nickLine = "%2"; + + if(Preferences::useClickableNicks()) + { + // HACK:Use space as a placeholder for \ as Qt tries to be clever and does a replace to / in urls in QTextEdit + nickLine = "%2"; + } + + if(privMsg) + { + nickLine.prepend ("-> "); + } + + if(encapsulateNick) + nickLine = "<" + nickLine + ">"; + + if(Preferences::useColoredNicks() && m_server) + { + QString nickColor; + + if (nick != m_server->getNickname()) + nickColor = Preferences::nickColor(m_server->obtainNickInfo(nick)->getNickColor()).name(); + else + nickColor = Preferences::nickColor(8).name(); + + if(nickColor == "#000000") + { + nickColor = "#000001"; // HACK Working around QTextBrowser's auto link coloring + } + + nickLine = ""+nickLine+""; + } + //FIXME: Another last-minute hack to get DCC Chat colored nicknames + // working. We can't use NickInfo::getNickColor() because we don't + // have a server. + else if (Preferences::useColoredNicks() && m_chatWin->getType() == ChatWindow::DccChat) + { + QString ownNick = static_cast(m_chatWin)->getOwnNick(); + QString nickColor; + + if (nick != ownNick) + { + int nickvalue = 0; + + for (uint index = 0; index < nick.length(); index++) + { + nickvalue += nick[index].unicode(); + } + + nickColor = Preferences::nickColor((nickvalue % 8)).name(); + } + else + nickColor = Preferences::nickColor(8).name(); + + if(nickColor == "#000000") + { + nickColor = "#000001"; // HACK Working around QTextBrowser's auto link coloring + } + + nickLine = ""+nickLine+""; + } + + if(Preferences::useBoldNicks()) + nickLine = "" + nickLine + ""; + + return nickLine; +} + +void IRCView::append(const QString& nick,const QString& message) +{ + QString channelColor = Preferences::color(Preferences::ChannelMessage).name(); + + if(channelColor == "#000000") + { + channelColor = "#000001"; // HACK Working around QTextBrowser's auto link coloring + } + + QString line; + m_tabNotification = Konversation::tnfNormal; + + QString nickLine = createNickLine(nick); + + if(basicDirection(message) == QChar::DirR) + { + line = RLE; + line += LRE; + line += "

" + nickLine + " %1" + PDF + RLM + " %3

\n"; + } + else + { + line = "

%1" + nickLine + " %3

\n"; + } + + line = line.arg(timeStamp(), nick, filter(message, channelColor, nick, true)); + + emit textToLog(QString("<%1>\t%2").arg(nick).arg(message)); + + doAppend(line); +} + +void IRCView::insertRememberLine() +{ + m_rememberLineDirtyBit = true; + + if (!Preferences::automaticRememberLineOnlyOnTextChange()) + appendRememberLine(); +} + +void IRCView::cancelRememberLine() +{ + m_rememberLineDirtyBit = false; +} + +void IRCView::appendRememberLine() +{ + m_rememberLineDirtyBit = false; + + if (m_rememberLineParagraph == paragraphs() - 1) + return; + + if (m_rememberLineParagraph > -1) + { + removeParagraph(m_rememberLineParagraph); + + QValueList newList; + QValueList::ConstIterator it; + + for (it = m_markerLineParagraphs.begin(); it != m_markerLineParagraphs.end(); ++it) + { + if ((*it) < m_rememberLineParagraph) + newList << (*it); + else if ((*it) > m_rememberLineParagraph) + newList << (*it) - 1; + } + + m_markerLineParagraphs = newList; + } + + repaintChanged(); + + appendLine(Preferences::color(Preferences::CommandMessage).name()); + + m_rememberLineParagraph = paragraphs() - 1; +} + +void IRCView::insertMarkerLine() +{ + qHeapSort(m_markerLineParagraphs); + + if (m_markerLineParagraphs.last() == paragraphs() - 1) + return; + + bool rememberLineDirtyBit = m_rememberLineDirtyBit; + m_rememberLineDirtyBit = false; + + appendLine(Preferences::color(Preferences::ActionMessage).name()); + + m_rememberLineDirtyBit = rememberLineDirtyBit; + + m_markerLineParagraphs.append(paragraphs() - 1); +} + +void IRCView::appendLine(const QString& color) +{ + QColor channelColor = Preferences::color(Preferences::ChannelMessage); + + QString line = "




\n"; + + doAppend(line, true); +} + +void IRCView::clearLines() +{ + if (m_rememberLineParagraph > -1) + m_markerLineParagraphs.append(m_rememberLineParagraph); + + if (m_markerLineParagraphs.count() > 0) + { + qHeapSort(m_markerLineParagraphs); + + QValueList::ConstIterator it; + int removeCounter = 0; + + for (it = m_markerLineParagraphs.begin(); it != m_markerLineParagraphs.end(); ++it) + { + removeParagraph((*it) - removeCounter); + removeCounter++; + } + + wipeLineParagraphs(); + + repaintChanged(); + } +} + +bool IRCView::hasLines() +{ + if (m_rememberLineParagraph > -1 || m_markerLineParagraphs.count() > 0) + return true; + + return false; +} + +void IRCView::updateLineParagraphs(int numRemoved) +{ + if (m_rememberLineParagraph - numRemoved < 0) + m_rememberLineParagraph = -1; + else + m_rememberLineParagraph -= numRemoved; + + if (!m_markerLineParagraphs.isEmpty()) + { + QValueList newMarkerLineParagraphs; + + QValueList::const_iterator it; + + for (it = m_markerLineParagraphs.begin(); it != m_markerLineParagraphs.end(); ++it) + { + if ((*it) - numRemoved >= 0) + newMarkerLineParagraphs << ((*it) - numRemoved); + } + + m_markerLineParagraphs = newMarkerLineParagraphs; + } +} + +void IRCView::wipeLineParagraphs() +{ + m_markerLineParagraphs.clear(); + m_rememberLineParagraph = -1; +} + +void IRCView::appendRaw(const QString& message, bool suppressTimestamps, bool self) +{ + QColor channelColor=Preferences::color(Preferences::ChannelMessage); + QString line; + m_tabNotification = Konversation::tnfNone; + + if(suppressTimestamps) + { + line = QString("

" + message + "

\n"); + } + else + { + line = QString("

" + timeStamp() + " " + message + "

\n"); + } + + doAppend(line, self); +} + +void IRCView::appendQuery(const QString& nick, const QString& message, bool inChannel) +{ + QString queryColor=Preferences::color(Preferences::QueryMessage).name(); + + if(queryColor == "#000000") + { + queryColor = "#000001"; // HACK Working around QTextBrowser's auto link coloring + } + + QString line; + m_tabNotification = Konversation::tnfPrivate; + + QString nickLine = createNickLine(nick, true, inChannel); + + if(basicDirection(message) == QChar::DirR) + { + line = RLE; + line += LRE; + line += "

" + nickLine + " %1" + PDF + " %3

\n"; + } + else + { + line = "

%1 " + nickLine + " %3

\n"; + } + + line = line.arg(timeStamp(), nick, filter(message, queryColor, nick, true)); + + emit textToLog(QString("<%1>\t%2").arg(nick).arg(message)); + + doAppend(line); +} + +void IRCView::appendChannelAction(const QString& nick,const QString& message) +{ + m_tabNotification = Konversation::tnfNormal; + + appendAction(nick, message); +} + + +void IRCView::appendQueryAction(const QString& nick,const QString& message) +{ + m_tabNotification = Konversation::tnfPrivate; + + appendAction(nick, message); +} + +void IRCView::appendAction(const QString& nick,const QString& message) +{ + QString actionColor=Preferences::color(Preferences::ActionMessage).name(); + + // HACK Working around QTextBrowser's auto link coloring + if (actionColor == "#000000") actionColor = "#000001"; + + QString line; + QString nickLine = createNickLine(nick, false); + + if (basicDirection(message) == QChar::DirR) + { + line = RLE; + line += LRE; + line += "

" + nickLine + " * %1" + PDF + " %3

\n"; + } + else + { + line = "

%1 * " + nickLine + " %3

\n"; + } + + line = line.arg(timeStamp(), nick, filter(message, actionColor, nick, true)); + + emit textToLog(QString("\t * %1 %2").arg(nick).arg(message)); + + doAppend(line); +} + +void IRCView::appendServerMessage(const QString& type, const QString& message, bool parseURL) +{ + QString serverColor = Preferences::color(Preferences::ServerMessage).name(); + m_tabNotification = Konversation::tnfControl; + + // Fixed width font option for MOTD + QString fixed; + if(Preferences::fixedMOTD() && !m_fontDataBase.isFixedPitch(font().family())) + { + if(type == i18n("MOTD")) + fixed=" face=\"" + KGlobalSettings::fixedFont().family() + "\""; + } + + QString line; + + if(basicDirection(message) == QChar::DirR) + { + line = RLE; + line += LRE; + line += "

[%2] %1" + PDF + " %3

\n"; + } + else + { + line = "

%1 [%2] %3

\n"; + } + + if(type != i18n("Notify")) + line = line.arg(timeStamp(), type, filter(message, serverColor, 0 , true, parseURL)); + else + line = ""+line.arg(timeStamp(), type, message)+""; + + emit textToLog(QString("%1\t%2").arg(type).arg(message)); + + doAppend(line); +} + +void IRCView::appendCommandMessage(const QString& type,const QString& message, bool important, bool parseURL, bool self) +{ + if (Preferences::hideUnimportantEvents() && !important) + return; + + QString commandColor = Preferences::color(Preferences::CommandMessage).name(); + QString line; + QString prefix="***"; + m_tabNotification = Konversation::tnfControl; + + if(type == i18n("Join")) + { + prefix="-->"; + parseURL=false; + } + else if(type == i18n("Part") || type == i18n("Quit")) + { + prefix="<--"; + } + + prefix=QStyleSheet::escape(prefix); + + if(basicDirection(message) == QChar::DirR) + { + line = RLE; + line += LRE; + line += "

%2 %1" + PDF + " %3

\n"; + } + else + { + line = "

%1 %2 %3

\n"; + } + + line = line.arg(timeStamp(), prefix, filter(message, commandColor, 0, true, parseURL, self)); + + emit textToLog(QString("%1\t%2").arg(type).arg(message)); + + doAppend(line, self); +} + +void IRCView::appendBacklogMessage(const QString& firstColumn,const QString& rawMessage) +{ + QString time; + QString message = rawMessage; + QString nick = firstColumn; + QString backlogColor = Preferences::color(Preferences::BacklogMessage).name(); + m_tabNotification = Konversation::tnfNone; + + time = nick.section(' ', 0, 4); + nick = nick.section(' ', 5); + + if(!nick.isEmpty() && !nick.startsWith("<") && !nick.startsWith("*")) + { + nick = '|' + nick + '|'; + } + + // Nicks are in "" format so replace the "<>" + nick.replace("<","<"); + nick.replace(">",">"); + + QString line; + + if(basicDirection(message) == QChar::DirR) + { + line = "

%2 %1 %3

\n"; + } + else + { + line = "

%1 %2 %3

\n"; + } + + line = line.arg(time, nick, filter(message, backlogColor, NULL, false, false)); + + doAppend(line); +} + +//without any display update stuff that freaks out the scrollview +void IRCView::removeSelectedText( int selNum ) +{ + QTextDocument* doc=document(); + + for ( int i = 0; i < (int)doc->numSelections(); ++i ) + { + if ( i == selNum ) + continue; + doc->removeSelection( i ); + } + // ...snip... + + doc->removeSelectedText( selNum, QTextEdit::textCursor() ); + + // ...snip... +} + +void IRCView::scrollToBottom() +{ + // QTextEdit::scrollToBottom does sync() too, but we don't want it because its slow + setContentsPos( contentsX(), contentsHeight() - visibleHeight() ); +} + +void IRCView::ensureCursorVisible() +{ + if (!m_disableEnsureCursorVisible) + QTextEdit::ensureCursorVisible(); +} + +void IRCView::doAppend(const QString& newLine, bool self) +{ + if (m_rememberLineDirtyBit) appendRememberLine(); + + // Add line to buffer + QString line(newLine); + + if (!self && m_chatWin) m_chatWin->activateTabNotification(m_tabNotification); + + // scroll view only if the scroll bar is already at the bottom + bool doScroll = ( KTextBrowser::verticalScrollBar()->value() == KTextBrowser::verticalScrollBar()->maxValue()); + + line.remove('\n'); // TODO why have newlines? we get

, so the \n are unnecessary... + + bool up = KTextBrowser::viewport()->isUpdatesEnabled(); + + KTextBrowser::viewport()->setUpdatesEnabled(false); + int paraFrom, indexFrom, paraTo, indexTo; + bool textselected = hasSelectedText(); + + // Remember the selection so we don't loose it when adding the new line + if(textselected) + getSelection(¶From, &indexFrom, ¶To, &indexTo); + + document()->lastParagraph()->format(); + + KTextBrowser::append(line); + + document()->lastParagraph()->format(); + + // get maximum number of lines we want to have in the scollback buffer + int sbm = Preferences::scrollbackMax(); + + // Explanation: the scrolling mechanism cannot handle the buffer changing when the scrollbar is not + // at an end, so the scrollbar wets its pants and forgets who it is for ten minutes + // Also make sure not to delete any lines if maximum lines of scrollback is set to 0 (unlimited) + if (sbm && doScroll) + { + int numRemoved = paragraphs() - sbm; + + if (numRemoved > 0) + { + for (int index = numRemoved; index > 0; --index) + { + removeParagraph(0); + } + + updateLineParagraphs(numRemoved); + + if (textselected) + { + paraFrom -= numRemoved; + paraTo -= numRemoved; + } + } + } + + resizeContents(contentsWidth(), document()->height()); + KTextBrowser::viewport()->setUpdatesEnabled(up); + + // Restore selection + if(textselected && paraFrom >= 0 && paraTo >= 0) { + // HACK: do not change scrollback position: setSelection() calls + // ensureCursorVisible() + m_disableEnsureCursorVisible = true; + setSelection(paraFrom, indexFrom, paraTo, indexTo); + m_disableEnsureCursorVisible = false; + } + + if (doScroll) updateScrollBarPos(); + + //FIXME: Disable auto-text for DCC Chats since we don't have a server + // to parse wildcards. + if (!m_autoTextToSend.isEmpty() && m_server) + { + // replace placeholders in autoText + QString sendText = m_server->parseWildcards(m_autoTextToSend,m_server->getNickname(), + QString(), QString(), QString(), QString()); + // avoid recursion due to signalling + m_autoTextToSend = QString(); + // send signal only now + emit autoText(sendText); + } + else + { + m_autoTextToSend = QString(); + } + + if (!m_lastStatusText.isEmpty()) emit clearStatusBarTempText(); +} + +// remember if scrollbar was positioned at the end of the text or not +void IRCView::hideEvent(QHideEvent* /* event */) { + m_resetScrollbar = ((contentsHeight()-visibleHeight()) == contentsY()); +} + +// Workaround to scroll to the end of the TextView when it's shown +void IRCView::showEvent(QShowEvent* event) { + Q_UNUSED(event); + // did the user scroll the view to the end of the text before hiding? + if (m_resetScrollbar) + { + // NOTE: when the view has not been painted yet, contentsHeight() might + // not return accurate information and hence this code won't reset + // scrollback properly in such a case. See paintEvent() hack below. + moveCursor(MoveEnd,false); + ensureVisible(0,contentsHeight()); + } +} + +void IRCView::paintEvent(QPaintEvent* event) +{ + // HACK: if the widget is being painted for the first time, call + // showEvent() which will reset scrollback position as needed. It seems + // that at the time this event is triggered, QTextEdit provides more + // accurate information than when showEvent() is triggered. + if (!m_wasPainted) + { + m_wasPainted = true; + showEvent(0); + } + KTextBrowser::paintEvent(event); +} + +void IRCView::contentsMouseReleaseEvent(QMouseEvent *ev) +{ + if (ev->button() == Qt::MidButton) + { + if(m_copyUrlMenu) + { + openLink(m_urlToCopy,true); + return; + } + else + { + emit textPasted(true); + return; + } + } + + if (ev->button() == QMouseEvent::LeftButton) + { + if (m_mousePressed) + { + if (ev->state() == (Qt::LeftButton|Qt::ShiftButton)) + saveLinkAs(m_highlightedURL); + else + openLink(m_highlightedURL); + + m_mousePressed = false; + return; + } + } + + KTextBrowser::contentsMouseReleaseEvent(ev); +} + +void IRCView::contentsMousePressEvent(QMouseEvent* ev) +{ + if (ev->button() == QMouseEvent::LeftButton) + { + m_urlToDrag = m_highlightedURL; + + if (!m_urlToDrag.isNull()) + { + m_mousePressed = true; + m_pressPosition = ev->pos(); + return; + } + } + + KTextBrowser::contentsMousePressEvent(ev); +} + +void IRCView::contentsMouseMoveEvent(QMouseEvent* ev) +{ + if (m_mousePressed && (m_pressPosition - ev->pos()).manhattanLength() > QApplication::startDragDistance()) + { + m_mousePressed = false; + removeSelection(); + KURL ux = KURL::fromPathOrURL(m_urlToDrag); + + if (m_server && m_urlToDrag.startsWith("##")) + { + //FIXME consistent IRC URL serialization + ux = QString("irc://%1:%2/%3").arg(m_server->getServerName()).arg(m_server->getPort()).arg(m_urlToDrag.mid(2)); + } + else if (m_urlToDrag.startsWith("#")) + { + ux = m_urlToDrag.mid(1); + } + + KURLDrag* u = new KURLDrag(ux, viewport()); + u->drag(); + return; + } + + KTextBrowser::contentsMouseMoveEvent(ev); +} + +void IRCView::contentsContextMenuEvent(QContextMenuEvent* ev) +{ + bool block = contextMenu(ev); + + // HACK Replace % with \x03 in the url to keep Qt from doing stupid things + m_highlightedURL = anchorAt(viewportToContents(mapFromGlobal(QCursor::pos()))); + m_highlightedURL = m_highlightedURL.replace('\x03', "%"); + // Hack to counter the fact that we're given an decoded url + m_highlightedURL = KURL::fromPathOrURL(m_highlightedURL).url(); + + if (m_highlightedURL.isEmpty()) viewport()->setCursor(Qt::ArrowCursor); + + if(m_highlightedURL.startsWith("#")) + { + // HACK:Use space as a placeholder for \ as Qt tries to be clever and does a replace to / in urls in QTextEdit + m_highlightedURL = m_highlightedURL.replace(' ', "\\"); + } + + if (!block) + KTextBrowser::contentsContextMenuEvent(ev); +} + +bool IRCView::contextMenu(QContextMenuEvent* ce) +{ + if (m_server && m_isOnNick && m_nickPopup->isEnabled()) + { + updateNickMenuEntries(m_nickPopup, getContextNick()); + + if(m_nickPopup->exec(ce->globalPos()) == -1) + clearContextNick(); + + m_isOnNick = false; + } + else if (m_server && m_isOnChannel && m_channelPopup->isEnabled()) + { + m_channelPopup->exec(ce->globalPos()); + m_isOnChannel = false; + } + else + { + KActionCollection* actionCollection = KonversationApplication::instance()->getMainWindow()->actionCollection(); + KToggleAction* toggleMenuBarAction = static_cast(actionCollection->action("options_show_menubar")); + + if (toggleMenuBarAction && !toggleMenuBarAction->isChecked()) + { + toggleMenuBarAction->plug(m_popup, 0); + m_popup->setItemVisible(toggleMenuBarSeparator, true); + } + + m_popup->setItemEnabled(Copy,(hasSelectedText())); + + KAction* channelSettingsAction = 0; + + if (m_chatWin->getType() == ChatWindow::Channel) + { + channelSettingsAction = KonversationApplication::instance()->getMainWindow()->actionCollection()->action("channel_settings"); + if (channelSettingsAction) channelSettingsAction->plug(m_popup); + } + + if (m_chatWin->getType() == ChatWindow::Query) + { + updateNickMenuEntries(m_popup, m_chatWin->getName()); + clearContextNick(); + } + + int r = m_popup->exec(ce->globalPos()); + + switch (r) + { + case -1: + // dummy. -1 means, no entry selected. we don't want -1to go in default, so + // we catch it here + break; + case Copy: + copy(); + break; + case CopyUrl: + { + QClipboard *cb = KApplication::kApplication()->clipboard(); + cb->setText(m_urlToCopy,QClipboard::Selection); + cb->setText(m_urlToCopy,QClipboard::Clipboard); + break; + } + case SelectAll: + selectAll(); + break; + case Search: + search(); + break; + case SendFile: + emit sendFile(); + break; + case Bookmark: + { + KBookmarkManager* bm = KBookmarkManager::userBookmarksManager(); + KBookmarkGroup bg = bm->addBookmarkDialog(m_urlToCopy, QString()); + bm->save(); + bm->emitChanged(bg); + break; + } + case SaveAs: + saveLinkAs(m_urlToCopy); + break; + default: + emit extendedPopup(r); + } + + if (toggleMenuBarAction) + { + toggleMenuBarAction->unplug(m_popup); + m_popup->setItemVisible(toggleMenuBarSeparator, false); + } + + if (channelSettingsAction) channelSettingsAction->unplug(m_popup); + } + return true; +} + +void IRCView::setupNickPopupMenu() +{ + m_nickPopup = new KPopupMenu(this,"nicklist_context_menu"); + m_modes = new KPopupMenu(this,"nicklist_modes_context_submenu"); + m_kickban = new KPopupMenu(this,"nicklist_kick_ban_context_submenu"); + m_nickPopupId= m_nickPopup->insertTitle(m_currentNick); + + m_nickPopup->insertItem(i18n("&Whois"),Konversation::Whois); + m_nickPopup->insertItem(i18n("&Version"),Konversation::Version); + m_nickPopup->insertItem(i18n("&Ping"),Konversation::Ping); + + m_nickPopup->insertSeparator(); + + m_modes->insertItem(i18n("Give Op"),Konversation::GiveOp); + m_modes->insertItem(i18n("Take Op"),Konversation::TakeOp); + m_modes->insertItem(i18n("Give Voice"),Konversation::GiveVoice); + m_modes->insertItem(i18n("Take Voice"),Konversation::TakeVoice); + m_nickPopup->insertItem(i18n("Modes"),m_modes,Konversation::ModesSub); + + m_kickban->insertItem(i18n("Kick"),Konversation::Kick); + m_kickban->insertItem(i18n("Kickban"),Konversation::KickBan); + m_kickban->insertItem(i18n("Ban Nickname"),Konversation::BanNick); + m_kickban->insertSeparator(); + m_kickban->insertItem(i18n("Ban *!*@*.host"),Konversation::BanHost); + m_kickban->insertItem(i18n("Ban *!*@domain"),Konversation::BanDomain); + m_kickban->insertItem(i18n("Ban *!user@*.host"),Konversation::BanUserHost); + m_kickban->insertItem(i18n("Ban *!user@domain"),Konversation::BanUserDomain); + m_kickban->insertSeparator(); + m_kickban->insertItem(i18n("Kickban *!*@*.host"),Konversation::KickBanHost); + m_kickban->insertItem(i18n("Kickban *!*@domain"),Konversation::KickBanDomain); + m_kickban->insertItem(i18n("Kickban *!user@*.host"),Konversation::KickBanUserHost); + m_kickban->insertItem(i18n("Kickban *!user@domain"),Konversation::KickBanUserDomain); + m_nickPopup->insertItem(i18n("Kick / Ban"),m_kickban,Konversation::KickBanSub); + + m_nickPopup->insertItem(i18n("Ignore"), Konversation::IgnoreNick); + m_nickPopup->insertItem(i18n("Unignore"), Konversation::UnignoreNick); + m_nickPopup->setItemVisible(Konversation::IgnoreNick, false); + m_nickPopup->setItemVisible(Konversation::UnignoreNick, false); + + m_nickPopup->insertSeparator(); + + m_nickPopup->insertItem(i18n("Open Query"),Konversation::OpenQuery); + if (kapp->authorize("allow_downloading")) + { + m_nickPopup->insertItem(SmallIcon("2rightarrow"),i18n("Send &File..."),Konversation::DccSend); + } + m_nickPopup->insertSeparator(); + + m_nickPopup->insertItem(i18n("Add to Watched Nicks"), Konversation::AddNotify); + + connect(m_nickPopup, SIGNAL(activated(int)), this, SIGNAL(popupCommand(int))); + connect(m_modes, SIGNAL(activated(int)), this, SIGNAL(popupCommand(int))); + connect(m_kickban, SIGNAL(activated(int)), this, SIGNAL(popupCommand(int))); +} + +void IRCView::updateNickMenuEntries(QPopupMenu* popup, const QString& nickname) +{ + if (popup) + { + if (Preferences::isIgnored(nickname)) + { + popup->setItemVisible(Konversation::UnignoreNick, true); + popup->setItemVisible(Konversation::IgnoreNick, false); + } + else + { + popup->setItemVisible(Konversation::IgnoreNick, true); + popup->setItemVisible(Konversation::UnignoreNick, false); + } + + if (!m_server || !m_server->getServerGroup()) + popup->setItemEnabled(Konversation::AddNotify, false); + else if (!m_server->isConnected()) + popup->setItemEnabled(Konversation::AddNotify, false); + else if (!Preferences::hasNotifyList(m_server->getServerGroup()->id())) + popup->setItemEnabled(Konversation::AddNotify, false); + else if (Preferences::isNotify(m_server->getServerGroup()->id(), nickname)) + popup->setItemEnabled(Konversation::AddNotify, false); + else + popup->setItemEnabled(Konversation::AddNotify, true); + } +} + +void IRCView::setupQueryPopupMenu() +{ + m_nickPopup = new KPopupMenu(this,"query_context_menu"); + m_nickPopupId = m_nickPopup->insertTitle(m_currentNick); + m_nickPopup->insertItem(i18n("&Whois"),Konversation::Whois); + m_nickPopup->insertItem(i18n("&Version"),Konversation::Version); + m_nickPopup->insertItem(i18n("&Ping"),Konversation::Ping); + m_nickPopup->insertSeparator(); + + m_nickPopup->insertItem(i18n("Ignore"), Konversation::IgnoreNick); + m_nickPopup->insertItem(i18n("Unignore"), Konversation::UnignoreNick); + m_nickPopup->setItemVisible(Konversation::IgnoreNick, false); + m_nickPopup->setItemVisible(Konversation::UnignoreNick, false); + + if (kapp->authorize("allow_downloading")) + m_nickPopup->insertItem(SmallIcon("2rightarrow"),i18n("Send &File..."),Konversation::DccSend); + + m_nickPopup->insertItem(i18n("Add to Watched Nicks"), Konversation::AddNotify); + + connect(m_nickPopup, SIGNAL(activated(int)), this, SIGNAL(popupCommand(int))); +} + +void IRCView::setupChannelPopupMenu() +{ + m_channelPopup = new KPopupMenu(this,"channel_context_menu"); + m_channelPopupId = m_channelPopup->insertTitle(m_currentChannel); + m_channelPopup->insertItem(i18n("&Join"),Konversation::Join); + m_channelPopup->insertItem(i18n("Get &user list"),Konversation::Names); + m_channelPopup->insertItem(i18n("Get &topic"),Konversation::Topic); + + connect(m_channelPopup, SIGNAL(activated(int)), this, SIGNAL(popupCommand(int))); +} + +void IRCView::setNickAndChannelContextMenusEnabled(bool enable) +{ + if (m_nickPopup) m_nickPopup->setEnabled(enable); + if (m_channelPopup) m_channelPopup->setEnabled(enable); +} + +void IRCView::search() +{ + emit doSearch(); +} + +void IRCView::searchAgain() +{ + if (m_pattern.isEmpty()) + { + emit doSearch(); + } + else + { + // next search must begin one index before / after the last search + // depending on the search direction. + if(m_forward) + { + ++m_findIndex; + if(m_findIndex == paragraphLength(m_findParagraph)) + { + m_findIndex = 0; + ++m_findParagraph; + } + } + else + { + if(m_findIndex) + { + --m_findIndex; + } + else + { + --m_findParagraph; + m_findIndex = paragraphLength(m_findParagraph); + } + } + + if(!find(m_pattern, m_caseSensitive, m_wholeWords, m_forward, &m_findParagraph, &m_findIndex)) + { + KMessageBox::information(this,i18n("No matches found for \"%1\".").arg(m_pattern),i18n("Information")); + } + + } +} + +bool IRCView::search(const QString& pattern, bool caseSensitive, +bool wholeWords, bool forward, bool fromCursor) +{ + m_pattern = pattern; + m_caseSensitive = caseSensitive; + m_wholeWords = wholeWords; + m_forward = forward; + m_fromCursor = fromCursor; + + if (m_pattern.isEmpty()) + return true; + + if (!m_fromCursor) + { + if(m_forward) + { + m_findParagraph = 1; + m_findIndex = 1; + } + else + { + m_findParagraph = paragraphs(); + m_findIndex = paragraphLength(paragraphs()); + } + } + + return searchNext(); +} + +bool IRCView::searchNext(bool reversed) +{ + if (m_pattern.isEmpty()) + return true; + + bool fwd = (reversed ? !m_forward : m_forward); + // next search must begin one index before / after the last search + // depending on the search direction. + if (fwd) + { + ++m_findIndex; + if(m_findIndex == paragraphLength(m_findParagraph)) + { + m_findIndex = 0; + ++m_findParagraph; + } + } + else + { + if (m_findIndex) + { + --m_findIndex; + } + else + { + --m_findParagraph; + m_findIndex = paragraphLength(m_findParagraph); + } + } + + return find(m_pattern, m_caseSensitive, m_wholeWords, fwd, + &m_findParagraph, &m_findIndex); +} + +// other windows can link own menu entries here +QPopupMenu* IRCView::getPopup() const +{ + return m_popup; +} + +// for more information about these RTFM +// http://www.unicode.org/reports/tr9/ +// http://www.w3.org/TR/unicode-xml/ +QChar IRCView::LRM = (ushort)0x200e; // Right-to-Left Mark +QChar IRCView::RLM = (ushort)0x200f; // Left-to-Right Mark +QChar IRCView::LRE = (ushort)0x202a; // Left-to-Right Embedding +QChar IRCView::RLE = (ushort)0x202b; // Right-to-Left Embedding +QChar IRCView::RLO = (ushort)0x202e; // Right-to-Left Override +QChar IRCView::LRO = (ushort)0x202d; // Left-to-Right Override +QChar IRCView::PDF = (ushort)0x202c; // Previously Defined Format + +QChar::Direction IRCView::basicDirection(const QString &string) +{ + // The following code decides between LTR or RTL direction for + // a line based on the amount of each type of characters pre- + // sent. It does so by counting, but stops when one of the two + // counters becomes higher than half of the string length to + // avoid unnecessary work. + + unsigned int pos = 0; + unsigned int rtl_chars = 0; + unsigned int ltr_chars = 0; + unsigned int str_len = string.length(); + unsigned int str_half_len = str_len/2; + + for(pos=0; pos < str_len; pos++) + { + if (!(string[pos].isNumber() || string[pos].isSymbol() || + string[pos].isSpace() || string[pos].isPunct() || + string[pos].isMark())) + { + switch(string[pos].direction()) + { + case QChar::DirL: + case QChar::DirLRO: + case QChar::DirLRE: + ltr_chars++; + break; + case QChar::DirR: + case QChar::DirAL: + case QChar::DirRLO: + case QChar::DirRLE: + rtl_chars++; + break; + default: + break; + } + } + + if (ltr_chars > str_half_len) + return QChar::DirL; + else if (rtl_chars > str_half_len) + return QChar::DirR; + } + + if (rtl_chars > ltr_chars) + return QChar::DirR; + else + return QChar::DirL; +} + +void IRCView::contentsDragMoveEvent(QDragMoveEvent *e) +{ + if(acceptDrops() && QUriDrag::canDecode(e)) + e->accept(); +} + +void IRCView::contentsDropEvent(QDropEvent *e) +{ + QStrList s; + if(QUriDrag::decode(e,s)) + emit filesDropped(s); +} + +QString IRCView::timeStamp() +{ + if(Preferences::timestamping()) + { + QTime time = QTime::currentTime(); + QString timeColor = Preferences::color(Preferences::Time).name(); + QString timeFormat = Preferences::timestampFormat(); + QString timeString; + + if(!Preferences::showDate()) + { + timeString = QString("[%1] ").arg(time.toString(timeFormat)); + } + else + { + QDate date = QDate::currentDate(); + timeString = QString("[%1 %2] ") + .arg(KGlobal::locale()->formatDate(date, true /*short format*/), + time.toString(timeFormat)); + } + + return timeString; + } + + return QString(); +} + +void IRCView::setChatWin(ChatWindow* chatWin) +{ + m_chatWin = chatWin; + + if(m_chatWin->getType()==ChatWindow::Channel) + setupNickPopupMenu(); + else + setupQueryPopupMenu(); + + setupChannelPopupMenu(); +} + +void IRCView::keyPressEvent(QKeyEvent* e) +{ + KKey key(e); + + if (KStdAccel::copy().contains(key)) + { + copy(); + e->accept(); + return; + } + else if (KStdAccel::paste().contains(key)) + { + emit textPasted(false); + e->accept(); + return; + } + + KTextBrowser::keyPressEvent(e); +} + +void IRCView::resizeEvent(QResizeEvent* e) +{ + bool doScroll = ( KTextBrowser::verticalScrollBar()->value() == KTextBrowser::verticalScrollBar()->maxValue()); + KTextBrowser::resizeEvent(e); + + if(doScroll) + { + QTimer::singleShot(0, this, SLOT(updateScrollBarPos())); + } +} + +void IRCView::updateScrollBarPos() +{ + ensureVisible(contentsX(), contentsHeight()); + repaintContents(false); +} + +void IRCView::saveLinkAs(const QString& url) +{ + KURL source(url); + KFileDialog dialog(":SaveLinkAs", QString (), this, "savelinkdia", true); + dialog.setCaption(i18n("Save Link As")); + dialog.setSelection(source.fileName()); + + if(dialog.exec() == QDialog::Rejected) + return; + + KURL destination = dialog.selectedURL(); + KIO::copyAs(source, destination); +} + +#include "ircview.moc" + +// kate: space-indent on; tab-width 4; indent-width 4; mixed-indent off; replace-tabs on; +// vim: set et sw=4 ts=4 cino=l1,cs,U1: diff --git a/konversation/src/ircview.h b/konversation/src/ircview.h new file mode 100644 index 0000000..39e3ff0 --- /dev/null +++ b/konversation/src/ircview.h @@ -0,0 +1,242 @@ +#ifndef IRCVIEW_H +#define IRCVIEW_H + +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2005-2006 Peter Simonsson + Copyright (C) 2006-2008 Eike Hein +*/ + +#include "common.h" + +#include +#include + +#include + + +class QPixmap; +class QStrList; +class QDropEvent; +class QDragEnterEvent; +class QEvent; + +class KPopupMenu; + +class Server; +class ChatWindow; +class SearchBar; + +class IRCView : public KTextBrowser +{ + Q_OBJECT + + public: + IRCView(QWidget* parent,Server* newServer); + ~IRCView(); + + void clear(); + void setViewBackground(const QColor& backgroundColor, const QString& pixmapName); + void setServer(Server* server); + + // Returns the current nick under context menu. + const QString& getContextNick() const; + + void enableParagraphSpacing(); + + QPopupMenu* getPopup() const; + + enum PopupIDs + { + Copy,CopyUrl,SelectAll, + Search, + SendFile, + Bookmark, + SaveAs + }; + + void setChatWin(ChatWindow* chatWin); + + bool search(const QString& pattern, bool caseSensitive, + bool wholeWords, bool forward, bool fromCursor); + bool searchNext(bool reversed = false); + + QColor highlightColor() { return m_highlightColor; } + QString currentChannel() { return m_currentChannel; } + + void setNickAndChannelContextMenusEnabled(bool enable); + + bool hasLines(); + + + signals: + // Notify container of new text and highlight state + void gotFocus(); // So we can set focus to input line + void textToLog(const QString& text); + void sendFile(); + void extendedPopup(int id); + void autoText(const QString& text); + void textPasted(bool useSelection); + void popupCommand(int); + void filesDropped(const QStrList&); + void doSearch(); + + void setStatusBarTempText(const QString&); + void clearStatusBarTempText(); + + public slots: + void insertRememberLine(); + void cancelRememberLine(); + void insertMarkerLine(); + void clearLines(); + + void append(const QString& nick, const QString& message); + void appendRaw(const QString& message, bool suppressTimestamps=false, bool self = false); + void appendQuery(const QString& nick, const QString& message, bool inChannel = false); + void appendQueryAction(const QString& nick, const QString& message); + void appendChannelAction(const QString& nick, const QString& message); + void appendServerMessage(const QString& type, const QString& message, bool parseURL = true); + void appendCommandMessage(const QString& command, const QString& message, bool important, + bool parseURL=true, bool self=false); + void appendBacklogMessage(const QString& firstColumn, const QString& message); + void search(); + void searchAgain(); + + void setCurrentChannel(const QString& channel) { m_currentChannel = channel; } + + virtual void removeSelectedText(int selNum=0); + + virtual void scrollToBottom(); // Overwritten for internal reasons + + // Clears context nick + void clearContextNick(); + + // Updates the scrollbar position + void updateScrollBarPos(); + + // Override ensureCursorVisible() to have an ability to disable this call + virtual void ensureCursorVisible(); + + protected slots: + void highlightedSlot(const QString& link); + void saveLinkAs(const QString& url); + + protected: + void openLink(const QString &url, bool newTab=false); + QString filter(const QString& line, const QString& defaultColor, const QString& who=NULL, + bool doHighlight=true, bool parseURL=true, bool self=false); + void appendAction(const QString& nick, const QString& message); + void doAppend(const QString& line, bool self=false); + void replaceDecoration(QString& line,char decoration,char replacement); + virtual void contentsDragMoveEvent(QDragMoveEvent* e); + virtual void contentsDropEvent(QDropEvent* e); + virtual void contentsMouseReleaseEvent(QMouseEvent* ev); + virtual void contentsMousePressEvent(QMouseEvent* ev); + virtual void contentsMouseMoveEvent(QMouseEvent* ev); + virtual void contentsContextMenuEvent(QContextMenuEvent* ev); + + virtual void keyPressEvent(QKeyEvent* e); + virtual void resizeEvent(QResizeEvent* e); + + void hideEvent(QHideEvent* event); + void showEvent(QShowEvent* event); + void paintEvent(QPaintEvent* event); + + bool contextMenu(QContextMenuEvent* ce); + + void setupNickPopupMenu(); + void updateNickMenuEntries(QPopupMenu* popup, const QString& nickname); + void setupQueryPopupMenu(); + void setupChannelPopupMenu(); + + QChar::Direction basicDirection(const QString &string); + + /// Returns a formated timestamp if timestamps are enabled else it returns QString::null + QString timeStamp(); + + /// Returns a formated nick string + QString createNickLine(const QString& nick, bool encapsulateNick = true, bool privMsg = false); + + // used by search function + int m_findParagraph; + int m_findIndex; + + void appendLine(const QString& color); + void appendRememberLine(); + + void updateLineParagraphs(int numRemoved); + void wipeLineParagraphs(); + + int m_rememberLineParagraph; + bool m_rememberLineDirtyBit; + + QValueList m_markerLineParagraphs; + + // This is set to what we last sent status text to the statusbar. Empty if we have sent clearStatusBarTempText() string + QString m_lastStatusText; + // decide if we should place the scrollbar at the bottom on show() + bool m_resetScrollbar; + + QString m_autoTextToSend; + Konversation::TabNotifyType m_tabNotification; + bool m_copyUrlMenu; + QString m_urlToCopy; + + QString m_buffer; + Server* m_server; + QPopupMenu* m_popup; + int toggleMenuBarSeparator; + int copyUrlMenuSeparator; + KPopupMenu* m_nickPopup; + KPopupMenu* m_channelPopup; + KPopupMenu* m_modes; + KPopupMenu* m_kickban; + + static QChar LRM; + static QChar RLM; + static QChar LRE; + static QChar RLE; + static QChar RLO; + static QChar LRO; + static QChar PDF; + + bool m_caseSensitive; + bool m_wholeWords; + bool m_forward; + bool m_fromCursor; + QString m_pattern; + QColor m_highlightColor; + + uint m_offset; + QStringList m_colorList; + + QString m_highlightedURL; // the URL we're currently hovering on with the mouse + QString m_currentNick; + QString m_currentChannel; + bool m_isOnNick; + bool m_isOnChannel; + bool m_mousePressed; + QString m_urlToDrag; + QPoint m_pressPosition; + int m_nickPopupId; + int m_channelPopupId; + + QFontDatabase m_fontDataBase; + + // Provide ability to disable parent ensureCursorVisible() call + bool m_disableEnsureCursorVisible; + // If this widget was painted at least once. Needed for scrollbar + // reset HACK as a precaution. + bool m_wasPainted; + + ChatWindow* m_chatWin; + friend class IRCStyleSheet; +}; +#endif diff --git a/konversation/src/ircviewbox.cpp b/konversation/src/ircviewbox.cpp new file mode 100644 index 0000000..817f7d9 --- /dev/null +++ b/konversation/src/ircviewbox.cpp @@ -0,0 +1,141 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 Renchi Raju +*/ + +#include "ircviewbox.h" +#include "ircview.h" +#include "searchbar.h" + +#include +#include +#include +#include + + +static QPixmap getIcon(const QString& name) +{ + KIconLoader* iconLoader = kapp->iconLoader(); + return iconLoader->loadIcon(name, KIcon::Toolbar, 16); +} + +IRCViewBox::IRCViewBox(QWidget* parent, Server* newServer) +: QVBox(parent) +{ + m_ircView = new IRCView(this, newServer); + m_searchBar = new SearchBar(this); + m_searchBar->hide(); + m_matchedOnce = false; + + connect(m_searchBar, SIGNAL(signalSearchChanged(const QString&)), + this, SLOT(slotSearchChanged(const QString&))); + connect(m_searchBar, SIGNAL(signalSearchNext()), + this, SLOT(slotSearchNext())); + connect(m_searchBar, SIGNAL(signalSearchPrevious()), + this, SLOT(slotSearchPrevious())); + connect(m_ircView, SIGNAL(doSearch()), + SLOT(slotSearch())); + connect(m_searchBar, SIGNAL(hidden()), m_ircView, SIGNAL(gotFocus())); +} + +IRCViewBox::~IRCViewBox() +{ + delete m_ircView; + delete m_searchBar; +} + +IRCView* IRCViewBox::ircView() const +{ + return m_ircView; +} + +void IRCViewBox::slotSearch() +{ + if (m_searchBar->isVisible()) + { + m_searchBar->hide(); + return; + } + + m_searchBar->show(); + m_searchBar->setFocus(); +} + +void IRCViewBox::slotSearchNext() +{ + searchNext(false); +} + +void IRCViewBox::slotSearchPrevious() +{ + searchNext(true); +} + +void IRCViewBox::searchNext(bool reversed) +{ + bool match = m_ircView->searchNext(reversed); + + if (match) + { + m_searchBar->setHasMatch(true); + m_searchBar->setStatus(QPixmap(), ""); + return; + } + + if (!m_matchedOnce) + { + m_searchBar->setHasMatch(false); + m_searchBar->setStatus(getIcon("messagebox_warning"), + i18n("Phrase not found")); + return; + } + + match = m_ircView->search(m_searchBar->pattern(), + m_searchBar->caseSensitive(), + m_searchBar->wholeWords(), + m_searchBar->searchForward(), + false); + + if (!match) + { + m_searchBar->setHasMatch(false); + m_searchBar->setStatus(getIcon("messagebox_warning"), + i18n("Phrase not found")); + return; + } + + m_searchBar->setHasMatch(true); + m_searchBar->setStatus(getIcon("messagebox_info"), + i18n("Wrapped search")); +} + +void IRCViewBox::slotSearchChanged(const QString& pattern) +{ + bool match = m_ircView->search(pattern, + m_searchBar->caseSensitive(), + m_searchBar->wholeWords(), + m_searchBar->searchForward(), + m_searchBar->fromCursor()); + + if (match) + { + m_searchBar->setHasMatch(true); + m_searchBar->setStatus(QPixmap(), ""); + } + else + { + m_searchBar->setHasMatch(false); + m_searchBar->setStatus(getIcon("messagebox_warning"), + i18n("Phrase not found")); + } + + m_matchedOnce = match; +} + +#include "ircviewbox.moc" diff --git a/konversation/src/ircviewbox.h b/konversation/src/ircviewbox.h new file mode 100644 index 0000000..321e293 --- /dev/null +++ b/konversation/src/ircviewbox.h @@ -0,0 +1,49 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 Renchi Raju +*/ + +#ifndef IRCVIEWBOX_H +#define IRCVIEWBOX_H + +#include + + +class IRCView; +class SearchBar; +class Server; + +class IRCViewBox : public QVBox +{ + Q_OBJECT + + public: + + IRCViewBox(QWidget* parent, Server* newServer); + ~IRCViewBox(); + + IRCView* ircView() const; + + public slots: + + void slotSearch(); + void slotSearchNext(); + void slotSearchPrevious(); + void slotSearchChanged(const QString& pattern); + + protected: + void searchNext(bool reversed = false); + + private: + + IRCView* m_ircView; + SearchBar* m_searchBar; + bool m_matchedOnce; +}; +#endif /* IRCVIEWBOX_H */ diff --git a/konversation/src/joinchanneldialog.cpp b/konversation/src/joinchanneldialog.cpp new file mode 100644 index 0000000..4799da2 --- /dev/null +++ b/konversation/src/joinchanneldialog.cpp @@ -0,0 +1,104 @@ +/* + 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. +*/ + +/* + Copyright (C) 2004 by Peter Simonsson +*/ + +#include "joinchanneldialog.h" +#include "joinchannelui.h" +#include "server.h" +#include "channel.h" +#include "servergroupsettings.h" + +#include + +#include +#include +#include + + +namespace Konversation +{ + + JoinChannelDialog::JoinChannelDialog(Server* server, QWidget *parent, const char *name) + : KDialogBase(parent, name, true, i18n("Join Channel on %1").arg(server->getDisplayName()), Ok|Cancel, Ok) + { + m_server = server; + m_widget = new JoinChannelUI(this); + setMainWidget(m_widget); + + m_widget->serverLbl->setText(server->getDisplayName()); + + if (m_server->getServerGroup()) + { + ChannelList history = server->getServerGroup()->channelHistory(); + ChannelList::iterator endIt = history.end(); + const QPtrList &channels = server->getChannelList(); + QPtrListIterator chanIt(channels); + Channel* chan = 0; + bool joined = false; + + for(ChannelList::iterator it = history.begin(); it != endIt; ++it) + { + chan = chanIt.toFirst(); + joined = false; + + while(chan) + { + if(chan->getName() == (*it).name()) + { + joined = true; + } + + ++chanIt; + chan = chanIt.current(); + } + + if(!joined) + { + m_widget->channelCombo->addToHistory((*it).name()); + } + } + } + + m_widget->channelCombo->setCurrentText(""); + } + + JoinChannelDialog::~JoinChannelDialog() + { + } + + QString JoinChannelDialog::channel() const + { + QString channel = m_widget->channelCombo->currentText(); + + if(!m_server->isAChannel(channel)) + { + channel = '#' + channel; + } + + return channel; + } + + QString JoinChannelDialog::password() const + { + return m_widget->passwordEdit->text(); + } + + void JoinChannelDialog::slotOk() + { + // If the channel already exist in the history only the password will be updated. + if (m_server->getServerGroup()) + m_server->getServerGroup()->appendChannelHistory(ChannelSettings(channel(), password())); + + accept(); + } + +} + +#include "joinchanneldialog.moc" diff --git a/konversation/src/joinchanneldialog.h b/konversation/src/joinchanneldialog.h new file mode 100644 index 0000000..7cad840 --- /dev/null +++ b/konversation/src/joinchanneldialog.h @@ -0,0 +1,44 @@ +/* + 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. +*/ + +/* + Copyright (C) 2004 Peter Simonsson +*/ + +#ifndef KONVERSATIONJOINCHANNELDIALOG_H +#define KONVERSATIONJOINCHANNELDIALOG_H + +#include + + +class Server; + +namespace Konversation +{ + + class JoinChannelUI; + + class JoinChannelDialog : public KDialogBase + { + Q_OBJECT + public: + explicit JoinChannelDialog(Server* server, QWidget *parent = 0, const char *name = 0); + ~JoinChannelDialog(); + + QString channel() const; + QString password() const; + + protected slots: + virtual void slotOk(); + + private: + JoinChannelUI* m_widget; + Server* m_server; + }; + +} +#endif diff --git a/konversation/src/joinchannelui.ui b/konversation/src/joinchannelui.ui new file mode 100644 index 0000000..7863331 --- /dev/null +++ b/konversation/src/joinchannelui.ui @@ -0,0 +1,110 @@ + +Konversation::JoinChannelUI +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. + +(C) 2004 Peter Simonsson + + + Konversation::JoinChannelUI + + + + 0 + 0 + 507 + 209 + + + + + unnamed + + + 0 + + + + channelLabel + + + C&hannel: + + + channelCombo + + + + + channelCombo + + + true + + + true + + + + + passwordEdit + + + Password + + + + + passwordLabel + + + &Password: + + + passwordEdit + + + + + textLabel8 + + + + 5 + 0 + 0 + 0 + + + + Server: + + + + + serverLbl + + + + 5 + 0 + 0 + 0 + + + + + + + + + + + + kcombobox.h + klineedit.h + klineedit.h + + diff --git a/konversation/src/konsolepanel.cpp b/konversation/src/konsolepanel.cpp new file mode 100644 index 0000000..2fe5b99 --- /dev/null +++ b/konversation/src/konsolepanel.cpp @@ -0,0 +1,75 @@ +/* + 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. +*/ + +/* + Copyright (C) 2003 Mickael Marchand +*/ + +#include "konsolepanel.h" +#include "common.h" +#include "viewcontainer.h" + +#include +#include +#include + + +KonsolePanel::KonsolePanel(QWidget *p) : ChatWindow( p ), k_part (0) +{ + setName(i18n("Konsole")); + setType(ChatWindow::Konsole); + KLibFactory *fact = KLibLoader::self()->factory("libkonsolepart"); + if (!fact) return; + + k_part = (KParts::ReadOnlyPart *) fact->create(this); + if (!k_part) return; + + k_part->widget()->setFocusPolicy(QWidget::WheelFocus); + setFocusProxy(k_part->widget()); + k_part->widget()->setFocus(); + + connect(k_part, SIGNAL(destroyed()), this, SLOT(partDestroyed())); + connect(k_part, SIGNAL(receivedData(const QString&)), this, SLOT(konsoleChanged(const QString&))); +} + +KonsolePanel::~KonsolePanel() +{ + kdDebug() << "KonsolePanel::~KonsolePanel()" << endl; + if ( k_part ) + { + // make sure to prevent partDestroyed() signals from being sent + disconnect(k_part, SIGNAL(destroyed()), this, SLOT(partDestroyed())); + delete k_part; + } +} + +QWidget* KonsolePanel::getWidget() +{ + if (k_part) + return k_part->widget(); + else + return 0; +} + +void KonsolePanel::childAdjustFocus() +{ + if (k_part) k_part->widget()->setFocus(); +} + +void KonsolePanel::partDestroyed() +{ + k_part = 0; + + emit closeView(this); +} + +void KonsolePanel::konsoleChanged(const QString& /* data */) +{ + activateTabNotification(Konversation::tnfSystem); +} + +#include "konsolepanel.moc" diff --git a/konversation/src/konsolepanel.h b/konversation/src/konsolepanel.h new file mode 100644 index 0000000..ad9d1c0 --- /dev/null +++ b/konversation/src/konsolepanel.h @@ -0,0 +1,47 @@ +/* + 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. +*/ + +/* + Copyright (C) 2003 Mickael Marchand +*/ + +#ifndef KONSOLE_PANEL_H +#define KONSOLE_PANEL_H + +#include "chatwindow.h" + +#include + + +class KonsolePanel : public ChatWindow +{ + Q_OBJECT + + public: + explicit KonsolePanel(QWidget *p); + ~KonsolePanel(); + + virtual void setName(const QString& newName) { ChatWindow::setName(newName); } + + QWidget* getWidget(); + + signals: + void closeView(ChatWindow* view); + + public slots: + void partDestroyed(); + + /** Called from ChatWindow adjustFocus */ + virtual void childAdjustFocus(); + + protected slots: + void konsoleChanged(const QString& data); + + private: + KParts::ReadOnlyPart *k_part; +}; +#endif /* KONSOLE_PANEL_H */ diff --git a/konversation/src/konvdcop.cpp b/konversation/src/konvdcop.cpp new file mode 100644 index 0000000..e7abda9 --- /dev/null +++ b/konversation/src/konvdcop.cpp @@ -0,0 +1,359 @@ +/* + 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. +*/ + +/* + The konversation DCOP interface class + begin: Mar 7 2003 + copyright: (C) 2003 by Alex Zepeda + email: zipzippy@sonic.net +*/ + +#include "konvdcop.h" +#include "konversationapplication.h" +#include "connectionmanager.h" +#include "awaymanager.h" +#include "channel.h" +#include "identity.h" +#include "server.h" + +#include +#include +#include +#include + + +KonvDCOP::KonvDCOP() : DCOPObject("irc"), QObject(0, "irc") +{ + connectDCOPSignal("kdesktop", "KScreensaverIface", "KDE_start_screensaver()", "setScreenSaverStarted()", false); + connectDCOPSignal("kdesktop", "KScreensaverIface", "KDE_stop_screensaver()", "setScreenSaverStopped()", false); +} + +void KonvDCOP::raw(const QString& server,const QString& command) +{ + kdDebug() << "KonvDCOP::raw()" << endl; + // send raw IRC protocol data + emit dcopRaw(server,command); +} + +QStringList KonvDCOP::listServers() +{ + KonversationApplication* konvApp = static_cast(kapp); + + QStringList hosts; + QPtrList serverList = konvApp->getConnectionManager()->getServerList(); + Server* server; + + for (server = serverList.first(); server; server = serverList.next()) + if (server) hosts << server->getServerName(); + + return hosts; +} + +QStringList KonvDCOP::listConnectedServers() +{ + KonversationApplication* konvApp = static_cast(kapp); + + QStringList connectedHosts; + QPtrList serverList = konvApp->getConnectionManager()->getServerList(); + Server* server; + + for (server = serverList.first(); server; server = serverList.next()) + if (server && server->isConnected()) connectedHosts << server->getServerName(); + + return connectedHosts; +} + +void KonvDCOP::setAway(const QString& awaymessage) +{ + static_cast(kapp)->getAwayManager()->requestAllAway(awaymessage); +} + +void KonvDCOP::setBack() +{ + static_cast(kapp)->getAwayManager()->requestAllUnaway(); +} + +void KonvDCOP::setScreenSaverStarted() +{ + static_cast(kapp)->getAwayManager()->setManagedIdentitiesAway(); +} + +void KonvDCOP::setScreenSaverStopped() +{ + static_cast(kapp)->getAwayManager()->setManagedIdentitiesUnaway(); +} + +void KonvDCOP::sayToAll(const QString &message) +{ + emit dcopMultiServerRaw("msg " + message); +} + +void KonvDCOP::actionToAll(const QString &message) +{ + emit dcopMultiServerRaw("me " + message); +} + +void KonvDCOP::say(const QString& _server,const QString& _target,const QString& _command) +{ + //Sadly, copy on write doesn't exist with QString::replace + QString server(_server), target(_target), command(_command); + + // TODO: this just masks a greater problem - Server::addQuery will return a query for '' --argonel + // TODO: other DCOP calls need argument checking too --argonel + if (server.isEmpty() || target.isEmpty() || command.isEmpty()) + kdDebug() << "KonvDCOP::say() requires 3 arguments." << endl; + else + { + command.replace('\n',"\\n"); + command.replace('\r',"\\r"); + target.remove('\n'); + target.remove('\r'); + server.remove('\n'); + server.remove('\r'); + // Act as if the user typed it + emit dcopSay(server,target,command); + } +} + +void KonvDCOP::info(const QString& string) +{ + kdDebug() << "KonvDCOP::info()" << endl; + emit dcopInfo(string); +} + +void KonvDCOP::debug(const QString& string) +{ + kdDebug() << "KonvDCOP::debug()" << endl; + emit dcopInfo(QString("Debug: %1").arg(string)); +} + +void KonvDCOP::error(const QString& string) +{ + kdDebug() << "KonvDCOP::error()" << endl; + emit dcopInfo(QString("Error: %1").arg(string)); +} + +void KonvDCOP::insertMarkerLine() +{ + emit dcopInsertMarkerLine(); +} + +void KonvDCOP::connectToServer(const QString& address, int port, const QString& channel, const QString& password) +{ + emit connectTo(Konversation::SilentlyReuseConnection, address, QString::number(port), password, "", channel); +} + +QString KonvDCOP::getNickname(const QString& serverName) +{ + Server* server = KonversationApplication::instance()->getConnectionManager()->getServerByName(serverName); + + if (!server) + { + error( i18n( "getNickname: Server %1 is not found." ).arg( serverName ) ); + return QString(); + } + + return server->getNickname(); +} + +QString KonvDCOP::getAnyNickname() +{ + KonversationApplication* konvApp = static_cast(kapp); + + Server* server = konvApp->getConnectionManager()->getAnyServer(); + + if (server) return server->getNickname(); + + return QString(); +} + +QString KonvDCOP::getChannelEncoding(const QString& server, const QString& channel) +{ + return Preferences::channelEncoding(server,channel); +} + +// Identity stuff +KonvIdentDCOP::KonvIdentDCOP() +: DCOPObject("identity"), +QObject(0, "identity") +{ +} + +QStringList KonvIdentDCOP::listIdentities() +{ + QStringList identities; + IdentityList ids = Preferences::identityList(); + for(IdentityList::ConstIterator it = ids.begin(); it != ids.end(); ++it) + { + identities.append((*it)->getName()); + } + return identities; +} + +void KonvIdentDCOP::setrealName(const QString &id_name, const QString& name) +{ + IdentityList ids = Preferences::identityList(); + + for(IdentityList::iterator it = ids.begin(); it != ids.end(); ++it) + { + if ((*it)->getName() == id_name) + { + (*it)->setRealName(name); + return; + } + } + +} + +QString KonvIdentDCOP::getrealName(const QString &id_name) +{ + IdentityList ids = Preferences::identityList(); + + for(IdentityList::ConstIterator it = ids.begin(); it != ids.end(); ++it) + { + if ((*it)->getName() == id_name) + { + return (*it)->getRealName(); + } + } + + return QString(); +} + +void KonvIdentDCOP::setIdent(const QString &/*identity*/, const QString& /*ident*/) +{ + //Preferences::identityByName(identity)->.setIdent(; +} + +QString KonvIdentDCOP::getIdent(const QString &identity) +{ + return Preferences::identityByName(identity)->getIdent(); +} + +void KonvIdentDCOP::setNickname(const QString &identity, int index,const QString& nick) +{ + const Identity *i = Preferences::identityByName(identity); + const_cast(i)->setNickname(index, nick); + static_cast(kapp)->saveOptions(true); +} + +QString KonvIdentDCOP::getNickname(const QString &identity, int index) +{ + return Preferences::identityByName(identity)->getNickname(index); +} + +void KonvIdentDCOP::setBot(const QString &identity, const QString& bot) +{ + const Identity *i = Preferences::identityByName(identity); + const_cast(i)->setBot(bot); + static_cast(kapp)->saveOptions(true); +} + +QString KonvIdentDCOP::getBot(const QString &identity) +{ + return Preferences::identityByName(identity)->getBot(); +} + +void KonvIdentDCOP::setPassword(const QString &identity, const QString& password) +{ + const Identity *i = Preferences::identityByName(identity); + const_cast(i)->setPassword(password); + static_cast(kapp)->saveOptions(true); +} + +QString KonvIdentDCOP::getPassword(const QString &identity) +{ + return Preferences::identityByName(identity)->getPassword(); +} + +void KonvIdentDCOP::setNicknameList(const QString &identity, const QStringList& newList) +{ + const Identity *i = Preferences::identityByName(identity); + const_cast(i)->setNicknameList(newList); + static_cast(kapp)->saveOptions(true); +} + +QStringList KonvIdentDCOP::getNicknameList(const QString &identity) +{ + return Preferences::identityByName(identity)->getNicknameList(); +} + +void KonvIdentDCOP::setQuitReason(const QString &identity, const QString& reason) +{ + const Identity *i = Preferences::identityByName(identity); + const_cast(i)->setQuitReason(reason); + static_cast(kapp)->saveOptions(true); +} + +QString KonvIdentDCOP::getQuitReason(const QString &identity) +{ + return Preferences::identityByName(identity)->getQuitReason(); +} + + +void KonvIdentDCOP::setPartReason(const QString &identity, const QString& reason) +{ + const Identity *i = Preferences::identityByName(identity); + const_cast(i)->setPartReason(reason); + static_cast(kapp)->saveOptions(true); +} + +QString KonvIdentDCOP::getPartReason(const QString &identity) +{ + return Preferences::identityByName(identity)->getPartReason(); +} + +void KonvIdentDCOP::setKickReason(const QString &identity, const QString& reason) +{ + const Identity *i = Preferences::identityByName(identity); + const_cast(i)->setKickReason(reason); + static_cast(kapp)->saveOptions(true); +} + +QString KonvIdentDCOP::getKickReason(const QString &identity) +{ + return Preferences::identityByName(identity)->getKickReason(); +} + +void KonvIdentDCOP::setShowAwayMessage(const QString &identity, bool state) +{ + const Identity *i = Preferences::identityByName(identity); + const_cast(i)->setShowAwayMessage(state); + static_cast(kapp)->saveOptions(true); +} + +bool KonvIdentDCOP::getShowAwayMessage(const QString &identity) +{ + return Preferences::identityByName(identity)->getShowAwayMessage(); +} + +void KonvIdentDCOP::setAwayMessage(const QString &identity, const QString& message) +{ + const Identity *i = Preferences::identityByName(identity); + const_cast(i)->setAwayMessage(message); + static_cast(kapp)->saveOptions(true); +} + +QString KonvIdentDCOP::getAwayMessage(const QString &identity) +{ + const QString f = Preferences::identityByName(identity)->getAwayMessage(); + return f; +} + +void KonvIdentDCOP::setReturnMessage(const QString &identity, const QString& message) +{ + const Identity *i = Preferences::identityByName(identity); + const_cast(i)->setReturnMessage(message); + static_cast(kapp)->saveOptions(true); +} + +QString KonvIdentDCOP::getReturnMessage(const QString &identity) +{ + return Preferences::identityByName(identity)->getReturnMessage(); +} + +#include "konvdcop.moc" diff --git a/konversation/src/konvdcop.h b/konversation/src/konvdcop.h new file mode 100644 index 0000000..3f513fb --- /dev/null +++ b/konversation/src/konvdcop.h @@ -0,0 +1,110 @@ +/* + 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. +*/ + +/* + The konversation DCOP interface class + begin: Mar 7 2003 + copyright: (C) 2003 by Alex Zepeda + email: zipzippy@sonic.net +*/ + +#ifndef KONV_DCOP_H +#define KONV_DCOP_H + +#include "konviface.h" +#include "common.h" + +#include +#include + + +class KonvDCOP : public QObject, virtual public KonvIface +{ + Q_OBJECT + + public: + KonvDCOP(); + + QString getNickname (const QString &server); + QString getAnyNickname (); + QString getChannelEncoding(const QString& server, const QString& channel); + + signals: + void dcopSay(const QString& server,const QString& target,const QString& command); + void dcopInfo(const QString& string); + void dcopInsertMarkerLine(); + void dcopRaw(const QString& server, const QString& command); + void dcopMultiServerRaw(const QString& command); + + void connectTo(Konversation::ConnectionFlag flag, + const QString& hostName, + const QString& port = "", + const QString& password = "", + const QString& nick = "", + const QString& channel = "", + bool useSSL = false); + + public slots: + void setAway(const QString &awaymessage); + void setBack(); + void sayToAll(const QString &message); + void actionToAll(const QString &message); + void raw(const QString& server,const QString& command); + void say(const QString& server,const QString& target,const QString& command); + void info(const QString& string); + void debug(const QString& string); + void error(const QString& string); + void insertMarkerLine(); + void connectToServer(const QString& adress, int port, const QString& channel, const QString& password); + QStringList listServers(); + QStringList listConnectedServers(); + + void setScreenSaverStarted(); + void setScreenSaverStopped(); +}; + +class KonvIdentDCOP : public QObject, virtual public KonvIdentityIface +{ + Q_OBJECT + + public: + KonvIdentDCOP(); + + void setrealName(const QString &identity, const QString& name); + QString getrealName(const QString &identity); + void setIdent(const QString &identity, const QString& ident); + QString getIdent(const QString &identity); + + void setNickname(const QString &identity, int index,const QString& nick); + QString getNickname(const QString &identity, int index); + + void setBot(const QString &identity, const QString& bot); + QString getBot(const QString &identity); + void setPassword(const QString &identity, const QString& password); + QString getPassword(const QString &identity); + + void setNicknameList(const QString &identity, const QStringList& newList); + QStringList getNicknameList(const QString &identity); + + void setQuitReason(const QString &identity, const QString& reason); + QString getQuitReason(const QString &identity); + void setPartReason(const QString &identity, const QString& reason); + QString getPartReason(const QString &identity); + void setKickReason(const QString &identity, const QString& reason); + QString getKickReason(const QString &identity); + + void setShowAwayMessage(const QString &identity, bool state); + bool getShowAwayMessage(const QString &identity); + + void setAwayMessage(const QString &identity, const QString& message); + QString getAwayMessage(const QString &identity); + void setReturnMessage(const QString &identity, const QString& message); + QString getReturnMessage(const QString &identity); + + QStringList listIdentities(); +}; +#endif diff --git a/konversation/src/konversation-0.19-appearance.pl b/konversation/src/konversation-0.19-appearance.pl new file mode 100755 index 0000000..ba440ac --- /dev/null +++ b/konversation/src/konversation-0.19-appearance.pl @@ -0,0 +1,52 @@ +#! /usr/bin/perl + +use strict; + +my $currentGroup = ""; +my $key; +my $value; +my $i; +my $out; +my @irccolors; +my @nickcolors; + +while (<>) +{ + chomp; + if ( /^\[/ ) + { + $currentGroup = $_; + next; + } + ($key, $value) = ($_ =~ /([^=]+)=[ \t]*([^\n]+)/); + if ($_ =~ /IRCColors/) + { + print("# DELETE $currentGroup$key\n"); + if ($value ne "#ffffff,#000000,#000080,#008000,#ff0000,#a52a2a,#800080,#ff8000,#808000,#00ff00,#008080,#00ffff,#0000ff,#ffc0cb,#a0a0a0,#c0c0c0") + { + $i = 0; + @irccolors = split(/,/, $value); + foreach $out (@irccolors) + { + $out =~ /([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})$/; + printf("IrcColorCode$i=%d,%d,%d\n",hex($1),hex($2),hex($3)); + $i++; + } + } + } + elsif ($_ =~ /NickColors/) + { + print("# DELETE $currentGroup$key\n"); + if ($value ne "#E90E7F,#8E55E9,#B30E0E,#18B33C,#58ADB3,#9E54B3,#0FB39A,#3176B3,#000000") + { + $i = 0; + @nickcolors = split(/,/, $value); + foreach $out (@nickcolors) + { + $out =~ /([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})$/; + printf("NickColor$i=%d,%d,%d\n",hex($1),hex($2),hex($3)); + $i++; + } + } + } +} diff --git a/konversation/src/konversation-0.19-colorcodes.pl b/konversation/src/konversation-0.19-colorcodes.pl new file mode 100644 index 0000000..5016c79 --- /dev/null +++ b/konversation/src/konversation-0.19-colorcodes.pl @@ -0,0 +1,26 @@ +#! /usr/bin/perl + +use strict; + +my $currentGroup = ""; +my $key; +my $value; + +while (<>) +{ + chomp; + if ( /^\[/ ) + { + $currentGroup = $_; + next; + } + ($key, $value) = ($_ =~ /([^=]+)=[ \t]*([^\n]+)/); + if ($_ =~ /FilterColorCodes/) + { + print("# DELETE $currentGroup$key\n"); + if ($value eq "true") + { + print("AllowColorCodes=false\n"); + } + } +} diff --git a/konversation/src/konversation-0.19-colors.pl b/konversation/src/konversation-0.19-colors.pl new file mode 100755 index 0000000..34a4918 --- /dev/null +++ b/konversation/src/konversation-0.19-colors.pl @@ -0,0 +1,23 @@ +#! /usr/bin/perl + +use strict; + +my $currentGroup = ""; +my $key; +my $value; + +while (<>) +{ + chomp; + if ( /^\[/ ) + { + $currentGroup = $_; + next; + } + ($key, $value) = ($_ =~ /([^=]+)=[ \t]*([^\n]+)/); + if ($value =~ /([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})$/) + { + print("# DELETE $currentGroup$key\n"); + printf("$key=%d,%d,%d\n",hex($1),hex($2),hex($3)); + } +} diff --git a/konversation/src/konversation-0.19-custombrowser.pl b/konversation/src/konversation-0.19-custombrowser.pl new file mode 100644 index 0000000..f63d0f2 --- /dev/null +++ b/konversation/src/konversation-0.19-custombrowser.pl @@ -0,0 +1,26 @@ +#! /usr/bin/perl + +use strict; + +my $currentGroup = ""; +my $key; +my $value; + +while (<>) +{ + chomp; + if ( /^\[/ ) + { + $currentGroup = $_; + next; + } + ($key, $value) = ($_ =~ /([^=]+)=[ \t]*([^\n]+)/); + if ($_ =~ /UseKdeDefault/) + { + print("# DELETE $currentGroup$key\n"); + if ($value eq "false") + { + print("UseCustomBrowser=true\n"); + } + } +} diff --git a/konversation/src/konversation-0.19-notifylists.pl b/konversation/src/konversation-0.19-notifylists.pl new file mode 100644 index 0000000..42bfe9d --- /dev/null +++ b/konversation/src/konversation-0.19-notifylists.pl @@ -0,0 +1,43 @@ +#! /usr/bin/perl + +use strict; + +my($out); +my($group); +my($gotgroup); +my(%group2groupno); +my(%key2value); +my(@split); +my(%saw); + +while (<>) +{ + if ($_ =~ /^\[ServerGroup ([0-9]+)\]/) + { + $group = $1; + $gotgroup = 1; + } + elsif ($_ =~ /^Name=(.+)/ && $gotgroup) + { + $group2groupno{$group} = $1; + $gotgroup = 0; + } + elsif ($_ =~ /^(.+)=(.+)/) + { + $key2value{$1} = $2; + } +} + +foreach $out (keys %group2groupno) +{ + @split = split(" ",$key2value{$group2groupno{$out}}); + + if (@split) + { + undef %saw; + @saw{@split} = (); + @split = keys %saw; + + print "[ServerGroup $out]\nNotifyList=@split\n"; + } +} diff --git a/konversation/src/konversation-0.19-sortorder.pl b/konversation/src/konversation-0.19-sortorder.pl new file mode 100755 index 0000000..6777a91 --- /dev/null +++ b/konversation/src/konversation-0.19-sortorder.pl @@ -0,0 +1,69 @@ +#! /usr/bin/perl + +use strict; + +my $currentGroup = ""; +my $name; +my $value; +my $out; +my %list; + +while (<>) +{ + chomp; + if ( /^\[/ ) + { + $currentGroup = $_; + next; + } + elsif ($_ =~ /AdminValue/) + { + ($name,$value) = split("=",$_); + $list{"$value"} = "p"; + print("# DELETE $currentGroup$name\n"); + } + elsif ($_ =~ /HalfopValue/) + { + ($name,$value) = split("=",$_); + $list{"$value"} = "h"; + print("# DELETE $currentGroup$name\n"); + } + elsif ($_ =~ /NoRightsValue/) + { + ($name,$value) = split("=",$_); + $list{"$value"} = "-"; + print("# DELETE $currentGroup$name\n"); + } + elsif ($_ =~ /OperatorValue/) + { + ($name,$value) = split("=",$_); + $list{"$value"} = "o"; + print("# DELETE $currentGroup$name\n"); + } + elsif ($_ =~ /OwnerValue/) + { + ($name,$value) = split("=",$_); + $list{"$value"} = "q"; + print("# DELETE $currentGroup$name\n"); + } + elsif ($_ =~ /VoiceValue/) + { + ($name,$value) = split("=",$_); + $list{"$value"} = "v"; + print("# DELETE $currentGroup$name\n"); + } + elsif ($_ =~ /AwayValue/) + { + ($name,$value) = split("=",$_); + print("# DELETE $currentGroup$name\n"); + } +} + +print "SortOrder="; + +foreach $out (reverse sort { $a <=> $b } keys %list) +{ + print $list{$out}; +} + +print "\n"; \ No newline at end of file diff --git a/konversation/src/konversation-0.19-tabplacement.pl b/konversation/src/konversation-0.19-tabplacement.pl new file mode 100755 index 0000000..91d9570 --- /dev/null +++ b/konversation/src/konversation-0.19-tabplacement.pl @@ -0,0 +1,26 @@ +#! /usr/bin/perl + +use strict; + +my $currentGroup = ""; +my $key; +my $value; + +while (<>) +{ + chomp; + if ( /^\[/ ) + { + $currentGroup = $_; + next; + } + ($key, $value) = ($_ =~ /([^=]+)=[ \t]*([^\n]+)/); + if ($_ =~ /TabPlacement/) + { + if ($value eq "0") + { + print("# DELETE $currentGroup$key\n"); + print("$key=Top\n"); + } + } +} diff --git a/konversation/src/konversation-0.20-customfonts.pl b/konversation/src/konversation-0.20-customfonts.pl new file mode 100644 index 0000000..21f3ae0 --- /dev/null +++ b/konversation/src/konversation-0.20-customfonts.pl @@ -0,0 +1,21 @@ +#! /usr/bin/perl + +use strict; + + +while (<>) +{ + chomp; + if ($_ =~ /^TextFont/) + { + print("CustomTextFont=true\n"); + } + if ($_ =~ /^ListFont/) + { + print("CustomListFont=true\n"); + } + if ($_ =~ /^TabFont/) + { + print("CustomTabFont=true\n"); + } +} diff --git a/konversation/src/konversation-0.20-quickbuttons.pl b/konversation/src/konversation-0.20-quickbuttons.pl new file mode 100644 index 0000000..c5b49bc --- /dev/null +++ b/konversation/src/konversation-0.20-quickbuttons.pl @@ -0,0 +1,137 @@ +#! /usr/bin/perl + +use strict; + +my $button0 = ""; +my $button1 = ""; +my $button2 = ""; +my $button3 = ""; +my $button4 = ""; +my $button5 = ""; +my $button6 = ""; +my $button7 = ""; + +while (<>) +{ + chomp; + if ($_ =~ /^Button0/) + { + $button0 = $_; + } + if ($_ =~ /^Button1/) + { + $button1 = $_; + } + if ($_ =~ /^Button2/) + { + $button2 = $_; + } + if ($_ =~ /^Button3/) + { + $button3 = $_; + } + if ($_ =~ /^Button4/) + { + $button4 = $_; + } + if ($_ =~ /^Button5/) + { + $button5 = $_; + } + if ($_ =~ /^Button6/) + { + $button6 = $_; + } + if ($_ =~ /^Button7/) + { + $button7 = $_; + } +} + +if ($button0 ne "") +{ + print("# DELETE [Button List]Button0\n"); + print("$button0\n"); +} +else +{ + print("# DELETE [Button List]Button0\n"); + print("Button0=Op,/OP %u%n\n"); +} + +if ($button1 ne "") +{ + print("# DELETE [Button List]Button1\n"); + print("$button1\n"); +} +else +{ + print("# DELETE [Button List]Button1\n"); + print("Button1=DeOp,/DEOP %u%n\n"); +} + +if ($button2 ne "") +{ + print("# DELETE [Button List]Button2\n"); + print("$button2\n"); +} +else +{ + print("# DELETE [Button List]Button2\n"); + print("Button2=WhoIs,/WHOIS %s,%%u%n\n"); +} + +if ($button3 ne "") +{ + print("# DELETE [Button List]Button3\n"); + print("$button3\n"); +} +else +{ + print("# DELETE [Button List]Button3\n"); + print("Button3=Version,/CTCP %s,%%u VERSION%n\n"); +} + +if ($button4 ne "") +{ + print("# DELETE [Button List]Button4\n"); + print("$button4\n"); +} +else +{ + print("# DELETE [Button List]Button4\n"); + print("Button4=Kick,/KICK %u%n\n"); +} + +if ($button5 ne "") +{ + print("# DELETE [Button List]Button5\n"); + print("$button5\n"); +} +else +{ + print("# DELETE [Button List]Button5\n"); + print("Button5=Ban,/BAN %u%n\n"); +} + +if ($button6 ne "") +{ + print("# DELETE [Button List]Button6\n"); + print("$button6\n"); +} +else +{ + print("# DELETE [Button List]Button6\n"); + print("Button6=Part,/PART %c Leaving...%n\n"); +} + +if ($button7 ne "") +{ + print("# DELETE [Button List]Button7\n"); + print("$button7\n"); +} +else +{ + print("# DELETE [Button List]Button7\n"); + print("Button7=Quit,/QUIT Leaving...%n\n"); +} \ No newline at end of file diff --git a/konversation/src/konversation.desktop b/konversation/src/konversation.desktop new file mode 100644 index 0000000..110292b --- /dev/null +++ b/konversation/src/konversation.desktop @@ -0,0 +1,47 @@ +[Desktop Entry] +Type=Application +Exec=konversation -caption "%c" %i +Icon=konversation +X-DocPath=konversation/index.html +GenericName=IRC Client +GenericName[ar]=زبون IRC +GenericName[bg]=IRC клиент +GenericName[br]=Kliant IRC +GenericName[ca]=Client IRC +GenericName[cs]=IRC klient +GenericName[cy]=Dibynnydd IRC +GenericName[da]=IRC-klient +GenericName[de]=IRC-Programm +GenericName[el]=Πελάτης IRC +GenericName[es]=Cliente de IRC +GenericName[et]=IRC klient +GenericName[ga]=Cliant IRC +GenericName[gl]=Cliente IRC +GenericName[he]=לקוח IRC +GenericName[it]=Client IRC +GenericName[ja]=IRC クライアント +GenericName[ka]=IRC საუბარი +GenericName[lt]=IRC klientas +GenericName[ms]=Klien IRC +GenericName[nl]=IRC-client +GenericName[pa]=IRC ਕਲਾਂਇਟ +GenericName[pt]=Cliente de IRC +GenericName[pt_BR]=Cliente IRC +GenericName[sr]=IRC клијент +GenericName[sr@Latn]=IRC klijent +GenericName[sv]=IRC-klient +GenericName[tr]=IRC İstemcisi +GenericName[uk]=Клієнт IRC +GenericName[xx]=xxIRC Clientxx +GenericName[zh_CN]=IRC 客户端 +GenericName[zh_TW]=IRC 客戶端程式 +Terminal=false +Name=Konversation +Name[hi]=कनवर्सेसन +Name[pa]=ਗੱਲਬਾਤ +Name[ta]=உரையாடல் +Name[xx]=xxKonversationxx +Categories=Qt;KDE;Network;IRCClient; +ServiceTypes=DCOP/InstantMessenger;DCOP/Unique +X-DCOP-ServiceName=konversation +X-DCOP-ServiceType=Unique diff --git a/konversation/src/konversation.upd b/konversation/src/konversation.upd new file mode 100644 index 0000000..0909314 --- /dev/null +++ b/konversation/src/konversation.upd @@ -0,0 +1,144 @@ +Id=1.1-rememberline +File=konversationrc +Group=General Options +Key=ShowRememberLineInAllWindows,MarkerLineInAllViews +RemoveKey=ShowRememberLineInAllWindows + +Id=1.1-markerlines +File=konversationrc +Group=Appearance,General Options +Key=AutoInsertRememberLineAfterMinimizing,AutomaticRememberLine +RemoveKey=AutoInsertRememberLineAfterMinimizing + +Id=0.20-customfonts +File=konversationrc +Group=Appearance +Script=konversation-0.20-customfonts.pl,perl + +Id=0.20-quickbuttons +File=konversationrc +Group=Button List +Script=konversation-0.20-quickbuttons.pl,perl + +Id=0.19-notifylists +File=konversationrc +Script=konversation-0.19-notifylists.pl,perl +RemoveGroup=Notify Group Lists + +Id=0.19-appearance +File=konversationrc +Group=Appearance +Key=CloseButtonsOnTabs,CloseButtons +RemoveKey=CloseButtonsOnTabs +RemoveKey=QuickButtons +RemoveKey=Codec +RemoveKey=FilterColorCodes +Script=konversation-0.19-appearance.pl,perl +Script=konversation-0.19-colorcodes.pl,perl + +Id=0.19-browser +File=konversationrc +Group=Web Browser Settings +Script=konversation-0.19-custombrowser.pl,perl + +Id=0.19-flags +File=konversationrc +Group=Flags +RemoveKey=BlinkingTabs +Script=konversation-0.19-tabplacement.pl,perl + +Id=0.19-highlightcolors +File=konversationrc +Group=Highlight List +Script=konversation-0.19-colors.pl,perl + +# Convert OSD color storage format +Id=0.19-osdcolors +File=konversationrc +Group=OSD +Script=konversation-0.19-colors.pl,perl + +# Convert nick list sort order storage format +Id=0.19-sortorder +File=konversationrc +Group=Sort Nicknames +Script=konversation-0.19-sortorder.pl,perl + +# Convert color storage format +Id=0.19-colors +File=konversationrc +Group=Message Text Colors +Script=konversation-0.19-colors.pl,perl + +Id=0.19-generaloptions +File=konversationrc +Group=General Options +Key=RedirectServerAndAppMsgToStatusPane,AndAppMsgToStatusPane +Key=ClickableNicks,UseClickableNicks +RemoveKey=RedirectServerAndAppMsgToStatusPane +RemoveKey=ClickableNicks +RemoveKey=ColorConfigurationGeometry +RemoveKey=ButtonGeometry +RemoveKey=Geometry +RemoveKey=HilightGeometry +RemoveKey=IgnoreGeometry +RemoveKey=KickReason +RemoveKey=LogfileGeometry +RemoveKey=PartReason +RemoveKey=ServerWindowStatusBarStatus +RemoveKey=ServerWindowToolBarIconSize +RemoveKey=ServerWindowToolBarIconText +RemoveKey=ServerWindowToolBarPos +RemoveKey=ServerWindowToolBarStatus +RemoveKey=ToolBarPos +RemoveKey=VersionReply +RemoveKey=MaximumLag + +Id=0.19-cleanup-themes +File=konversationrc +Group=Themes +RemoveKey=IconThemeIndex +RemoveKey=IconThemeName + +Id=0.19-cleanup-notifylist +File=konversationrc +Group=Notify List +RemoveKey=NotifyList + +Id=0.19-cleanup-dcc +File=konversationrc +Group=DCC Settings +RemoveKey=GetIpFromServer +RemoveKey=Rollback + +Id=0.19-cleanup-colors +File=konversationrc +Group=Colors +RemoveGroup=Colors + +Id=0.19-cleanup-hilightlist +File=konversationrc +Group=Hilight List +RemoveGroup=Hilight List + +Id=0.19-cleanup-notificationmessages +File=konversationrc +Group=Notification Messages +RemoveGroup=Notification Messages + +Id=0.19-cleanup-ledcolors +File=konversationrc +Group=Led Colors +RemoveGroup=Led Colors + +Id=0.19-cleanup-kmditaskbar +File=konversationrc +Group=MainWindow Toolbar KMdiTaskBar +RemoveGroup=MainWindow Toolbar KMdiTaskBar + +# Rename ChannelSplitter +Id=0.19-channelsplitter +File=konversationrc +Group=Appearance +Key=ChannelSplitter,ChannelSplitterSizes +RemoveKey=ChannelSplitter diff --git a/konversation/src/konversationapplication.cpp b/konversation/src/konversationapplication.cpp new file mode 100644 index 0000000..fd0afa7 --- /dev/null +++ b/konversation/src/konversationapplication.cpp @@ -0,0 +1,888 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2005 Ismail Donmez + Copyright (C) 2005 Peter Simonsson + Copyright (C) 2005 John Tapsell + Copyright (C) 2005-2008 Eike Hein +*/ + +#include "konversationapplication.h" +#include "konversationmainwindow.h" +#include "connectionmanager.h" +#include "awaymanager.h" +#include "dcctransfermanager.h" +#include "viewcontainer.h" +#include "highlight.h" +#include "server.h" +#include "konversationsound.h" +#include "quickconnectdialog.h" +#include "servergroupsettings.h" +#include "serversettings.h" +#include "channel.h" +#include "images.h" +#include "notificationhandler.h" +#include "commit.h" +#include "version.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +KonversationApplication::KonversationApplication() +: KUniqueApplication(true, true, true) +{ + mainWindow = 0; + m_connectionManager = 0; + m_awayManager = 0; + quickConnectDialog = 0; + osd = 0; +} + +KonversationApplication::~KonversationApplication() +{ + kdDebug() << k_funcinfo << endl; + Server::_stashRates(); + Preferences::writeConfig(); + saveOptions(false); + + delete m_images; + delete dcopObject; + //delete prefsDCOP; + delete identDCOP; + delete osd; + osd = 0; +} + +int KonversationApplication::newInstance() +{ + KCmdLineArgs* args = KCmdLineArgs::parsedArgs(); + QCString url; + if (args->count() > 0) url = args->arg(0); + + if (!mainWindow) + { + connect(this, SIGNAL(shutDown()), this, SLOT(prepareShutdown())); + + m_connectionManager = new ConnectionManager(this); + + m_awayManager = new AwayManager(this); + + connect(m_connectionManager, SIGNAL(identityOnline(int)), m_awayManager, SLOT(identityOnline(int))); + connect(m_connectionManager, SIGNAL(identityOffline(int)), m_awayManager, SLOT(identityOffline(int))); + connect(m_connectionManager, SIGNAL(identityOffline(int)), m_awayManager, SLOT(identityOffline(int))); + connect(m_connectionManager, SIGNAL(connectionChangedAwayState(bool)), m_awayManager, SLOT(updateGlobalAwayAction(bool))); + + // an instance of DccTransferManager needs to be created before GUI class instances' creation. + m_dccTransferManager = new DccTransferManager(this); + + // make sure all vars are initialized properly + quickConnectDialog = 0; + + // Sound object used to play sound... + m_sound = new Konversation::Sound(this); + + // initialize OSD display here, so we can read the Preferences::properly + osd = new OSDWidget( "Konversation" ); + + Preferences::self(); + readOptions(); + + // Images object providing LEDs, NickIcons + m_images = new Images(); + connect(this, SIGNAL(iconChanged(int)), m_images, SLOT(updateIcons())); + + // Auto-alias scripts. This adds any missing aliases + QStringList aliasList(Preferences::aliasList()); + QStringList scripts(Preferences::defaultAliasList()); + bool changed = false; + for ( QStringList::ConstIterator it = scripts.begin(); it != scripts.end(); ++it ) + { + if(!aliasList.contains(*it)) { + changed = true; + aliasList.append(*it); + } + } + if(changed) + Preferences::setAliasList(aliasList); + + // Setup system codec + // TODO: check if this works now as intended + // QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale()); + + // open main window + mainWindow = new KonversationMainWindow(); + setMainWidget(mainWindow); + + connect(mainWindow, SIGNAL(showQuickConnectDialog()), this, SLOT(openQuickConnectDialog()) ); + connect(Preferences::self(), SIGNAL(updateTrayIcon()), mainWindow, SLOT(updateTrayIcon()) ); + connect(osd, SIGNAL(hidden()), mainWindow, SIGNAL(endNotification())); + // take care of user style changes, setting back colors and stuff + + // apply GUI settings + emit appearanceChanged(); + + if (Preferences::showTrayIcon() && (Preferences::hiddenToTray() || Preferences::hideToTrayOnStartup())) + mainWindow->hide(); + else + mainWindow->show(); + + bool openServerList = Preferences::showServerList(); + + // handle autoconnect on startup + Konversation::ServerGroupList serverGroups = Preferences::serverGroupList(); + + if (url.isEmpty() && !args->isSet("server")) + { + for (Konversation::ServerGroupList::iterator it = serverGroups.begin(); it != serverGroups.end(); ++it) + { + if ((*it)->autoConnectEnabled()) + { + openServerList = false; + m_connectionManager->connectTo(Konversation::CreateNewConnection, (*it)->id()); + } + } + } + + if (openServerList) mainWindow->openServerList(); + + connect(this, SIGNAL(serverGroupsChanged(const Konversation::ServerGroupSettings*)), this, SLOT(saveOptions())); + + // prepare dcop interface + dcopObject = new KonvDCOP; + kapp->dcopClient()->setDefaultObject(dcopObject->objId()); + identDCOP = new KonvIdentDCOP; + + if (dcopObject) + { + connect(dcopObject,SIGNAL (dcopMultiServerRaw(const QString&)), + this,SLOT (dcopMultiServerRaw(const QString&)) ); + connect(dcopObject,SIGNAL (dcopRaw(const QString&,const QString&)), + this,SLOT (dcopRaw(const QString&,const QString&)) ); + connect(dcopObject,SIGNAL (dcopSay(const QString&,const QString&,const QString&)), + this,SLOT (dcopSay(const QString&,const QString&,const QString&)) ); + connect(dcopObject,SIGNAL (dcopInfo(const QString&)), + this,SLOT (dcopInfo(const QString&)) ); + connect(dcopObject,SIGNAL (dcopInsertMarkerLine()), + mainWindow,SIGNAL(insertMarkerLine())); + connect(dcopObject, SIGNAL(connectTo(Konversation::ConnectionFlag, const QString&, const QString&, const QString&, const QString&, const QString&, bool)), + m_connectionManager, SLOT(connectTo(Konversation::ConnectionFlag, const QString&, const QString&, const QString&, const QString&, const QString&, bool))); + } + + m_notificationHandler = new Konversation::NotificationHandler(this); + } + + if (!url.isEmpty()) + getConnectionManager()->connectTo(Konversation::SilentlyReuseConnection, url); + else if (args->isSet("server")) + { + getConnectionManager()->connectTo(Konversation::SilentlyReuseConnection, + args->getOption("server"), + args->getOption("port"), + args->getOption("password"), + args->getOption("nick"), + args->getOption("channel"), + args->isSet("ssl")); + } + + return KUniqueApplication::newInstance(); +} + +KonversationApplication* KonversationApplication::instance() +{ + return static_cast(KApplication::kApplication()); +} + +void KonversationApplication::prepareShutdown() +{ + if (mainWindow->isHidden() && Preferences::showTrayIcon()) + Preferences::setHiddenToTray(true); + else + Preferences::setHiddenToTray(false); + + mainWindow->getViewContainer()->prepareShutdown(); + + m_awayManager->blockSignals(true); + delete m_awayManager; + + m_connectionManager->quitServers(); + m_connectionManager->blockSignals(true); + delete m_connectionManager; +} + +void KonversationApplication::showQueueTuner(bool p) +{ + getMainWindow()->getViewContainer()->showQueueTuner(p); +} + +void KonversationApplication::dcopMultiServerRaw(const QString &command) +{ + sendMultiServerCommand(command.section(' ', 0,0), command.section(' ', 1)); +} + +void KonversationApplication::dcopRaw(const QString& connection, const QString &command) +{ + Server* server = 0; + + bool conversion = false; + int connectionId = connection.toInt(&conversion); + + if (conversion) server = getConnectionManager()->getServerByConnectionId(connectionId); + + if (!server) server = getConnectionManager()->getServerByName(connection); + + if (server) server->dcopRaw(command); +} + + +void KonversationApplication::dcopSay(const QString& connection, const QString& target, const QString& command) +{ + Server* server = 0; + + bool conversion = false; + int connectionId = connection.toInt(&conversion); + + if (conversion) server = getConnectionManager()->getServerByConnectionId(connectionId); + + if (!server) server = getConnectionManager()->getServerByName(connection); + + if (server) server->dcopSay(target, command); +} + +void KonversationApplication::dcopInfo(const QString& string) +{ + mainWindow->getViewContainer()->appendToFrontmost(i18n("DCOP"), string, 0); +} + +void KonversationApplication::readOptions() +{ + // get standard config file + KConfig* config=kapp->config(); + + // read nickname sorting order for channel nick lists + config->setGroup("Sort Nicknames"); + QString sortOrder=config->readEntry("SortOrder"); + QStringList sortOrderList=QStringList::split("",sortOrder); + sortOrderList.sort(); + if (sortOrderList.join("")!="-hopqv") + { + sortOrder=Preferences::defaultNicknameSortingOrder(); + Preferences::setSortOrder(sortOrder); + } + + // Identity list + QStringList identityList=config->groupList().grep(QRegExp("Identity [0-9]+")); + if(!identityList.isEmpty()) + { + Preferences::clearIdentityList(); + + for(unsigned int index=0;indexsetGroup(identityList[index]); + + newIdentity->setName(config->readEntry("Name")); + + newIdentity->setIdent(config->readEntry("Ident")); + newIdentity->setRealName(config->readEntry("Realname")); + + newIdentity->setNicknameList(config->readListEntry("Nicknames")); + + newIdentity->setBot(config->readEntry("Bot")); + newIdentity->setPassword(config->readEntry("Password")); + + newIdentity->setInsertRememberLineOnAway(config->readBoolEntry("InsertRememberLineOnAway")); + newIdentity->setShowAwayMessage(config->readBoolEntry("ShowAwayMessage")); + newIdentity->setAwayMessage(config->readEntry("AwayMessage")); + newIdentity->setReturnMessage(config->readEntry("ReturnMessage")); + newIdentity->setAutomaticAway(config->readBoolEntry("AutomaticAway", false)); + newIdentity->setAwayInactivity(config->readNumEntry("AwayInactivity", 10)); + newIdentity->setAutomaticUnaway(config->readBoolEntry("AutomaticUnaway", false)); + + newIdentity->setQuitReason(config->readEntry("QuitReason")); + newIdentity->setPartReason(config->readEntry("PartReason")); + newIdentity->setKickReason(config->readEntry("KickReason")); + + newIdentity->setShellCommand(config->readEntry("PreShellCommand")); + + newIdentity->setCodecName(config->readEntry("Codec")); + + newIdentity->setAwayNick(config->readEntry("AwayNick")); + + Preferences::addIdentity(newIdentity); + + } + + } + + osd->setEnabled(Preferences::useOSD()); + + //How to load the font from the text? + osd->setFont(Preferences::oSDFont()); + + osd->setDuration(Preferences::oSDDuration()); + osd->setScreen(Preferences::oSDScreen()); + osd->setShadow(Preferences::oSDDrawShadow()); + + osd->setOffset(Preferences::oSDOffsetX(), Preferences::oSDOffsetY()); + osd->setAlignment((OSDWidget::Alignment)Preferences::oSDAlignment()); + + if(Preferences::oSDUseCustomColors()) + { + osd->setTextColor(Preferences::oSDTextColor()); + osd->setBackgroundColor(Preferences::oSDBackgroundColor()); + } + + // Check if there is old server list config + config->setGroup("Server List"); + + // Read the new server settings + QStringList groups = config->groupList().grep(QRegExp("ServerGroup [0-9]+")); + QMap notifyList; + + if(!groups.isEmpty()) + { + Konversation::ServerGroupList serverGroups; + QStringList::iterator it; + QStringList tmp1; + QStringList::iterator it2; + Konversation::ChannelList channelHistory; + Konversation::ServerSettings server; + Konversation::ChannelSettings channel; + + for(it = groups.begin(); it != groups.end(); ++it) + { + config->setGroup((*it)); + Konversation::ServerGroupSettingsPtr serverGroup = new Konversation::ServerGroupSettings; + serverGroup->setName(config->readEntry("Name")); + serverGroup->setIdentityId(Preferences::identityByName(config->readEntry("Identity"))->id()); + serverGroup->setConnectCommands(config->readEntry("ConnectCommands")); + serverGroup->setAutoConnectEnabled(config->readBoolEntry("AutoConnect")); + serverGroup->setNotificationsEnabled(config->readBoolEntry("EnableNotifications", true)); + serverGroup->setExpanded(config->readBoolEntry("Expanded", false)); + + notifyList.insert((*serverGroup).id(),QStringList::split(' ',config->readEntry("NotifyList"))); + + tmp1 = config->readListEntry("ServerList"); + for(it2 = tmp1.begin(); it2 != tmp1.end(); ++it2) + { + config->setGroup((*it2)); + server.setHost(config->readEntry("Server")); + server.setPort(config->readNumEntry("Port")); + server.setPassword(config->readEntry("Password")); + server.setSSLEnabled(config->readBoolEntry("SSLEnabled")); + serverGroup->addServer(server); + } + + config->setGroup((*it)); + tmp1 = config->readListEntry("AutoJoinChannels"); + + for(it2 = tmp1.begin(); it2 != tmp1.end(); ++it2) + { + config->setGroup((*it2)); + + if(!config->readEntry("Name").isEmpty()) + { + channel.setName(config->readEntry("Name")); + channel.setPassword(config->readEntry("Password")); + serverGroup->addChannel(channel); + } + } + + config->setGroup((*it)); + tmp1 = config->readListEntry("ChannelHistory"); + channelHistory.clear(); + + for(it2 = tmp1.begin(); it2 != tmp1.end(); ++it2) + { + config->setGroup((*it2)); + + if(!config->readEntry("Name").isEmpty()) + { + channel.setName(config->readEntry("Name")); + channel.setPassword(config->readEntry("Password")); + channel.setNotificationsEnabled(config->readBoolEntry("EnableNotifications", true)); + channelHistory.append(channel); + } + } + + serverGroup->setChannelHistory(channelHistory); + + serverGroups.append(serverGroup); + } + + Preferences::setServerGroupList(serverGroups); + } + + // Notify Settings and lists. Must follow Server List. + Preferences::setNotifyList(notifyList); + Preferences::setNotifyDelay(Preferences::notifyDelay()); + Preferences::setUseNotify(Preferences::useNotify()); + + // Quick Buttons List + + // if there are button definitions in the config file, remove default buttons + if(config->hasGroup("Button List")) Preferences::clearQuickButtonList(); + config->setGroup("Button List"); + // Read all default buttons + QStringList buttonList(Preferences::quickButtonList()); + // Read all quick buttons + int index=0; + while(config->hasKey(QString("Button%1").arg(index))) + { + buttonList.append(config->readEntry(QString("Button%1").arg(index++))); + } // while + // Put back the changed button list + Preferences::setQuickButtonList(buttonList); + + // Autoreplace List + + // if there are autoreplace definitions in the config file, remove default entries + if(config->hasGroup("Autoreplace List")) Preferences::clearAutoreplaceList(); + config->setGroup("Autoreplace List"); + // Read all default entries + QStringList autoreplaceList(Preferences::autoreplaceList()); + // Read all entries + index=0; + while(config->hasKey(QString("Autoreplace%1").arg(index))) + { + // read entry and get length of the string + QString entry=config->readEntry(QString("Autoreplace%1").arg(index++)); + unsigned int length=entry.length()-1; + // if there's a "#" in the end, strip it (used to preserve blanks at the end of the replacement text) + // there should always be one, but older versions did not do it, so we check first + if(entry.at(length)=='#') entry=entry.left(length); + // add entry to internal list + autoreplaceList.append(entry); + } // while + // Put back the changed autoreplace list + Preferences::setAutoreplaceList(autoreplaceList); + + // Highlight List + if(config->hasKey("Highlight")) // Stay compatible with versions < 0.14 + { + QString highlight=config->readEntry("Highlight"); + QStringList hiList=QStringList::split(' ',highlight); + + unsigned int hiIndex; + for(hiIndex=0;hiIndexdeleteEntry("Highlight"); + } + else + { + int i = 0; + + while(config->hasGroup(QString("Highlight%1").arg(i))) + { + config->setGroup(QString("Highlight%1").arg(i)); + Preferences::addHighlight(config->readEntry("Pattern"), + config->readBoolEntry("RegExp"), + config->readColorEntry("Color"), + config->readPathEntry("Sound"), + config->readEntry("AutoText")); + i++; + } + } + + // Ignore List + config->setGroup("Ignore List"); + // Remove all default entries if there is at least one Ignore in the Preferences::file + if(config->hasKey("Ignore0")) Preferences::clearIgnoreList(); + // Read all ignores + index=0; + while(config->hasKey(QString("Ignore%1").arg(index))) + { + Preferences::addIgnore(config->readEntry(QString("Ignore%1").arg(index++))); + } + + // Aliases + config->setGroup("Aliases"); + QStringList newList=config->readListEntry("AliasList"); + if(!newList.isEmpty()) Preferences::setAliasList(newList); + + // Channel Encodings + QMap channelEncodingEntries=config->entryMap("Channel Encodings"); + QRegExp re("^(.+) ([^\\s]+)$"); + QStringList channelEncodingEntryKeys=channelEncodingEntries.keys(); + QStringList::iterator itStr=channelEncodingEntryKeys.begin(); + for(; itStr != channelEncodingEntryKeys.end(); ++itStr) + { + if(re.search(*itStr) > -1) + { + int serverGroupId = Preferences::serverGroupIdByName(re.cap(1)); + if(serverGroupId != -1) + Preferences::setChannelEncoding(serverGroupId,re.cap(2),channelEncodingEntries[*itStr]); + } + } + + // O, what a tangled web + Server::_fetchRates(); +} + +void KonversationApplication::saveOptions(bool updateGUI) +{ + KConfig* config=kapp->config(); + +// Should be handled in NicklistBehaviorConfigController now +// config->setGroup("Sort Nicknames"); + + // Clean up identity list + QStringList identities=config->groupList().grep(QRegExp("Identity [0-9]+")); + if(identities.count()) + { + // remove old identity list from Preferences::file to keep numbering under control + for(unsigned int index=0;indexdeleteGroup(identities[index]); + } + + IdentityList identityList = Preferences::identityList(); + int index = 0; + + for(IdentityList::ConstIterator it = identityList.begin(); it != identityList.end(); ++it) + { + IdentityPtr identity = (*it); + config->setGroup(QString("Identity %1").arg(index)); + + config->writeEntry("Name",identity->getName()); + config->writeEntry("Ident",identity->getIdent()); + config->writeEntry("Realname",identity->getRealName()); + config->writeEntry("Nicknames",identity->getNicknameList()); + config->writeEntry("Bot",identity->getBot()); + config->writeEntry("Password",identity->getPassword()); + config->writeEntry("InsertRememberLineOnAway", identity->getInsertRememberLineOnAway()); + config->writeEntry("ShowAwayMessage",identity->getShowAwayMessage()); + config->writeEntry("AwayMessage",identity->getAwayMessage()); + config->writeEntry("ReturnMessage",identity->getReturnMessage()); + config->writeEntry("AutomaticAway", identity->getAutomaticAway()); + config->writeEntry("AwayInactivity", identity->getAwayInactivity()); + config->writeEntry("AutomaticUnaway", identity->getAutomaticUnaway()); + config->writeEntry("QuitReason",identity->getQuitReason()); + config->writeEntry("PartReason",identity->getPartReason()); + config->writeEntry("KickReason",identity->getKickReason()); + config->writeEntry("PreShellCommand",identity->getShellCommand()); + config->writeEntry("Codec",identity->getCodecName()); + config->writeEntry("AwayNick", identity->getAwayNick()); + index++; + } // endfor + + // Remove the old servergroups from the config + QStringList groups = config->groupList().grep(QRegExp("ServerGroup [0-9]+")); + if(groups.count()) + { + QStringList::iterator it; + for(it = groups.begin(); it != groups.end(); ++it) + { + config->deleteGroup((*it)); + } + } + + // Remove the old servers from the config + groups = config->groupList().grep(QRegExp("Server [0-9]+")); + if(groups.count()) + { + QStringList::iterator it; + for(it = groups.begin(); it != groups.end(); ++it) + { + config->deleteGroup((*it)); + } + } + + // Remove the old channels from the config + groups = config->groupList().grep(QRegExp("Channel [0-9]+")); + if(groups.count()) + { + QStringList::iterator it; + for(it = groups.begin(); it != groups.end(); ++it) + { + config->deleteGroup((*it)); + } + } + + // Add the new servergroups to the config + Konversation::ServerGroupList serverGroupList = Preferences::serverGroupList(); + Konversation::ServerGroupList::iterator it; + index = 0; + int index2 = 0; + int index3 = 0; + int width = QString::number(serverGroupList.count()).length(); + QString groupName; + QStringList servers; + Konversation::ServerList::iterator it2; + Konversation::ServerList serverlist; + Konversation::ChannelList channelList; + Konversation::ChannelList::iterator it3; + QStringList channels; + QStringList channelHistory; + + for(it = serverGroupList.begin(); it != serverGroupList.end(); ++it) + { + serverlist = (*it)->serverList(); + servers.clear(); + + for(it2 = serverlist.begin(); it2 != serverlist.end(); ++it2) + { + groupName = QString("Server %1").arg(index2); + servers.append(groupName); + config->setGroup(groupName); + config->writeEntry("Server", (*it2).host()); + config->writeEntry("Port", (*it2).port()); + config->writeEntry("Password", (*it2).password()); + config->writeEntry("SSLEnabled", (*it2).SSLEnabled()); + index2++; + } + + channelList = (*it)->channelList(); + channels.clear(); + + for(it3 = channelList.begin(); it3 != channelList.end(); ++it3) + { + groupName = QString("Channel %1").arg(index3); + channels.append(groupName); + config->setGroup(groupName); + config->writeEntry("Name", (*it3).name()); + config->writeEntry("Password", (*it3).password()); + index3++; + } + + channelList = (*it)->channelHistory(); + channelHistory.clear(); + + for(it3 = channelList.begin(); it3 != channelList.end(); ++it3) + { + groupName = QString("Channel %1").arg(index3); + channelHistory.append(groupName); + config->setGroup(groupName); + config->writeEntry("Name", (*it3).name()); + config->writeEntry("Password", (*it3).password()); + config->writeEntry("EnableNotifications", (*it3).enableNotifications()); + index3++; + } + + config->setGroup(QString("ServerGroup %1").arg(QString::number(index).rightJustify(width,'0'))); + config->writeEntry("Name", (*it)->name()); + config->writeEntry("Identity", (*it)->identity()->getName()); + config->writeEntry("ServerList", servers); + config->writeEntry("AutoJoinChannels", channels); + config->writeEntry("ConnectCommands", (*it)->connectCommands()); + config->writeEntry("AutoConnect", (*it)->autoConnectEnabled()); + config->writeEntry("ChannelHistory", channelHistory); + config->writeEntry("EnableNotifications", (*it)->enableNotifications()); + config->writeEntry("Expanded", (*it)->expanded()); + config->writeEntry("NotifyList",Preferences::notifyStringByGroupName((*it)->name())); + index++; + } + + config->deleteGroup("Server List"); + + // Ignore List + config->deleteGroup("Ignore List"); + config->setGroup("Ignore List"); + QPtrList ignoreList=Preferences::ignoreList(); + Ignore* item=ignoreList.first(); + index=0; + while(item) + { + config->writeEntry(QString("Ignore%1").arg(index),QString("%1,%2").arg(item->getName()).arg(item->getFlags())); + item=ignoreList.next(); + index++; + } + + // Channel Encodings + // remove all entries once + config->deleteGroup("Channel Encodings"); + config->setGroup("Channel Encodings"); + QValueList encServers=Preferences::channelEncodingsServerGroupIdList(); + //i have no idea these would need to be sorted //encServers.sort(); + QValueList::iterator encServer; + for ( encServer = encServers.begin(); encServer != encServers.end(); ++encServer ) + { + Konversation::ServerGroupSettingsPtr sgsp = Preferences::serverGroupById(*encServer); + if ( sgsp ) // sgsp == 0 when the entry is of QuickConnect or something? + { + QStringList encChannels=Preferences::channelEncodingsChannelList(*encServer); + //ditto //encChannels.sort(); + QStringList::iterator encChannel; + for ( encChannel = encChannels.begin(); encChannel != encChannels.end(); ++encChannel ) + { + QString enc = Preferences::channelEncoding(*encServer, *encChannel); + QString key = sgsp->name() + ' ' + (*encChannel); + config->writeEntry(key, enc); + } + } + } + + config->sync(); + + if(updateGUI) + emit appearanceChanged(); +} + +// FIXME: use KURL maybe? +void KonversationApplication::storeUrl(const QString& who,const QString& newUrl) +{ + QString url(newUrl); + // clean up URL to help KRun() in URL catcher interface + if(url.startsWith("www.")) url="http://"+url; + else if(url.startsWith("ftp.")) url="ftp://"+url; + + url=url.replace("&","&"); + + // check that we don't add the same URL twice + deleteUrl(who,url); + urlList.append(who+' '+url); + emit catchUrl(who,url); +} + +const QStringList& KonversationApplication::getUrlList() +{ + return urlList; +} + +void KonversationApplication::deleteUrl(const QString& who,const QString& url) +{ + urlList.remove(who+' '+url); +} + +void KonversationApplication::clearUrlList() +{ + urlList.clear(); +} + +void KonversationApplication::openQuickConnectDialog() +{ + quickConnectDialog = new QuickConnectDialog(mainWindow); + connect(quickConnectDialog, SIGNAL(connectClicked(Konversation::ConnectionFlag, const QString&, const QString&, + const QString&, const QString&, const QString&, bool)), + m_connectionManager, SLOT(connectTo(Konversation::ConnectionFlag, const QString&, const QString&, + const QString&, const QString&, const QString&, bool))); + quickConnectDialog->show(); +} + +void KonversationApplication::sendMultiServerCommand(const QString& command, const QString& parameter) +{ + QPtrList serverList = getConnectionManager()->getServerList(); + + for (Server* server = serverList.first(); server; server = serverList.next()) + server->executeMultiServerCommand(command, parameter); +} + +void KonversationApplication::splitNick_Server(const QString& nick_server, QString &ircnick, QString &serverOrGroup) +{ + //kaddresbook uses the utf separator 0xE120, so treat that as a separator as well + QString nickServer = nick_server; + nickServer.replace(QChar(0xE120), "@"); + ircnick = nickServer.section("@",0,0); + serverOrGroup = nickServer.section("@",1); +} + +NickInfoPtr KonversationApplication::getNickInfo(const QString &ircnick, const QString &serverOrGroup) +{ + QPtrList serverList = getConnectionManager()->getServerList(); + NickInfoPtr nickInfo; + QString lserverOrGroup = serverOrGroup.lower(); + for(Server* lookServer = serverList.first(); lookServer; lookServer = serverList.next()) + { + if(lserverOrGroup.isEmpty() + || lookServer->getServerName().lower()==lserverOrGroup + || lookServer->getDisplayName().lower()==lserverOrGroup) + { + nickInfo = lookServer->getNickInfo(ircnick); + if(nickInfo) return nickInfo; //If we found one + } + } + return 0; +} + +// auto replace on input/output +QString KonversationApplication::doAutoreplace(const QString& text,bool output) +{ + // get autoreplace list + QStringList autoreplaceList=Preferences::autoreplaceList(); + // working copy + QString line=text; + + // loop through the list of replacement patterns + for(unsigned int index=0;index= 0 && index < (int)line.length()); + } + else + { + QRegExp needleReg("\\b" + QRegExp::escape(pattern) + "\\b"); + needleReg.setCaseSensitive(false); + line.replace(needleReg,replacement); + } + } + } + + return line; +} + +#include "konversationapplication.moc" + +// kate: space-indent on; tab-width 4; indent-width 4; mixed-indent off; replace-tabs on; +// vim: set et sw=4 ts=4 cino=l1,cs,U1: diff --git a/konversation/src/konversationapplication.h b/konversation/src/konversationapplication.h new file mode 100644 index 0000000..3464406 --- /dev/null +++ b/konversation/src/konversationapplication.h @@ -0,0 +1,169 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2005 Ismail Donmez + Copyright (C) 2005 Peter Simonsson + Copyright (C) 2005 John Tapsell + Copyright (C) 2005-2008 Eike Hein +*/ + +#ifndef KONVERSATIONAPPLICATION_H +#define KONVERSATIONAPPLICATION_H + +#include "preferences.h" +#include "osd.h" +#include "konvdcop.h" +#include "identity.h" +#include "nickinfo.h" + +#include + + +class QCString; + +class ConnectionManager; +class AwayManager; +class DccTransferManager; +class KonversationMainWindow; +class KonvDCOP; +class Server; +class QuickConnectDialog; +class Images; +class ServerGroupSettings; + +namespace Konversation +{ + class Sound; + class NotificationHandler; + + // Shared between NickListView and IRCView + enum PopupIDs + { + ModesSub,GiveOp,TakeOp,GiveHalfOp,TakeHalfOp,GiveVoice,TakeVoice, + KickBanSub,IgnoreNick,UnignoreNick, + Kick,KickBan,BanNick,BanHost,BanDomain,BanUserHost,BanUserDomain, + KickBanHost,KickBanDomain,KickBanUserHost,KickBanUserDomain, + Whois,Version,Ping,OpenQuery,DccSend,Join,Names,Topic, + CustomID, AddressbookSub, AddressbookChange, AddressbookNew, AddressbookDelete, + AddressbookEdit, SendEmail, StartDccChat, AddNotify + }; + +} + +class KonversationApplication : public KUniqueApplication +{ + Q_OBJECT + + public: + /** This function in general shouldn't be called, because in the future there + * may be multiple windows. + * However, in some situations we have messageboxes that aren't targeted for + * any particular main window, such as general errors from dcop calls. + * + * Note to any MDI developer - get this to return any of the windows, or some + * 'main' one. + */ + KonversationMainWindow* getMainWindow() { return mainWindow; } + + ConnectionManager* getConnectionManager() { return m_connectionManager; } + AwayManager* getAwayManager() { return m_awayManager; } + DccTransferManager* getDccTransferManager() { return m_dccTransferManager; } + + // HACK + void showQueueTuner(bool); + + // URL-Catcher + void storeUrl(const QString& who,const QString& url); + const QStringList& getUrlList(); + + KonversationApplication(); + ~KonversationApplication(); + + static KonversationApplication* instance(); + + /** For dcop and addressbook, a user can be specified as user@irc.server.net + * or user\@servergroup or using the unicode separator symbol 0xE120 instead + * of the "@". This function takes a string like the above examples, and + * modifies ircnick and serverOrGroup to contain the split up string. If + * the string doesn't have an @ or 0xE120, ircnick is set to the + * nick_server, and serverOrGroup is set to empty. + * Behaviour is undefined for serverOrGroup if multiple @ or 0xE120 are found. + * @param nick_server A string containting ircnick and possibly servername or server group + * @param ircnick This is modified to contain the ircnick + * @param serverOrGroup This is modified to contain the servername, servergroup or an empty string. + */ + static void splitNick_Server(const QString& nick_server, QString &ircnick, QString &serverOrGroup); + + /** Tries to find a nickinfo for a given ircnick on a given ircserver. + * @param ircnick The case-insensitive ircnick of the person you want to find. e.g. "johnflux" + * @param serverOrGroup The case-insensitive server name (e.g. "irc.kde.org") or server group name (e.g. "freenode"), or null to search all servers + * @return A nickinfo for this user and server if one is found. + */ + NickInfoPtr getNickInfo(const QString &ircnick, const QString &serverOrGroup); + + OSDWidget* osd; + + Konversation::Sound* sound() { return m_sound; } + + Images* images() { return m_images; } + + Konversation::NotificationHandler* notificationHandler() const { return m_notificationHandler; } + + // auto replacement for input or output lines + QString doAutoreplace(const QString& text,bool output); + + int newInstance(); + + + signals: + void catchUrl(const QString& who,const QString& url); + void serverGroupsChanged(const Konversation::ServerGroupSettings* serverGroup); + + + public slots: + void readOptions(); + void saveOptions(bool updateGUI=true); + + void deleteUrl(const QString& who,const QString& url); + void clearUrlList(); + + + protected slots: + void prepareShutdown(); + + void openQuickConnectDialog(); + + void dcopMultiServerRaw(const QString &command); + void dcopRaw(const QString& connection, const QString &command); + void dcopSay(const QString& connection, const QString& target, const QString& command); + void dcopInfo(const QString& string); + void sendMultiServerCommand(const QString& command, const QString& parameter); + + + private: + ConnectionManager* m_connectionManager; + AwayManager* m_awayManager; + DccTransferManager* m_dccTransferManager; + QStringList urlList; + KonvDCOP* dcopObject; + KonvIdentDCOP* identDCOP; + KonversationMainWindow* mainWindow; + Konversation::Sound* m_sound; + QuickConnectDialog* quickConnectDialog; + Images* m_images; + + Konversation::NotificationHandler* m_notificationHandler; + + QStringList colorList; +}; + +#endif + +// kate: space-indent on; tab-width 4; indent-width 4; mixed-indent off; replace-tabs on; +// vim: set et sw=4 ts=4 cino=l1,cs,U1: diff --git a/konversation/src/konversationmainwindow.cpp b/konversation/src/konversationmainwindow.cpp new file mode 100644 index 0000000..a85c5fd --- /dev/null +++ b/konversation/src/konversationmainwindow.cpp @@ -0,0 +1,654 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2005 Ismail Donmez + Copyright (C) 2005 Peter Simonsson + Copyright (C) 2005 John Tapsell + Copyright (C) 2005-2008 Eike Hein +*/ + +#include "konversationmainwindow.h" +#include "konversationapplication.h" +#include "linkaddressbook/addressbook.h" +#include "konvisettingsdialog.h" +#include "viewcontainer.h" +#include "konversationstatusbar.h" +#include "konvibookmarkhandler.h" +#include "trayicon.h" +#include "serverlistdialog.h" +#include "identitydialog.h" +#include "notificationhandler.h" +#include "irccharsets.h" +#include "connectionmanager.h" +#include "awaymanager.h" +#include "dcctransfermanager.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#ifdef USE_KNOTIFY +#include +#endif + + +KonversationMainWindow::KonversationMainWindow() : KMainWindow(0,"main_window", WStyle_ContextHelp | WType_TopLevel | WDestructiveClose) +{ + m_hasDirtySettings = false; + m_closeApp = false; + m_serverListDialog = 0; + m_settingsDialog = NULL; + + m_viewContainer = new ViewContainer(this); + setCentralWidget(m_viewContainer->getWidget()); + + //used for event compression. See header file for resetHasDirtySettings() + connect(KonversationApplication::instance(), SIGNAL(appearanceChanged()), this, SLOT(resetHasDirtySettings())); + connect(KonversationApplication::instance(), SIGNAL(appearanceChanged()), this, SLOT(updateTrayIcon())); + + + // Set up view container + connect(KonversationApplication::instance(), SIGNAL(appearanceChanged()), m_viewContainer, SLOT(updateAppearance())); + connect(KonversationApplication::instance(), SIGNAL(iconChanged(int)), m_viewContainer, SLOT(updateViewIcons())); + connect(KonversationApplication::instance(), SIGNAL(serverGroupsChanged(const Konversation::ServerGroupSettings*)), + m_viewContainer, SLOT(updateViews(const Konversation::ServerGroupSettings*))); + connect(m_viewContainer, SIGNAL(autoJoinToggled(const Konversation::ServerGroupSettings*)), + KonversationApplication::instance(), SIGNAL(serverGroupsChanged(const Konversation::ServerGroupSettings*))); + connect(m_viewContainer, SIGNAL(setWindowCaption(const QString&)), this, SLOT(setCaption(const QString&))); + connect(KonversationApplication::instance()->getConnectionManager(), + SIGNAL(connectionChangedState(Server*, Konversation::ConnectionState)), + m_viewContainer, SLOT(connectionStateChanged(Server*, Konversation::ConnectionState))); + connect(this, SIGNAL(triggerRememberLine()), m_viewContainer, SLOT(insertRememberLine())); + connect(this, SIGNAL(triggerRememberLines(Server*)), m_viewContainer, SLOT(insertRememberLines(Server*))); + connect(this, SIGNAL(cancelRememberLine()), m_viewContainer, SLOT(cancelRememberLine())); + connect(this, SIGNAL(insertMarkerLine()), m_viewContainer, SLOT(insertMarkerLine())); + + // Set up status bar + m_statusBar = new KonversationStatusBar(this); + connect(KonversationApplication::instance(), SIGNAL(appearanceChanged()), m_statusBar, SLOT(updateAppearance())); + + createStandardStatusBarAction(); + + connect(actionCollection(), SIGNAL(actionStatusText(const QString&)), m_statusBar, SLOT(setMainLabelTempText(const QString&))); + connect(actionCollection(), SIGNAL(clearStatusText()), m_statusBar, SLOT(clearMainLabelTempText())); + actionCollection()->setHighlightingEnabled(true); + + connect(m_viewContainer, SIGNAL(resetStatusBar()), m_statusBar, SLOT(resetStatusBar())); + connect(m_viewContainer, SIGNAL(setStatusBarTempText(const QString&)), m_statusBar, SLOT(setMainLabelTempText(const QString&))); + connect(m_viewContainer, SIGNAL(clearStatusBarTempText()), m_statusBar, SLOT(clearMainLabelTempText())); + connect(m_viewContainer, SIGNAL(setStatusBarInfoLabel(const QString&)), m_statusBar, SLOT(updateInfoLabel(const QString&))); + connect(m_viewContainer, SIGNAL(clearStatusBarInfoLabel()), m_statusBar, SLOT(clearInfoLabel())); + connect(m_viewContainer, SIGNAL(setStatusBarLagLabelShown(bool)), m_statusBar, SLOT(setLagLabelShown(bool))); + connect(m_viewContainer, SIGNAL(updateStatusBarLagLabel(Server*, int)), m_statusBar, SLOT(updateLagLabel(Server*, int))); + connect(m_viewContainer, SIGNAL(resetStatusBarLagLabel()), m_statusBar, SLOT(resetLagLabel())); + connect(m_viewContainer, SIGNAL(setStatusBarLagLabelTooLongLag(Server*, int)), m_statusBar, SLOT(setTooLongLag(Server*, int))); + connect(m_viewContainer, SIGNAL(updateStatusBarSSLLabel(Server*)), m_statusBar, SLOT(updateSSLLabel(Server*))); + connect(m_viewContainer, SIGNAL(removeStatusBarSSLLabel()), m_statusBar, SLOT(removeSSLLabel())); + + + // Actions + KStdAction::quit(this,SLOT(quitProgram()),actionCollection()); + + hideMenuBarAction = KStdAction::showMenubar(this, SLOT(toggleMenubar()), actionCollection()); + + setStandardToolBarMenuEnabled(true); + KStdAction::configureToolbars(this, SLOT(configureToolbar()), actionCollection()); + + KStdAction::keyBindings(this, SLOT(openKeyBindings()), actionCollection()); + KAction *preferencesAction = KStdAction::preferences(this, SLOT(openPrefsDialog()), actionCollection()); + +#ifdef USE_KNOTIFY // options_configure_notifications + KAction *configureNotificationsAction = KStdAction::configureNotifications(this,SLOT(openNotifications()), actionCollection()); +#endif + + KAction* action; + + (new KAction(i18n("&Server List..."), "server", KShortcut("F2"), this, SLOT(openServerList()), + actionCollection(), "open_server_list"))->setToolTip(i18n("Manage networks and servers")); + (new KAction(i18n("Quick &Connect..."), "connect_creating", KShortcut("F7"), this, SLOT(openQuickConnectDialog()), + actionCollection(), "quick_connect_dialog"))->setToolTip(i18n("Type in the address of a new IRC server to connect to")); + + action = new KAction(i18n("&Reconnect"), "connect_creating", 0, m_viewContainer, SLOT(reconnectFrontServer()), actionCollection(), "reconnect_server"); + action->setEnabled(false); + action->setToolTip(i18n("Reconnect to the current server.")); + + action = new KAction(i18n("&Disconnect"), "connect_no", 0, m_viewContainer, SLOT(disconnectFrontServer()), actionCollection(), "disconnect_server"); + action->setEnabled(false); + action->setToolTip(i18n("Disconnect from the current server.")); + + (new KAction(i18n("&Identities..."), "identity", KShortcut("F8"), this, SLOT(openIdentitiesDialog()), + actionCollection(), "identities_dialog"))->setToolTip(i18n("Manage your nick, away and other identity settings")); + + new KToggleAction(i18n("&Watched Nicks Online"), "kontact_contacts", KShortcut("F4"), m_viewContainer, SLOT(openNicksOnlinePanel()), actionCollection(), "open_nicksonline_window"); + new KToggleAction(i18n("&DCC Status"), "2rightarrow", KShortcut("F9"), m_viewContainer, SLOT(toggleDccPanel()), actionCollection(), "open_dccstatus_window"); + action = new KAction(i18n("&Open Logfile"), "history", KShortcut("Ctrl+O"), m_viewContainer, SLOT(openLogFile()), actionCollection(), "open_logfile"); + action->setEnabled(false); + action->setToolTip(i18n("Open the known history for this channel in a new tab")); + + action = new KAction(i18n("&Channel Settings..."), "edit", m_viewContainer, SLOT(openChannelSettings()), actionCollection(), "channel_settings"); + action->setEnabled(false); + action->setToolTip(i18n("Open the channel settings dialog for this tab")); + + KToggleAction* channelListAction = new KToggleAction(i18n("Channel &List"), "view_text", KShortcut("F5"), m_viewContainer, SLOT(openChannelList()), actionCollection(), "open_channel_list"); + channelListAction->setEnabled(false); + channelListAction->setToolTip(i18n("Show a list of all the known channels on this server")); + + action = new KToggleAction(i18n("&URL Catcher"), "enhanced_browsing", KShortcut("F6"), m_viewContainer, SLOT(addUrlCatcher()), actionCollection(), "open_url_catcher"); + action->setToolTip(i18n("List all URLs that have been mentioned recently in a new tab")); + + if (kapp->authorize("shell_access")) + { + action = new KAction(i18n("New &Konsole"), "openterm", 0, m_viewContainer, SLOT(addKonsolePanel()), actionCollection(), "open_konsole"); + action->setToolTip(i18n("Open a terminal in a new tab")); + } + + // Actions to navigate through the different pages + KShortcut nextShortcut = KStdAccel::tabNext(); + nextShortcut.setSeq(1, KKeySequence("Alt+Right")); + KShortcut prevShortcut = KStdAccel::tabPrev(); + prevShortcut.setSeq(1, KKeySequence("Alt+Left")); + action = new KAction(i18n("&Next Tab"), QApplication::reverseLayout() ? "previous" : "next", + QApplication::reverseLayout() ? prevShortcut : nextShortcut, + m_viewContainer, SLOT(showNextView()), actionCollection(), "next_tab"); + action->setEnabled(false); + action = new KAction(i18n("&Previous Tab"), QApplication::reverseLayout() ? "next" : "previous", + QApplication::reverseLayout() ? nextShortcut : prevShortcut, + m_viewContainer, SLOT(showPreviousView()),actionCollection(),"previous_tab"); + action->setEnabled(false); + action = new KAction(i18n("Close &Tab"),"tab_remove",KShortcut("Ctrl+w"), m_viewContainer, SLOT(closeCurrentView()),actionCollection(),"close_tab"); + action->setEnabled(false); + action = new KAction(i18n("Next Active Tab"), 0, KShortcut("Ctrl+Alt+Space"), m_viewContainer, SLOT(showNextActiveView()), + actionCollection(), "next_active_tab"); + action->setEnabled(false); + + if (Preferences::tabPlacement()==Preferences::Left) + { + action = new KAction(i18n("Move Tab Up"), "1uparrow", KShortcut("Alt+Shift+Left"), + m_viewContainer, SLOT(moveViewLeft()), actionCollection(), "move_tab_left"); + action->setEnabled(false); + action->setToolTip("Move this tab"); + action = new KAction(i18n("Move Tab Down"), "1downarrow", KShortcut("Alt+Shift+Right"), + m_viewContainer, SLOT(moveViewRight()), actionCollection(), "move_tab_right"); + action->setEnabled(false); + action->setToolTip("Move this tab"); + } + else + { + KAction* action2; + if (QApplication::reverseLayout()) + { + action2 = new KAction(i18n("Move Tab Right"), "1rightarrow", KShortcut("Alt+Shift+Right"), + m_viewContainer, SLOT(moveViewLeft()), actionCollection(), "move_tab_left"); + action = new KAction(i18n("Move Tab Left"), "1leftarrow", KShortcut("Alt+Shift+Left"), + m_viewContainer, SLOT(moveViewRight()), actionCollection(), "move_tab_right"); + } + else + { + action = new KAction(i18n("Move Tab Left"), "1leftarrow", KShortcut("Alt+Shift+Left"), + m_viewContainer, SLOT(moveViewLeft()), actionCollection(), "move_tab_left"); + action2 = new KAction(i18n("Move Tab Right"), "1rightarrow", KShortcut("Alt+Shift+Right"), + m_viewContainer, SLOT(moveViewRight()), actionCollection(), "move_tab_right"); + } + + action->setEnabled(false); + action->setToolTip("Move this tab"); + action2->setEnabled(false); + action2->setToolTip("Move this tab"); + } + + action = new KAction(i18n("Rejoin Channel"), 0, m_viewContainer, SLOT(rejoinChannel()), actionCollection(), "rejoin_channel"); + action->setEnabled(false); + + action = new KToggleAction(i18n("Enable Notifications"), 0, 0, m_viewContainer, SLOT(toggleViewNotifications()), actionCollection(), "tab_notifications"); + action->setEnabled(false); + + action = new KToggleAction(i18n("Join on Connect"), 0, 0, m_viewContainer, SLOT(toggleAutoJoin()), actionCollection(), "tab_autojoin"); + action->setEnabled(false); + + KSelectAction* selectAction = new KSelectAction(i18n("Set Encoding"), "charset", 0, actionCollection(), "tab_encoding"); + selectAction->setEditable(false); + QStringList encodingDescs = Konversation::IRCCharsets::self()->availableEncodingDescriptiveNames(); + encodingDescs.prepend(i18n("Default")); + selectAction->setItems(encodingDescs); + selectAction->setEnabled(false); + connect(selectAction, SIGNAL(activated(int)), m_viewContainer, SLOT(changeViewCharset(int))); + + QSignalMapper* tabSelectionMapper = new QSignalMapper(this); + connect(tabSelectionMapper, SIGNAL(mapped(int)), m_viewContainer, SLOT(goToView(int))); + + for (uint i = 1; i <= 10; ++i) + { + KAction* tabSelectionAction = new KAction(i18n("Go to Tab %1").arg(i), 0, KShortcut(QString("Alt+%1").arg(i%10)), + tabSelectionMapper, SLOT(map()), actionCollection(), QString("go_to_tab_%1").arg(i).local8Bit()); + tabSelectionMapper->setMapping( tabSelectionAction, i-1); + } + + action = new KAction(i18n("Clear &Marker Lines"), 0, KShortcut("CTRL+SHIFT+R"), m_viewContainer, SLOT(clearViewLines()),actionCollection(),"clear_lines"); + action->setToolTip(i18n("Clear marker lines in the current tab")); + action->setEnabled(false); + action = new KAction(i18n("&Clear Window"), 0, KShortcut("Ctrl+L"), m_viewContainer, SLOT(clearView()),actionCollection(),"clear_window"); + action->setToolTip(i18n("Clear the contents of the current tab")); + action->setEnabled(false); + action = new KAction(i18n("Clear &All Windows"),0,KShortcut("CTRL+SHIFT+L"), m_viewContainer, SLOT(clearAllViews()),actionCollection(),"clear_tabs"); + action->setToolTip(i18n("Clear the contents of all open tabs")); + action->setEnabled(false); + + KToggleAction* awayAction = new KToggleAction(i18n("Global Away"), KShortcut("Ctrl+Shift+A"), actionCollection(), "toggle_away"); + connect(awayAction, SIGNAL(toggled(bool)), static_cast(kapp)->getAwayManager(), SLOT(toggleGlobalAway(bool))); + awayAction->setEnabled(false); + + action = new KAction(i18n("&Join Channel..."), "add", KShortcut("Ctrl+J"), m_viewContainer, SLOT(showJoinChannelDialog()), actionCollection(), "join_channel"); + action->setEnabled(false); + action->setToolTip("Join a new channel on this server"); + + action = KStdAction::find(m_viewContainer, SLOT(findText()), actionCollection()); + action->setEnabled(false); + action = KStdAction::findNext(m_viewContainer, SLOT(findNextText()), actionCollection()); + action->setEnabled(false); + action = KStdAction::findPrev(m_viewContainer, SLOT(findPrevText()), actionCollection()); + action->setEnabled(false); + + action = new KAction(i18n("&IRC Color..."), "colorize", CTRL+Key_K, m_viewContainer, SLOT(insertIRCColor()), actionCollection(), "irc_colors"); + action->setToolTip(i18n("Set the color of your current IRC message")); + action->setEnabled(false); + action = new KAction(i18n("&Marker Line"), 0, KShortcut("Ctrl+R") , m_viewContainer, SLOT(insertMarkerLine()), actionCollection(), "insert_marker_line"); + action->setToolTip(i18n("Insert a horizontal line into the current tab that only you can see")); + action->setEnabled(false); + action = new KAction(i18n("Special &Character..."), "char", KShortcut("Alt+Shift+C"), m_viewContainer, SLOT(insertCharacter()), actionCollection(), "insert_character"); + action->setToolTip(i18n("Insert any character into your current IRC message")); + action->setEnabled(false); + + action = new KAction(i18n("Close &All Open Queries"), 0, KShortcut("F11"), m_viewContainer, SLOT(closeQueries()), actionCollection(), "close_queries"); + action->setEnabled(false); + + KToggleAction* toggleChannelNickListsAction = new KToggleAction(i18n("Hide Nicklist"), 0, + KShortcut("Ctrl+H"), m_viewContainer, SLOT(toggleChannelNicklists()), actionCollection(), "hide_nicknamelist"); + if (!Preferences::showNickList()) + toggleChannelNickListsAction->setChecked(true); + + // set up system tray + m_trayIcon = new Konversation::TrayIcon(this); + connect(this, SIGNAL(endNotification()), m_trayIcon, SLOT(endNotification())); + connect(KonversationApplication::instance(), SIGNAL(iconChanged(int)), m_trayIcon, SLOT(updateAppearance())); + connect(m_trayIcon, SIGNAL(quitSelected()), this, SLOT(quitProgram())); + KPopupMenu *trayMenu = m_trayIcon->contextMenu(); + #ifdef USE_KNOTIFY + configureNotificationsAction->plug(trayMenu); + #endif + preferencesAction->plug(trayMenu); + awayAction->plug(trayMenu); + + // decide whether to show the tray icon or not + updateTrayIcon(); + + createGUI(NULL, false); + + resize(700, 500); // Give the app a sane default size + setAutoSaveSettings(); + + // Apply menubar show/hide pref + hideMenuBarAction->setChecked(Preferences::showMenuBar()); + toggleMenubar(true); + + // Bookmarks + m_bookmarkHandler = new KonviBookmarkHandler(this); + + // set up KABC with a nice gui error dialog + KABC::GuiErrorHandler *m_guiErrorHandler = new KABC::GuiErrorHandler(this); + kapp->dcopClient()->setAcceptCalls( false ); + Konversation::Addressbook::self()->getAddressBook()->setErrorHandler(m_guiErrorHandler); + kapp->dcopClient()->setAcceptCalls( true ); + + if (Preferences::useNotify() && Preferences::openWatchedNicksAtStartup()) + m_viewContainer->openNicksOnlinePanel(); + +} + +KonversationMainWindow::~KonversationMainWindow() +{ + delete m_viewContainer; +} + +int KonversationMainWindow::confirmQuit() +{ + KonversationApplication* konvApp = static_cast(kapp); + + if (konvApp->getConnectionManager()->connectionCount() == 0) + return KMessageBox::Continue; + + int result = KMessageBox::Cancel; + + if (!KMessageBox::shouldBeShownContinue("systemtrayquitKonversation") + && konvApp->getDccTransferManager()->hasActiveTransfers()) + { + result = KMessageBox::warningContinueCancel( + this, + i18n("You have active DCC file transfers. Are you sure you want to quit Konversation?"), + i18n("Confirm Quit"), + i18n("Quit"), + "QuitWithActiveDccTransfers"); + } + else + { + result = KMessageBox::warningContinueCancel( + this, + i18n("Are you sure you want to quit Konversation?"), + i18n("Confirm Quit"), + i18n("Quit"), + "systemtrayquitKonversation"); + } + + return result; +} + +void KonversationMainWindow::quitProgram() +{ + if (Preferences::showTrayIcon() && + sender() != m_trayIcon && + confirmQuit() == KMessageBox::Cancel) return; + + // will call queryClose() + m_closeApp = true; + close(); +} + +bool KonversationMainWindow::queryClose() +{ + KonversationApplication* konvApp = static_cast(kapp); + + if (!konvApp->sessionSaving()) + { + if (sender() == m_trayIcon) + m_closeApp = true; + + if (Preferences::showTrayIcon() && !m_closeApp) + { + KMessageBox::information( this, + i18n("

Closing the main window will keep Konversation running in the system tray. " + "Use Quit from the Konversation menu to quit the application.

"), + i18n( "Docking in System Tray" ), "HideOnCloseInfo" ); + hide(); + + return false; + } + + if (!Preferences::showTrayIcon() && confirmQuit() == KMessageBox::Cancel) + return false; + } + + return true; +} + +void KonversationMainWindow::hideEvent(QHideEvent *e) +{ + emit triggerRememberLine(); + + m_statusBar->clearMainLabelTempText(); + + KMainWindow::hideEvent(e); +} + +void KonversationMainWindow::showEvent(QShowEvent *e) +{ + emit cancelRememberLine(); + + KMainWindow::showEvent(e); +} + +void KonversationMainWindow::leaveEvent(QEvent* e) +{ + m_statusBar->clearMainLabelTempText(); + + KMainWindow::leaveEvent(e); +} + +bool KonversationMainWindow::event(QEvent* e) +{ + if (e->type() == QEvent::WindowActivate) + { + emit endNotification(); + emit cancelRememberLine(); + } + else if(e->type() == QEvent::WindowDeactivate) + { + m_statusBar->clearMainLabelTempText(); + + if (kapp->activeModalWidget() == 0) + emit triggerRememberLine(); + } + + return KMainWindow::event(e); +} + +void KonversationMainWindow::settingsChangedSlot() +{ + // This is for compressing the events. m_hasDirtySettings is set to true + // when the settings have changed, then set to false when the app reacts to it + // via the appearanceChanged signal. This prevents a series of settingsChanged signals + // causing the app expensively rereading its settings many times. + // The appearanceChanged signal is connected to resetHasDirtySettings to reset this bool + if (!m_hasDirtySettings) + { + QTimer::singleShot(0, KonversationApplication::instance(), SIGNAL(appearanceChanged())); + m_hasDirtySettings = true; + } +} + +void KonversationMainWindow::resetHasDirtySettings() +{ + m_hasDirtySettings = false; +} + +void KonversationMainWindow::updateTrayIcon() +{ + m_trayIcon->setNotificationEnabled(Preferences::trayNotify()); + + if (Preferences::showTrayIcon()) + m_trayIcon->show(); + else + m_trayIcon->hide(); +} + +void KonversationMainWindow::toggleMenubar(bool dontShowWarning) +{ + if (hideMenuBarAction->isChecked()) + menuBar()->show(); + else + { + if (!dontShowWarning) + { + QString accel = hideMenuBarAction->shortcut().toString(); + KMessageBox::information(this, + i18n("This will hide the menu bar completely. You can show it again by typing %1.").arg(accel), + "Hide menu bar","HideMenuBarWarning"); + } + menuBar()->hide(); + } + + Preferences::setShowMenuBar(hideMenuBarAction->isChecked()); +} + +int KonversationMainWindow::configureToolbar() +{ + saveMainWindowSettings(KGlobal::config()); + KEditToolbar dlg(actionCollection(), xmlFile(), true, this); + connect(&dlg, SIGNAL(newToolbarConfig()), SLOT(saveToolbarConfig())); + return dlg.exec(); +} + +void KonversationMainWindow::saveToolbarConfig() +{ + createGUI(xmlFile(), false); + applyMainWindowSettings(KGlobal::config()); +} + +void KonversationMainWindow::focusAndShowErrorMessage(const QString &errorMsg) +{ + show(); + KWin::demandAttention(winId()); + KWin::activateWindow(winId()); + KMessageBox::error(this, errorMsg); +} + +void KonversationMainWindow::openPrefsDialog() +{ + //An instance of your dialog could be already created and could be cached, + //in which case you want to display the cached dialog instead of creating + //another one + if (!m_settingsDialog) + { + m_settingsDialog = new KonviSettingsDialog(this); + //User edited the configuration - update your local copies of the + //configuration data + connect(m_settingsDialog, SIGNAL(settingsChanged()), this, SLOT(settingsChangedSlot())); + } + m_settingsDialog->show(); +} + +void KonversationMainWindow::openKeyBindings() +{ + // Change a number of action names to make them friendlier for the shortcut list. + actionCollection()->action("tab_notifications")->setText(i18n("Toggle Notifications")); + actionCollection()->action("toggle_away")->setText(i18n("Toggle Away Globally")); + actionCollection()->action("irc_colors")->setText(i18n("Insert &IRC Color...")); + actionCollection()->action("insert_character")->setText(i18n("Insert Special &Character...")); + actionCollection()->action("insert_marker_line")->setText(i18n("Insert &Marker Line")); + QString openChannelListString = actionCollection()->action("open_channel_list")->text(); + actionCollection()->action("open_channel_list")->setText(i18n("&Channel List")); + QString openLogFileString = actionCollection()->action("open_logfile")->text(); + actionCollection()->action("open_logfile")->setText(i18n("&Open Logfile")); + + // Open shortcut configuration dialog. + KKeyDialog::configure(actionCollection()); + + // Reset action names. + actionCollection()->action("tab_notifications")->setText(i18n("Enable Notifications")); + actionCollection()->action("toggle_away")->setText(i18n("Set &Away Globally")); + actionCollection()->action("irc_colors")->setText(i18n("&IRC Color...")); + actionCollection()->action("insert_character")->setText(i18n("Special &Character...")); + actionCollection()->action("insert_marker_line")->setText(i18n("&Marker Line")); + actionCollection()->action("open_channel_list")->setText(openChannelListString); + actionCollection()->action("open_logfile")->setText(openLogFileString); +} + +void KonversationMainWindow::openServerList() +{ + if (!m_serverListDialog) + { + m_serverListDialog = new Konversation::ServerListDialog(this); + KonversationApplication* konvApp = static_cast(kapp); + + connect(m_serverListDialog, SIGNAL(serverGroupsChanged(const Konversation::ServerGroupSettings*)), + konvApp, SIGNAL(serverGroupsChanged(const Konversation::ServerGroupSettings*))); + connect(konvApp, SIGNAL(serverGroupsChanged(const Konversation::ServerGroupSettings*)), + m_serverListDialog, SLOT(updateServerList())); + connect(m_serverListDialog, SIGNAL(connectTo(Konversation::ConnectionFlag, int)), + konvApp->getConnectionManager(), SLOT(connectTo(Konversation::ConnectionFlag, int))); + connect(m_serverListDialog, SIGNAL(connectTo(Konversation::ConnectionFlag, ConnectionSettings&)), + konvApp->getConnectionManager(), SLOT(connectTo(Konversation::ConnectionFlag, ConnectionSettings&))); + connect(konvApp->getConnectionManager(), SIGNAL(closeServerList()), m_serverListDialog, SLOT(slotClose())); + } + + m_serverListDialog->show(); +} + +void KonversationMainWindow::openQuickConnectDialog() +{ + emit showQuickConnectDialog(); +} + +// open the preferences dialog and show the watched nicknames page +void KonversationMainWindow::openNotify() +{ + openPrefsDialog(); + if (m_settingsDialog) m_settingsDialog->openWatchedNicknamesPage(); +} + +void KonversationMainWindow::openIdentitiesDialog() +{ + Konversation::IdentityDialog dlg(this); + + if (dlg.exec() == KDialog::Accepted) + { + if (m_serverListDialog) + m_serverListDialog->updateServerList(); + m_viewContainer->updateViewEncoding(m_viewContainer->getFrontView()); + } +} + +IdentityPtr KonversationMainWindow::editIdentity(IdentityPtr identity) +{ + IdentityPtr newIdentity; + + Konversation::IdentityDialog dlg(this); + newIdentity = dlg.setCurrentIdentity(identity); + + if ((dlg.exec() == KDialog::Accepted) && m_serverListDialog) + { + m_serverListDialog->updateServerList(); + return newIdentity; + } + else + return 0; +} + +void KonversationMainWindow::openNotifications() +{ + #ifdef USE_KNOTIFY + (void) KNotifyDialog::configure(this); + #endif +} + +void KonversationMainWindow::notifyAction(const QString& serverName, const QString& nick) +{ + KonversationApplication* konvApp = static_cast(kapp); + Server* server = konvApp->getConnectionManager()->getServerByName(serverName); + if (server) server->notifyAction(nick); +} + +// TODO: Let an own class handle notify things +void KonversationMainWindow::setOnlineList(Server* notifyServer,const QStringList& /*list*/, bool /*changed*/) +{ + emit nicksNowOnline(notifyServer); + // FIXME if (changed && nicksOnlinePanel) newText(nicksOnlinePanel, QString::null, true); +} + +QString KonversationMainWindow::currentURL(bool passNetwork) +{ + return m_viewContainer->currentViewURL(passNetwork); +} + +QString KonversationMainWindow::currentTitle() +{ + return m_viewContainer->currentViewTitle(); +} + +#include "konversationmainwindow.moc" diff --git a/konversation/src/konversationmainwindow.h b/konversation/src/konversationmainwindow.h new file mode 100644 index 0000000..5781e9f --- /dev/null +++ b/konversation/src/konversationmainwindow.h @@ -0,0 +1,148 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2005 Ismail Donmez + Copyright (C) 2005 Peter Simonsson + Copyright (C) 2005 John Tapsell + Copyright (C) 2005-2008 Eike Hein +*/ + +#ifndef _KONVERSATIONMAINWINDOW_H_ +#define _KONVERSATIONMAINWINDOW_H_ + +#include "channel.h" +#include "preferences.h" +#include "ssllabel.h" +#include "nickinfo.h" +#include "server.h" + +#include + +#include +#include + + +class KToggleAction; +class KScriptManager; + +class KonviBookmarkHandler; +class Ignore; +class NicksOnline; +class QuickButtonsDialog; +class KonviSettingsDialog; +class ViewContainer; +class KonversationStatusBar; + +namespace Konversation +{ + class ServerListDialog; + class TrayIcon; +} + +class KonversationMainWindow : public KMainWindow +{ + Q_OBJECT + + public: + KonversationMainWindow(); + ~KonversationMainWindow(); + + ViewContainer* getViewContainer() { return m_viewContainer; } + Konversation::TrayIcon* systemTrayIcon() const { return m_trayIcon; } + + /** Some errors need to be shown, even when konversation is minimized. + * For example, when a kimiface call is received to query a person, + * (e.g. the user choses "Chat with X" in kmail) but that person isn't + * recognised, we need to give immediate feedback to the user. + */ + void focusAndShowErrorMessage(const QString &errorMsg); + + QString currentURL(bool passNetwork); + QString currentTitle(); + + signals: + void startNotifyTimer(int msec); + void showQuickConnectDialog(); + void nicksNowOnline(Server*); + void endNotification(); + void serverStateChanged(Server* server, Konversation::ConnectionState state); + void triggerRememberLine(); + void triggerRememberLines(Server*); + void cancelRememberLine(); + void insertMarkerLine(); + + public slots: + void updateTrayIcon(); + + void openServerList(); + + void openIdentitiesDialog(); + IdentityPtr editIdentity(IdentityPtr identity); + + void setOnlineList(Server* notifyServer,const QStringList& list, bool changed); + + protected slots: + /** This is connected to the preferences settingsChanged signal and acts to compress + * multiple successively settingsChanged() signals into a single output + * appearanceChanged() signal. + * + * Do not connect to the settingsChanged signal elsewhere. If you want to know when + * the settings have changed, connect to: + * KonversationApplication::instance(), SIGNAL(appearanceChanged()) + */ + void settingsChangedSlot(); + + /** This is connected to the appearanceChanged signal. + * @see settingsChangedSlot() + */ + void resetHasDirtySettings(); + + void toggleMenubar(bool dontShowWarning = false); + + int configureToolbar(); + void saveToolbarConfig(); + + void openPrefsDialog(); + void openKeyBindings(); + void openQuickConnectDialog(); + + void openNotify(); + // it seems that moc does not honor #ifs in compile so we create an + // empty slot in our .cpp file rather than #if this slot out + void openNotifications(); + void notifyAction(const QString& serverName,const QString& nick); + + void quitProgram(); + void showEvent(QShowEvent* e); + void hideEvent(QHideEvent* e); + void leaveEvent(QEvent* e); + + + protected: + int confirmQuit(); + bool queryClose(); + virtual bool event(QEvent* e); + + ViewContainer* m_viewContainer; + KonversationStatusBar* m_statusBar; + Konversation::TrayIcon* m_trayIcon; + + KToggleAction* hideMenuBarAction; + + KPopupMenu* m_bookmarks; + KonviBookmarkHandler* m_bookmarkHandler; + KonviSettingsDialog *m_settingsDialog; + Konversation::ServerListDialog* m_serverListDialog; + + /** @see settingsChangedSlot() */ + bool m_hasDirtySettings; + bool m_closeApp; +}; + +#endif diff --git a/konversation/src/konversationsound.cpp b/konversation/src/konversationsound.cpp new file mode 100644 index 0000000..7eb6466 --- /dev/null +++ b/konversation/src/konversationsound.cpp @@ -0,0 +1,41 @@ +/* + 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. +*/ + +/* + begin: Thu Jan 29 2004 + copyright: (C) 2004 by Peter Simonsson + email: psn@linux.se +*/ + +#include "konversationsound.h" + +#include +#include + +#ifdef USE_KNOTIFY +#include +#endif + + +namespace Konversation +{ + Sound::Sound(QObject* parent, const char* name) + : QObject(parent, name) + {} + + Sound::~Sound() + {} + + void Sound::play(const KURL& url) + { + #ifdef USE_KNOTIFY + KNotifyClient::userEvent(0,QString(),1,1,url.path()); + #endif + } +} + +#include "konversationsound.moc" diff --git a/konversation/src/konversationsound.h b/konversation/src/konversationsound.h new file mode 100644 index 0000000..145b75b --- /dev/null +++ b/konversation/src/konversationsound.h @@ -0,0 +1,41 @@ +/* + 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. +*/ + +/* + begin: Thu Jan 29 2004 + copyright: (C) 2004 by Peter Simonsson + email: psn@linux.se +*/ + +#ifndef KONVERSATIONKONVERSATIONSOUND_H +#define KONVERSATIONKONVERSATIONSOUND_H + +#include + + +class KURL; + +namespace Konversation +{ + + /** + Class that handles sounds + */ + class Sound : public QObject + { + Q_OBJECT + + public: + explicit Sound(QObject *parent = 0, const char *name = 0); + ~Sound(); + + public slots: + void play(const KURL& url); + + }; +} +#endif diff --git a/konversation/src/konversationstatusbar.cpp b/konversation/src/konversationstatusbar.cpp new file mode 100644 index 0000000..db29a06 --- /dev/null +++ b/konversation/src/konversationstatusbar.cpp @@ -0,0 +1,242 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Eike Hein +*/ + +#include "konversationstatusbar.h" +#include "konversationmainwindow.h" +#include "viewcontainer.h" +#include "ssllabel.h" + +#include +#include +#include + +#include +#include +#include +#include + + +KonversationStatusBar::KonversationStatusBar(KonversationMainWindow* window) +{ + m_window = window; + + // Initialize status bar. + m_window->statusBar(); + + m_mainLabel = new KSqueezedTextLabel(m_window->statusBar(),"mainLabel"); + setMainLabelText(i18n("Ready.")); + m_mainLabel->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); + m_mainLabel->setMinimumWidth(0); + + // KSqueezedLabel calculates the wrong height. Popular workaround. + int height = m_window->fontMetrics().height()+2; + m_mainLabel->setFixedHeight(height); + + m_infoLabel = new QLabel(m_window->statusBar(), "infoLabel"); + m_infoLabel->hide(); + QWhatsThis::add(m_infoLabel, i18n("This shows the number of users in the channel, and the number of those that are operators (ops).

A channel operator is a user that has special privileges, such as the ability to kick and ban users, change the channel modes, make other users operators")); + + m_lagLabel = new QLabel(i18n("Lag: Unknown"), m_window->statusBar(), "lagLabel"); + m_lagLabel->hide(); + + m_sslLabel = new SSLLabel(m_window->statusBar(),"sslLabel"); + m_sslLabel->setPixmap(SmallIcon("encrypted")); + m_sslLabel->hide(); + QWhatsThis::add(m_sslLabel, i18n("All communication with the server is encrypted. This makes it harder for someone to listen in on your communications.")); + + m_window->statusBar()->addWidget(m_mainLabel, 1, false); + m_window->statusBar()->addWidget(m_infoLabel, 0, true); + m_window->statusBar()->addWidget(m_lagLabel, 0, true); + m_window->statusBar()->addWidget(m_sslLabel, 0, true); + + QWhatsThis::add(m_window->statusBar(), i18n("The status bar shows various messages, including any problems connecting to the server. On the far right the current delay to the server is shown. The delay is the time it takes for messages from you to reach the server, and from the server back to you.")); +} + +KonversationStatusBar::~KonversationStatusBar() +{ +} + +void KonversationStatusBar::updateAppearance() +{ + // KSqueezedLabel calculates the wrong height. Popular workaround. + int height = m_window->fontMetrics().height()+2; + m_mainLabel->setFixedHeight(height); +} + +void KonversationStatusBar::resetStatusBar() +{ + setMainLabelText(i18n("Ready.")); + setInfoLabelShown(false); + setLagLabelShown(false); + clearInfoLabel(); + resetLagLabel(); +} + +void KonversationStatusBar::setMainLabelText(const QString& text) +{ + m_oldMainLabelText = text; + + // Don't overwrite the temp text if there is any. + if (m_tempMainLabelText.isEmpty()) + m_mainLabel->setText(text); +} + +void KonversationStatusBar::setMainLabelTempText(const QString& text) +{ + if (!text.isEmpty()) + { + m_tempMainLabelText = text; + m_mainLabel->setText(text); + } + else + clearMainLabelTempText(); +} + +void KonversationStatusBar::clearMainLabelTempText() +{ + // Unset the temp text so the next setMainLabelText won't fail. + m_tempMainLabelText = QString(); + + m_mainLabel->setText(m_oldMainLabelText); +} + +void KonversationStatusBar::setInfoLabelShown(bool shown) +{ + if (shown) + m_infoLabel->show(); + else + m_infoLabel->hide(); +} + +void KonversationStatusBar::updateInfoLabel(const QString& text) +{ + QString formatted = Konversation::removeIrcMarkup(text); + m_infoLabel->setText(formatted); + + if (m_infoLabel->isHidden()) m_infoLabel->show(); +} + +void KonversationStatusBar::clearInfoLabel() +{ + m_infoLabel->setText(QString()); +} + +void KonversationStatusBar::setLagLabelShown(bool shown) +{ + if (shown) + m_lagLabel->show(); + else + m_lagLabel->hide(); +} + +void KonversationStatusBar::updateLagLabel(Server* lagServer, int msec) +{ + if (lagServer==m_window->getViewContainer()->getFrontServer()) + { + setMainLabelText(i18n("Ready.")); + + QString lagString = lagServer->getServerName() + " - "; + + if (msec == -1) + lagString += i18n("Lag: Unknown"); + else if (msec < 1000) + lagString += i18n("Lag: %1 ms").arg(msec); + else + lagString += i18n("Lag: %1 s").arg(msec / 1000); + + m_lagLabel->setText(lagString); + + if (m_lagLabel->isHidden()) m_lagLabel->show(); + } +} + +void KonversationStatusBar::resetLagLabel() +{ + m_lagLabel->setText(i18n("Lag: Unknown")); +} + +void KonversationStatusBar::setTooLongLag(Server* lagServer, int msec) +{ + if ((msec % 5000)==0) + { + int seconds = msec/1000; + int minutes = seconds/60; + int hours = minutes/60; + int days = hours/24; + QString lagString; + + if (days) + { + const QString daysString = i18n("1 day", "%n days", days); + const QString hoursString = i18n("1 hour", "%n hours", (hours % 24)); + const QString minutesString = i18n("1 minute", "%n minutes", (minutes % 60)); + const QString secondsString = i18n("1 second", "%n seconds", (seconds % 60)); + lagString = i18n("%1 = name of server, %2 = (x days), %3 = (x hours), %4 = (x minutes), %5 = (x seconds)", "No answer from server %1 for more than %2, %3, %4, and %5.").arg(lagServer->getServerName()) + .arg(daysString).arg(hoursString).arg(minutesString).arg(secondsString); + // or longer than an hour + } + else if (hours) + { + const QString hoursString = i18n("1 hour", "%n hours", hours); + const QString minutesString = i18n("1 minute", "%n minutes", (minutes % 60)); + const QString secondsString = i18n("1 second", "%n seconds", (seconds % 60)); + lagString = i18n("%1 = name of server, %2 = (x hours), %3 = (x minutes), %4 = (x seconds)", "No answer from server %1 for more than %2, %3, and %4.").arg(lagServer->getServerName()) + .arg(hoursString).arg(minutesString).arg(secondsString); + // or longer than a minute + } + else if (minutes) + { + const QString minutesString = i18n("1 minute", "%n minutes", minutes); + const QString secondsString = i18n("1 second", "%n seconds", (seconds % 60)); + lagString = i18n("%1 = name of server, %2 = (x minutes), %3 = (x seconds)", "No answer from server %1 for more than %2 and %3.").arg(lagServer->getServerName()) + .arg(minutesString).arg(secondsString); + // or just some seconds + } + else + { + lagString = i18n("No answer from server %1 for more than 1 second.", "No answer from server %1 for more than %n seconds.", seconds).arg(lagServer->getServerName()); + } + + setMainLabelText(lagString); + } + + if (lagServer==m_window->getViewContainer()->getFrontServer()) + { + QString lagString = lagServer->getServerName() + " - "; + lagString.append(i18n("Lag: %1 s").arg(msec/1000)); + + if (m_lagLabel->isHidden()) m_lagLabel->show(); + m_lagLabel->setText(lagString); + } +} + +void KonversationStatusBar::updateSSLLabel(Server* server) +{ + if (server == m_window->getViewContainer()->getFrontServer() + && server->getUseSSL() && server->isConnected()) + { + disconnect(m_sslLabel,0,0,0); + connect(m_sslLabel,SIGNAL(clicked()),server,SLOT(showSSLDialog())); + QToolTip::remove(m_sslLabel); + QToolTip::add(m_sslLabel,server->getSSLInfo()); + m_sslLabel->show(); + } + else + m_sslLabel->hide(); +} + +void KonversationStatusBar::removeSSLLabel() +{ + disconnect(m_sslLabel,0,0,0); + m_sslLabel->hide(); +} + +#include "konversationstatusbar.moc" diff --git a/konversation/src/konversationstatusbar.h b/konversation/src/konversationstatusbar.h new file mode 100644 index 0000000..931f7d6 --- /dev/null +++ b/konversation/src/konversationstatusbar.h @@ -0,0 +1,67 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Eike Hein +*/ + +#ifndef KONVERSATIONSTATUSBAR_H +#define KONVERSATIONSTATUSBAR_H + +#include + + +class QLabel; + +class KonversationMainWindow; +class KSqueezedTextLabel; +class SSLLabel; +class Server; + +class KonversationStatusBar : public QObject +{ + Q_OBJECT + + public: + explicit KonversationStatusBar(KonversationMainWindow* parent); + ~KonversationStatusBar(); + + public slots: + void updateAppearance(); + + void resetStatusBar(); + + void setMainLabelText(const QString& text); + + void setMainLabelTempText(const QString& text); + void clearMainLabelTempText(); + + void setInfoLabelShown(bool shown); + void updateInfoLabel(const QString& text); + void clearInfoLabel(); + + void setLagLabelShown(bool shown); + void updateLagLabel(Server* lagServer, int msec); + void resetLagLabel(); + void setTooLongLag(Server* lagServer, int msec); + + void updateSSLLabel(Server* server); + void removeSSLLabel(); + + private: + KonversationMainWindow* m_window; + + KSqueezedTextLabel* m_mainLabel; + QLabel* m_infoLabel; + QLabel* m_lagLabel; + SSLLabel* m_sslLabel; + + QString m_oldMainLabelText; + QString m_tempMainLabelText; +}; + +#endif diff --git a/konversation/src/konversationui.rc b/konversation/src/konversationui.rc new file mode 100644 index 0000000..66d3945 --- /dev/null +++ b/konversation/src/konversationui.rc @@ -0,0 +1,82 @@ + + + + +

+ + + + + + + + + + + + + + + + + + &Insert + + + + + + &Bookmarks + + + + + + + + &Window + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/konversation/src/konvibookmarkhandler.cpp b/konversation/src/konvibookmarkhandler.cpp new file mode 100644 index 0000000..3258cba --- /dev/null +++ b/konversation/src/konvibookmarkhandler.cpp @@ -0,0 +1,96 @@ +/* + Copyright (c) 2005 by İsmail Dönmez + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* + +Based on the code by: +Copyright (C) 2002 Carsten Pfeiffer + +*/ + +#include "konvibookmarkhandler.h" +#include "konversationapplication.h" +#include "konversationmainwindow.h" +#include "connectionmanager.h" +#include "konvibookmarkmenu.h" + +#include + +#include +#include + + +KonviBookmarkHandler::KonviBookmarkHandler(KonversationMainWindow* mainWindow) +: QObject( mainWindow, "KonviBookmarkHandler" ), +KBookmarkOwner(), +m_mainWindow(mainWindow) +{ + m_menu = static_cast(mainWindow->factory()->container("bookmarks", mainWindow)); + + m_file = locate( "data", "konversation/bookmarks.xml" ); + + if ( m_file.isEmpty() ) + m_file = locateLocal( "data", "konversation/bookmarks.xml" ); + + if(!m_menu) + { + m_bookmarkMenu = 0; + return; + } + + KBookmarkManager *manager = KBookmarkManager::managerForFile( m_file, false); + manager->setEditorOptions(kapp->caption(), false); + manager->setUpdate( true ); + manager->setShowNSBookmarks( false ); + + connect( manager, SIGNAL(changed(const QString &,const QString &)), SLOT(slotBookmarksChanged(const QString &,const QString &))); + + m_bookmarkMenu = new KonviBookmarkMenu( manager, this, m_menu, NULL, true ); +} + +KonviBookmarkHandler::~KonviBookmarkHandler() +{ + delete m_bookmarkMenu; +} + +void KonviBookmarkHandler::slotEditBookmarks() +{ + KProcess proc; + proc << QString::fromLatin1("keditbookmarks"); + proc << "--nobrowser"; + proc << "--caption" << i18n("Konversation Bookmarks Editor"); + proc << m_file; + proc.start(KProcess::DontCare); +} + +void KonviBookmarkHandler::slotBookmarksChanged( const QString &, +const QString &) +{ + // This is called when someone changes bookmarks in konversation + m_bookmarkMenu->slotBookmarksChanged(""); +} + +void KonviBookmarkHandler::openBookmarkURL(const QString& url, const QString& /* title */) +{ + KonversationApplication* konvApp = static_cast(kapp); + konvApp->getConnectionManager()->connectTo(Konversation::SilentlyReuseConnection, url); +} + +QString KonviBookmarkHandler::currentURL() const +{ + return m_mainWindow->currentURL(true); +} + +QString KonviBookmarkHandler::currentTitle() const +{ + return m_mainWindow->currentTitle(); +} + +#include "konvibookmarkhandler.moc" diff --git a/konversation/src/konvibookmarkhandler.h b/konversation/src/konvibookmarkhandler.h new file mode 100644 index 0000000..0071195 --- /dev/null +++ b/konversation/src/konvibookmarkhandler.h @@ -0,0 +1,55 @@ +#ifndef KONVIBOOKMARKHANDLER_H +#define KONVIBOOKMARKHANDLER_H + +/* + Copyright (c) 2005 by İsmail Dönmez + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* + +Based on the code by : +Copyright (C) 2002 Carsten Pfeiffer + +*/ + +#include + + +class QString; +class KPopupMenu; +class KonversationMainWindow; +class KonviBookmarkMenu; + +class KonviBookmarkHandler : public QObject, public KBookmarkOwner +{ + Q_OBJECT + + public: + explicit KonviBookmarkHandler(KonversationMainWindow *mainWindow); + ~KonviBookmarkHandler(); + + KPopupMenu* popupMenu(); + + // KBookmarkOwner interface: + virtual void openBookmarkURL(const QString& url, const QString& title); + virtual QString currentURL() const; + virtual QString currentTitle() const; + + private slots: + void slotBookmarksChanged(const QString &, const QString & caller); + void slotEditBookmarks(); + + + private: + KonversationMainWindow* m_mainWindow; + KPopupMenu *m_menu; + KonviBookmarkMenu *m_bookmarkMenu; + QString m_file; +}; +#endif // KONVIBOOKMARKHANDLER_H diff --git a/konversation/src/konvibookmarkmenu.cpp b/konversation/src/konvibookmarkmenu.cpp new file mode 100644 index 0000000..4474f6a --- /dev/null +++ b/konversation/src/konvibookmarkmenu.cpp @@ -0,0 +1,154 @@ +/* + Copyright (c) 2005 by İsmail Dönmez + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* + +Based on the code by: +Copyright (C) 2002 Carsten Pfeiffer + +*/ + +#include "konvibookmarkmenu.h" +#include "konvibookmarkhandler.h" + +#include + +#include +#include + + +KonviBookmarkMenu::KonviBookmarkMenu( KBookmarkManager* mgr, +KonviBookmarkHandler * _owner, KPopupMenu * _parentMenu, +KActionCollection *collec, bool _isRoot, bool _add, +const QString & parentAddress ) +: KBookmarkMenu( mgr, _owner, _parentMenu, collec, _isRoot, _add, parentAddress), +m_kOwner(_owner) +{ + /* + * First, we disconnect KBookmarkMenu::slotAboutToShow() + * Then, we connect KonviBookmarkMenu::slotAboutToShow(). + * They are named differently because the SLOT() macro thinks we want + * KonviBookmarkMenu::KBookmarkMenu::slotAboutToShow() + * Could this be solved if slotAboutToShow() is virtual in KBookmarMenu? + */ + disconnect(_parentMenu, SIGNAL(aboutToShow()), this, SLOT(slotAboutToShow())); + connect(_parentMenu, SIGNAL(aboutToShow()), SLOT(slotAboutToShow2())); +} + +/* + * Duplicate this exactly because KBookmarkMenu::slotBookmarkSelected can't + * be overrided. I would have preferred to NOT have to do this. + * + * Why did I do this? + * - when KBookmarkMenu::fillbBookmarkMenu() creates sub-KBookmarkMenus. + * - when ... adds KActions, it uses KBookmarkMenu::slotBookmarkSelected() + * instead of KonviBookmarkMenu::slotBookmarkSelected(). + */ +void KonviBookmarkMenu::slotAboutToShow2() +{ + // Did the bookmarks change since the last time we showed them ? + if ( m_bDirty ) + { + m_bDirty = false; + refill(); + } +} + +void KonviBookmarkMenu::refill() +{ + m_lstSubMenus.clear(); + QPtrListIterator it( m_actions ); + for (; it.current(); ++it ) + it.current()->unplug( m_parentMenu ); + m_parentMenu->clear(); + m_actions.clear(); + fillBookmarkMenu(); + m_parentMenu->adjustSize(); +} + +void KonviBookmarkMenu::fillBookmarkMenu() +{ + if ( m_bIsRoot ) + { + if ( m_bAddBookmark ) + addAddBookmark(); + + addEditBookmarks(); + + if ( m_bAddBookmark ) + addNewFolder(); + } + + KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup(); + Q_ASSERT(!parentBookmark.isNull()); + bool separatorInserted = false; + for ( KBookmark bm = parentBookmark.first(); !bm.isNull(); + bm = parentBookmark.next(bm) ) + { + QString text = bm.text(); + text.replace( '&', "&&" ); + if ( !separatorInserted && m_bIsRoot) // inserted before the first konq bookmark, to avoid the separator if no konq bookmark + { + m_parentMenu->insertSeparator(); + separatorInserted = true; + } + if ( !bm.isGroup() ) + { + if ( bm.isSeparator() ) + { + m_parentMenu->insertSeparator(); + } + else + { + // kdDebug(1203) << "Creating URL bookmark menu item for " << bm.text() << endl; + // create a normal URL item, with ID as a name + KAction * action = new KAction( text, bm.icon(), 0, + this, SLOT( slotBookmarkSelected() ), + m_actionCollection, bm.url().url().utf8() ); + + action->setStatusText( bm.url().prettyURL() ); + + action->plug( m_parentMenu ); + m_actions.append( action ); + } + } + else + { + // kdDebug(1203) << "Creating bookmark submenu named " << bm.text() << endl; + KActionMenu * actionMenu = new KActionMenu( text, bm.icon(), + m_actionCollection, 0L ); + actionMenu->plug( m_parentMenu ); + m_actions.append( actionMenu ); + KonviBookmarkMenu *subMenu = new KonviBookmarkMenu( m_pManager, + m_kOwner, actionMenu->popupMenu(), + m_actionCollection, false, + m_bAddBookmark, bm.address() ); + m_lstSubMenus.append( subMenu ); + } + } + + if ( !m_bIsRoot && m_bAddBookmark ) + { + if ( m_parentMenu->count() > 0 ) + m_parentMenu->insertSeparator(); + addAddBookmark(); + addNewFolder(); + } +} + +void KonviBookmarkMenu::slotBookmarkSelected() +{ + if ( !m_pOwner ) return; // this view doesn't handle bookmarks... + /* URL */ + m_kOwner->openBookmarkURL( QString::fromUtf8(sender()->name()), + ( (KAction *)sender() )->text() /* Title */ ); +} + +#include "konvibookmarkmenu.moc" diff --git a/konversation/src/konvibookmarkmenu.h b/konversation/src/konvibookmarkmenu.h new file mode 100644 index 0000000..f7921c2 --- /dev/null +++ b/konversation/src/konvibookmarkmenu.h @@ -0,0 +1,65 @@ +#ifndef KONVIBOOKMARKMENU_H +#define KONVIBOOKMARKMENU_H + +/* + Copyright (c) 2005 by İsmail Dönmez + + ************************************************************************* + * * + * 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. * + * * + ************************************************************************* + +Based on the code by: +Copyright (C) 2002 Carsten Pfeiffer + +*/ + +#include + +#include + + +class QString; +class KBookmark; +class KAction; +class KActionMenu; +class KActionCollection; +class KBookmarkOwner; +class KBookmarkMenu; +class KPopupMenu; +class KonviBookmarkHandler; +class KonviBookmarkMenu; +class KonviBookmarkMenuPrivate; + +class KonviBookmarkMenu : public KBookmarkMenu +{ + Q_OBJECT + + public: + KonviBookmarkMenu( KBookmarkManager* mgr, + KonviBookmarkHandler * _owner, KPopupMenu * _parentMenu, + KActionCollection *collec, bool _isRoot, + bool _add = true, const QString & parentAddress = ""); + + void fillBookmarkMenu(); + + public slots: + + private: + + protected slots: + void slotAboutToShow2(); + void slotBookmarkSelected(); + + protected: + void refill(); + + private: + KonviBookmarkHandler * m_kOwner; + KonviBookmarkMenuPrivate *d; +}; +#endif // KONVIBOOKMARKMENU_H diff --git a/konversation/src/konviconfigdialog.cpp b/konversation/src/konviconfigdialog.cpp new file mode 100644 index 0000000..386236d --- /dev/null +++ b/konversation/src/konviconfigdialog.cpp @@ -0,0 +1,284 @@ +/* + * This file is part of the KDE libraries + * Copyright (C) 2003 Benjamin C Meyer (ben+kdelibs at meyerhome dot net) + * Copyright (C) 2003 Waldo Bastian + * Copyright (C) 2004 Michael Brade + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* + * KConfigDialog derivative allowing for a multi-level hierarchical TreeList. + * Differences from KConfigDialog: + * - Use QStringList instead of QString for the item name(s) in addPage and + * addPageInternal, thus calling the respective KDialogBase methods which + * allow specifying a path from which the TreeList hierarchy is constructed. + * - Use 16x16 icons in the TreeList. + * - Fill a new int m_lastAddedIndex with the pageIndex() of a new page added + * with addPageInternal, and offer a public interface int lastAddedIndex(). + * See the KConfigDialog reference for detailed documentation. + * + * begin: Nov 22 2005 + * copyright: (C) 2005-2006 by Eike Hein, KConfigDialog developers + * email: hein@kde.org + */ + +#include "konviconfigdialog.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + + +QAsciiDict KonviConfigDialog::openDialogs; + +// This class is here purly so we don't break binary compatibility down the road. +class KonviConfigDialog::KConfigDialogPrivate +{ + public: + KConfigDialogPrivate(KDialogBase::DialogType t) : shown(false), type(t), manager(0) { } + + bool shown; + KDialogBase::DialogType type; + KConfigDialogManager *manager; + QMap managerForPage; +}; + +KonviConfigDialog::KonviConfigDialog( QWidget *parent, const char *name, + KConfigSkeleton *config, + DialogType dialogType, + int dialogButtons, + ButtonCode defaultButton, + bool modal ) : + KDialogBase( dialogType, Qt::WStyle_DialogBorder, + parent, name, modal, i18n("Configure"), dialogButtons, defaultButton ), + d(new KConfigDialogPrivate(dialogType)) +{ + if ( name ) + { + openDialogs.insert(name, this); + } + else + { + QCString genericName; + genericName.sprintf("SettingsDialog-%p", this); + openDialogs.insert(genericName, this); + setName(genericName); + } + + connect(this, SIGNAL(okClicked()), this, SLOT(updateSettings())); + connect(this, SIGNAL(applyClicked()), this, SLOT(updateSettings())); + connect(this, SIGNAL(applyClicked()), this, SLOT(updateButtons())); + connect(this, SIGNAL(defaultClicked()), this, SLOT(updateWidgetsDefault())); + connect(this, SIGNAL(defaultClicked()), this, SLOT(updateButtons())); + + d->manager = new KConfigDialogManager(this, config); + setupManagerConnections(d->manager); + + enableButton(Apply, false); +} + +KonviConfigDialog::~KonviConfigDialog() +{ + openDialogs.remove(name()); + delete d; +} + +void KonviConfigDialog::addPage(QWidget *page, + const QStringList &items, + const QString &pixmapName, + const QString &header, + bool manage) +{ + addPageInternal(page, items, pixmapName, header); + if(manage) + d->manager->addWidget(page); +} + +void KonviConfigDialog::addPage(QWidget *page, + KConfigSkeleton *config, + const QStringList &items, + const QString &pixmapName, + const QString &header) +{ + addPageInternal(page, items, pixmapName, header); + d->managerForPage[page] = new KConfigDialogManager(page, config); + setupManagerConnections(d->managerForPage[page]); +} + +void KonviConfigDialog::addPageInternal(QWidget *page, + const QStringList &items, + const QString &pixmapName, + const QString &header) +{ + if(d->shown) + { + kdDebug(240) << "KonviConfigDialog::addPage: can not add a page after the dialog has been shown."; + return; + } + switch(d->type) + { + case TreeList: + case IconList: + case Tabbed: + { + QVBox *frame = addVBoxPage(items, header, SmallIcon(pixmapName, 16)); + frame->setSpacing( 0 ); + frame->setMargin( 0 ); + page->reparent(((QWidget*)frame), 0, QPoint()); + m_lastAddedIndex = pageIndex(frame); + } + break; + + case Swallow: + { + page->reparent(this, 0, QPoint()); + setMainWidget(page); + } + break; + + case Plain: + { + QFrame *main = plainPage(); + QVBoxLayout *topLayout = new QVBoxLayout( main, 0, 0 ); + page->reparent(((QWidget*)main), 0, QPoint()); + topLayout->addWidget( page ); + } + break; + + default: + kdDebug(240) << "KonviConfigDialog::addpage: unknown type."; + } +} + +void KonviConfigDialog::setupManagerConnections(KConfigDialogManager *manager) +{ + connect(manager, SIGNAL(settingsChanged()), this, SLOT(settingsChangedSlot())); + connect(manager, SIGNAL(widgetModified()), this, SLOT(updateButtons())); + + connect(this, SIGNAL(okClicked()), manager, SLOT(updateSettings())); + connect(this, SIGNAL(applyClicked()), manager, SLOT(updateSettings())); + connect(this, SIGNAL(defaultClicked()), manager, SLOT(updateWidgetsDefault())); +} + +KonviConfigDialog* KonviConfigDialog::exists(const char* name) +{ + return openDialogs.find(name); +} + +bool KonviConfigDialog::showDialog(const char* name) +{ + KonviConfigDialog *dialog = exists(name); + if(dialog) + dialog->show(); + return (dialog != NULL); +} + +void KonviConfigDialog::updateButtons() +{ + static bool only_once = false; + if (only_once) return; + only_once = true; + + QMap::iterator it; + + bool has_changed = d->manager->hasChanged() || hasChanged(); + for (it = d->managerForPage.begin(); + it != d->managerForPage.end() && !has_changed; + ++it) + { + has_changed |= (*it)->hasChanged(); + } + + enableButton(Apply, has_changed); + + bool is_default = d->manager->isDefault() && isDefault(); + for (it = d->managerForPage.begin(); + it != d->managerForPage.end() && is_default; + ++it) + { + is_default &= (*it)->isDefault(); + } + + enableButton(Default, !is_default); + + emit widgetModified(); + only_once = false; +} + +void KonviConfigDialog::settingsChangedSlot() +{ + // Update the buttons + updateButtons(); + emit settingsChanged(); + emit settingsChanged(name()); +} + +void KonviConfigDialog::show() +{ + QMap::iterator it; + + updateWidgets(); + d->manager->updateWidgets(); + for (it = d->managerForPage.begin(); it != d->managerForPage.end(); ++it) + (*it)->updateWidgets(); + + bool has_changed = d->manager->hasChanged() || hasChanged(); + for (it = d->managerForPage.begin(); + it != d->managerForPage.end() && !has_changed; + ++it) + { + has_changed |= (*it)->hasChanged(); + } + + enableButton(Apply, has_changed); + + bool is_default = d->manager->isDefault() && isDefault(); + for (it = d->managerForPage.begin(); + it != d->managerForPage.end() && is_default; + ++it) + { + is_default &= (*it)->isDefault(); + } + + enableButton(Default, !is_default); + d->shown = true; + KDialogBase::show(); +} + +int KonviConfigDialog::lastAddedIndex() +{ + return m_lastAddedIndex; +} + +void KonviConfigDialog::updateSettings() +{ +} + +void KonviConfigDialog::updateWidgets() +{ +} + +void KonviConfigDialog::updateWidgetsDefault() +{ +} + diff --git a/konversation/src/konviconfigdialog.h b/konversation/src/konviconfigdialog.h new file mode 100644 index 0000000..b53262b --- /dev/null +++ b/konversation/src/konviconfigdialog.h @@ -0,0 +1,124 @@ +/* + * This file is part of the KDE libraries + * Copyright (C) 2003 Benjamin C Meyer (ben+kdelibs at meyerhome dot net) + * Copyright (C) 2003 Waldo Bastian + * Copyright (C) 2004 Michael Brade + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* + * KConfigDialog derivative allowing for a multi-level hierarchical TreeList. + * Differences from KConfigDialog: + * - Use QStringList instead of QString for the item name(s) in addPage and + * addPageInternal, thus calling the respective KDialogBase methods which + * allow specifying a path from which the TreeList hierarchy is constructed. + * - Use 16x16 icons in the TreeList. + * - Fill a new int m_lastAddedIndex with the pageIndex() of a new page added + * with addPageInternal, and offer a public interface int lastAddedIndex(). + * See the KConfigDialog reference for detailed documentation. + * + * begin: Nov 22 2005 + * copyright: (C) 2005-2006 by Eike Hein, KConfigDialog developers + * email: hein@kde.org + */ + +#ifndef KONVICONFIGDIALOG_H +#define KONVICONFIGDIALOG_H + +#include + +#include + + +class KConfig; +class KConfigSkeleton; +class KConfigDialogManager; + +class KonviConfigDialog : public KDialogBase +{ + Q_OBJECT + + signals: + void widgetModified(); + + void settingsChanged(); + + void settingsChanged(const char *dialogName); + + void sigUpdateWidgets(); + + public: + KonviConfigDialog( QWidget *parent, const char *name, + KConfigSkeleton *config, + DialogType dialogType = IconList, + int dialogButtons = Default|Ok|Apply|Cancel|Help, + ButtonCode defaultButton = Ok, + bool modal=false ); + + ~KonviConfigDialog(); + + void addPage( QWidget *page, const QStringList &items, + const QString &pixmapName, + const QString &header=QString(), + bool manage=true ); + + void addPage( QWidget *page, KConfigSkeleton *config, + const QStringList &items, + const QString &pixmapName, + const QString &header=QString() ); + + static KonviConfigDialog* exists( const char* name ); + + static bool showDialog( const char* name ); + + virtual void show(); + + int lastAddedIndex(); + + protected slots: + virtual void updateSettings(); + + virtual void updateWidgets(); + + virtual void updateWidgetsDefault(); + + protected: + virtual bool hasChanged() { return false; } + + virtual bool isDefault() { return true; } + + protected slots: + void updateButtons(); + + void settingsChangedSlot(); + + private: + void addPageInternal(QWidget *page, const QStringList &items, + const QString &pixmapName, const QString &header); + + void setupManagerConnections(KConfigDialogManager *manager); + + private: + static QAsciiDict openDialogs; + + class KConfigDialogPrivate; + + KConfigDialogPrivate *d; + + int m_lastAddedIndex; +}; +#endif //KONVICONFIGDIALOG_H diff --git a/konversation/src/konviface.h b/konversation/src/konviface.h new file mode 100644 index 0000000..945bd33 --- /dev/null +++ b/konversation/src/konviface.h @@ -0,0 +1,89 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2007-2007 Eike Hein +*/ + +#ifndef KONV_IFACE_H +#define KONV_IFACE_H + +#include "ignore.h" + +#include +#include + +#include + + +class KonvIface : virtual public DCOPObject +{ + K_DCOP + + k_dcop: + virtual void setAway(const QString &awaymessage) = 0; + virtual void setBack() = 0; + virtual void sayToAll(const QString &message) = 0; + virtual void actionToAll(const QString &message) = 0; + + virtual void raw(const QString& server,const QString& command) = 0; + virtual void say(const QString& server,const QString& target,const QString& command) = 0; + virtual void info(const QString& string) = 0; + virtual void debug(const QString& string) = 0; + virtual void error(const QString& string) = 0; + virtual void insertMarkerLine() = 0; + virtual void connectToServer(const QString& address, int port, const QString& channel, const QString& password) = 0; + virtual QString getNickname (const QString &serverid) = 0; + virtual QString getAnyNickname () = 0; + virtual QStringList listServers() = 0; + virtual QStringList listConnectedServers() = 0; + virtual QString getChannelEncoding(const QString& server, const QString& channel) = 0; + + virtual void setScreenSaverStarted() = 0; + virtual void setScreenSaverStopped() = 0; +}; + +class KonvIdentityIface : virtual public DCOPObject +{ + K_DCOP + k_dcop: + + virtual void setrealName(const QString &identity, const QString& name) = 0; + virtual QString getrealName(const QString &identity) = 0; + virtual void setIdent(const QString &identity, const QString& ident) = 0; + virtual QString getIdent(const QString &identity) = 0; + + virtual void setNickname(const QString &identity, int index,const QString& nick) = 0; + virtual QString getNickname(const QString &identity, int index) = 0; + + virtual void setBot(const QString &identity, const QString& bot) = 0; + virtual QString getBot(const QString &identity) = 0; + virtual void setPassword(const QString &identity, const QString& password) = 0; + virtual QString getPassword(const QString &identity) = 0; + + virtual void setNicknameList(const QString &identity, const QStringList& newList) = 0; + virtual QStringList getNicknameList(const QString &identity) = 0; + + virtual void setQuitReason(const QString &identity, const QString& reason) = 0; + virtual QString getQuitReason(const QString &identity) = 0; + virtual void setPartReason(const QString &identity, const QString& reason) = 0; + virtual QString getPartReason(const QString &identity) = 0; + virtual void setKickReason(const QString &identity, const QString& reason) = 0; + virtual QString getKickReason(const QString &identity) = 0; + + virtual void setShowAwayMessage(const QString &identity, bool state) = 0; + virtual bool getShowAwayMessage(const QString &identity) = 0; + + virtual void setAwayMessage(const QString &identity, const QString& message) = 0; + virtual QString getAwayMessage(const QString &identity) = 0; + virtual void setReturnMessage(const QString &identity, const QString& message) = 0; + virtual QString getReturnMessage(const QString &identity) = 0; + + virtual QStringList listIdentities() = 0; +}; +#endif diff --git a/konversation/src/konvirc.protocol b/konversation/src/konvirc.protocol new file mode 100644 index 0000000..78c00b8 --- /dev/null +++ b/konversation/src/konvirc.protocol @@ -0,0 +1,11 @@ +[Protocol] +exec=konversation %u +protocol=irc +input=none +output=none +helper=true +listing=false +reading=false +writing=false +makedir=false +deleting=false diff --git a/konversation/src/konvirc6.protocol b/konversation/src/konvirc6.protocol new file mode 100644 index 0000000..6d885cb --- /dev/null +++ b/konversation/src/konvirc6.protocol @@ -0,0 +1,11 @@ +[Protocol] +exec=konversation %u +protocol=irc6 +input=none +output=none +helper=true +listing=false +reading=false +writing=false +makedir=false +deleting=false diff --git a/konversation/src/konvisettingsdialog.cpp b/konversation/src/konvisettingsdialog.cpp new file mode 100644 index 0000000..0e00a35 --- /dev/null +++ b/konversation/src/konvisettingsdialog.cpp @@ -0,0 +1,316 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 John Tapsell + Copyright (C) 2006 Eike Hein +*/ + +#include "konvisettingsdialog.h" +#include "konviconfigdialog.h" +#include "config/preferences.h" +#include "chatwindowappearance_preferences.h" +#include "connectionbehavior_preferences.h" +#include "highlight_preferences.h" +#include "warnings_preferences.h" +#include "log_preferences.h" +#include "quickbuttons_preferences.h" +#include "autoreplace_preferences.h" +#include "chatwindowbehaviour_preferences.h" +#include "fontappearance_preferences.h" +#include "nicklistbehavior_preferences.h" +#include "tabs_preferences.h" +#include "colorsappearance_preferences.h" +#include "generalbehavior_preferences.h" +#include "dcc_preferences.h" +#include "osd_preferences.h" +#include "theme_preferences.h" +#include "alias_preferences.h" +#include "ignore_preferences.h" +#include "watchednicknames_preferences.h" +#include "tabnotifications_preferences.h" + +#include +#include + +#include +#include +#include +#include + + +KonviSettingsDialog::KonviSettingsDialog( QWidget *parent) : + KonviConfigDialog( parent, "settings", Preferences::self(), KDialogBase::TreeList) +{ + m_modified = false; + setShowIconsInTreeList(true); + + QStringList iconPath; + + iconPath << i18n("Interface"); + setFolderIcon( iconPath, SmallIcon("looknfeel") ); + + iconPath.clear(); + iconPath << i18n("Behavior"); + setFolderIcon( iconPath, SmallIcon("configure") ); + + iconPath.clear(); + iconPath<< i18n("Behavior"); + setFolderIcon( iconPath, SmallIcon("configure") ); + + iconPath.clear(); + iconPath<< i18n("Notifications"); + setFolderIcon( iconPath, SmallIcon("playsound") ); + + QStringList pagePath; + + //Interface/Chat Window + m_confChatWindowAppearanceWdg = new ChatWindowAppearance_Config( 0, "ChatWindowAppearance" ); + m_confChatWindowAppearanceWdg->kcfg_TimestampFormat->insertItem("hh:mm"); + m_confChatWindowAppearanceWdg->kcfg_TimestampFormat->insertItem("hh:mm:ss"); + m_confChatWindowAppearanceWdg->kcfg_TimestampFormat->insertItem("h:m ap"); + pagePath.clear(); + pagePath << i18n("Interface") << i18n("Chat Window"); + addPage ( m_confChatWindowAppearanceWdg, pagePath, "view_text", i18n("Chat Window") ); + + //Interface/Themes + m_confThemeWdg = new Theme_Config( this, "Theme" ); + pagePath.clear(); + pagePath << i18n("Interface") << i18n("Nicklist Themes"); + addPage ( m_confThemeWdg, pagePath, "iconthemes", i18n("Nicklist Themes") ); + m_indexToPageMapping.insert(lastAddedIndex(), m_confThemeWdg); + connect(m_confThemeWdg, SIGNAL(modified()), this, SLOT(modifiedSlot())); + + //Interface/Colors + m_confColorsAppearanceWdg = new ColorsAppearance_Config( this, "ColorsAppearance" ); + pagePath.clear(); + pagePath << i18n("Interface") << i18n("Colors"); + addPage ( m_confColorsAppearanceWdg, pagePath, "colorize", i18n("Colors") ); + + //Interface/Fonts + m_confFontAppearanceWdg = new FontAppearance_Config( this, "FontAppearance" ); + pagePath.clear(); + pagePath << i18n("Interface") << i18n("Fonts"); + addPage ( m_confFontAppearanceWdg, pagePath, "fonts", i18n("Fonts") ); + + //Interface/Quick Buttons + m_confQuickButtonsWdg = new QuickButtons_Config( this, "QuickButtons" ); + pagePath.clear(); + pagePath << i18n("Interface") << i18n("Quick Buttons"); + addPage ( m_confQuickButtonsWdg, pagePath, "keyboard", i18n("Quick Buttons") ); + m_indexToPageMapping.insert(lastAddedIndex(), m_confQuickButtonsWdg); + connect(m_confQuickButtonsWdg, SIGNAL(modified()), this, SLOT(modifiedSlot())); + + //Interface/Tabs + m_confTabBarWdg = new Tabs_Config( this, "TabBar" ); + pagePath.clear(); + pagePath << i18n("Interface") << i18n("Tabs"); + addPage ( m_confTabBarWdg, pagePath, "tab_new", i18n("Tabs") ); + + //Behavior/General + m_confGeneralBehaviorWdg = new GeneralBehavior_Config( this, "GeneralBehavior" ); + pagePath.clear(); + pagePath << i18n("Behavior") << i18n("General"); + addPage ( m_confGeneralBehaviorWdg, pagePath, "exec", i18n("General") ); + + //Behavior/Connection + m_confConnectionBehaviorWdg = new ConnectionBehavior_Config( this, "ConnectionBehavior" ); + pagePath.clear(); + pagePath << i18n("Behavior") << i18n("Connection"); + addPage ( m_confConnectionBehaviorWdg, pagePath, "connect_creating", i18n("Connection") ); + + //Behaviour/Chat Window + m_confChatwindowBehaviourWdg = new ChatwindowBehaviour_Config( this, "ChatwindowBehaviour" ); + pagePath.clear(); + pagePath << i18n("Behavior") << i18n("Chat Window"); + addPage ( m_confChatwindowBehaviourWdg, pagePath, "view_text", i18n("Chat Window") ); + + //Behaviour/Nickname List + m_confNicklistBehaviorWdg = new NicklistBehavior_Config( this, "NicklistBehavior" ); + pagePath.clear(); + pagePath << i18n("Behavior") << i18n("Nickname List"); + addPage ( m_confNicklistBehaviorWdg, pagePath, "player_playlist", i18n("Nickname List") ); + connect(m_confNicklistBehaviorWdg, SIGNAL(modified()), this, SLOT(modifiedSlot())); + m_indexToPageMapping.insert(lastAddedIndex(), m_confNicklistBehaviorWdg); + + //Behaviour/Command Aliases + m_confAliasWdg = new Alias_Config( this, "Alias" ); + pagePath.clear(); + pagePath << i18n("Behavior") << i18n("Command Aliases"); + addPage ( m_confAliasWdg, pagePath, "editcopy", i18n("Command Aliases") ); + m_indexToPageMapping.insert(lastAddedIndex(), m_confAliasWdg); + connect(m_confAliasWdg, SIGNAL(modified()), this, SLOT(modifiedSlot())); + + //Behaviour/Auto Replace + m_confAutoreplaceWdg = new Autoreplace_Config( this, "Autoreplace" ); + pagePath.clear(); + pagePath << i18n("Behavior") << i18n("Auto Replace"); + addPage ( m_confAutoreplaceWdg, pagePath, "kview", i18n("Auto Replace") ); + m_indexToPageMapping.insert(lastAddedIndex(), m_confAutoreplaceWdg); + connect(m_confAutoreplaceWdg, SIGNAL(modified()), this, SLOT(modifiedSlot())); + + //Behaviour/Ignore + m_confIgnoreWdg = new Ignore_Config(this, "Ignore"); + pagePath.clear(); + pagePath << i18n("Behavior") << i18n("Ignore"); + addPage ( m_confIgnoreWdg, pagePath, "stop", i18n("Ignore") ); + connect(m_confIgnoreWdg, SIGNAL(modified()), this, SLOT(modifiedSlot())); + m_indexToPageMapping.insert(lastAddedIndex(), m_confIgnoreWdg); + + //Behaviour/Logging + m_confLogWdg = new Log_Config( this, "Log" ); + pagePath.clear(); + pagePath << i18n("Behavior") << i18n("Logging"); + addPage ( m_confLogWdg, pagePath, "log", i18n("Logging") ); + + m_confDCCWdg = new DCC_Config( this, "DCC" ); + pagePath.clear(); + pagePath << i18n("Behavior") << i18n("DCC"); + addPage ( m_confDCCWdg, pagePath, "2rightarrow", i18n("DCC") ); + + //Notifications/Tab Bar + m_confTabNotificationsWdg = new TabNotifications_Config( this, "TabBar" ); + pagePath.clear(); + pagePath << i18n("Notifications") << i18n("Tabs"); + addPage ( m_confTabNotificationsWdg, pagePath, "tab_new", i18n("Tabs") ); + + //Notification/Highlighting + m_confHighlightWdg = new Highlight_Config( this, "Highlight" ); + pagePath.clear(); + pagePath << i18n("Notifications") << i18n("Highlight"); + addPage ( m_confHighlightWdg, pagePath, "paintbrush", i18n("Highlight") ); + connect(m_confHighlightWdg, SIGNAL(modified()), this, SLOT(modifiedSlot())); + m_indexToPageMapping.insert(lastAddedIndex(), m_confHighlightWdg); + + //Notification/Watched Nicknames + m_confWatchedNicknamesWdg = new WatchedNicknames_Config( this, "WatchedNicknames" ); + pagePath.clear(); + pagePath << i18n("Notifications") << i18n("Watched Nicknames"); + addPage ( m_confWatchedNicknamesWdg, pagePath, "kfind", i18n("Watched Nicknames") ); + // remember index so we can open this page later from outside + m_watchedNicknamesIndex=lastAddedIndex(); + connect(m_confWatchedNicknamesWdg, SIGNAL(modified()), this, SLOT(modifiedSlot())); + m_indexToPageMapping.insert(lastAddedIndex(), m_confWatchedNicknamesWdg); + + //Notification/On Screen Display + m_confOSDWdg = new OSD_Config( this, "OSD" ); + pagePath.clear(); + pagePath << i18n("Notifications") << i18n("On Screen Display"); + addPage ( m_confOSDWdg, pagePath, "tv", i18n("On Screen Display") ); + //no modified connection needed - it's all kcfg widgets + m_indexToPageMapping.insert(lastAddedIndex(), m_confOSDWdg); + + //Notification/Warning Dialogs + m_confWarningsWdg = new Warnings_Config( this, "Warnings" ); + pagePath.clear(); + pagePath << i18n("Notifications") << i18n("Warning Dialogs"); + addPage ( m_confWarningsWdg, pagePath, "messagebox_warning", i18n("Warning Dialogs") ); + m_indexToPageMapping.insert(lastAddedIndex(), m_confWarningsWdg); + connect(m_confWarningsWdg, SIGNAL(modified()), this, SLOT(modifiedSlot())); + + unfoldTreeList(); +} + +void KonviSettingsDialog::showEvent(QShowEvent* e) +{ + KonviConfigDialog::showEvent(e); + + QSplitter* splitter = ((QSplitter*)child(0, "QSplitter", true)); + KListView* listView = ((KListView*)child(0, "KListView", true)); + + if (splitter && listView) + { + int visible = listView->visibleWidth(); + int content = listView->contentsWidth(); + + if (visible < content) + { + int shiftSplitterBy = content - visible; + resize(width()+shiftSplitterBy, height()); + QValueList oldSizes = splitter->sizes(); + QValueList newSizes; + newSizes << oldSizes[0] + shiftSplitterBy << oldSizes[1] - shiftSplitterBy; + splitter->setSizes(newSizes); + } + } +} + +void KonviSettingsDialog::modifiedSlot() +{ + // this is for the non KConfigXT parts to tell us, if the user actually changed + // something or went back to the old settings +// kdDebug() << "KonviSettingsDialog::modifiedSlot()" << endl; + m_modified = false; + QIntDictIterator it( m_indexToPageMapping ); + for ( ; it.current(); ++it ) + { + if ( (*it).hasChanged() ) + { + m_modified = true; +// kdDebug() << "KonviSettingsDialog::modifiedSlot(): modified!" << endl; + break; + } + } + updateButtons(); +} + +KonviSettingsDialog::~KonviSettingsDialog() +{ +} + +void KonviSettingsDialog::updateSettings() +{ + QIntDictIterator it( m_indexToPageMapping ); + for ( ; it.current(); ++it ) + { + // this is for the non KConfigXT parts to update the UI (like quick buttons) + (*it).saveSettings(); + } + m_modified = false; + emit settingsChanged(); +} + +void KonviSettingsDialog::updateWidgets() +{ + QIntDictIterator it( m_indexToPageMapping ); + for ( ; it.current(); ++it ) + { + (*it).loadSettings(); + } + m_modified = false; +} + +void KonviSettingsDialog::updateWidgetsDefault() +{ + QIntDictIterator it( m_indexToPageMapping ); + for ( ; it.current(); ++it ) + { + (*it).restorePageToDefaults(); + } + m_modified = true; +} + +void KonviSettingsDialog::openWatchedNicknamesPage() +{ + // page index has been calculated in the constructor + showPage(m_watchedNicknamesIndex); +} + +// accessor method - will be used by KonviConfigDialog::updateButtons() +bool KonviSettingsDialog::hasChanged() +{ + return m_modified; +} + +// accessor method - will be used by KonviConfigDialog::updateButtons() +bool KonviSettingsDialog::isDefault() +{ + return true; +} + +#include "konvisettingsdialog.moc" + diff --git a/konversation/src/konvisettingsdialog.h b/konversation/src/konvisettingsdialog.h new file mode 100644 index 0000000..b9b0878 --- /dev/null +++ b/konversation/src/konvisettingsdialog.h @@ -0,0 +1,95 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 John Tapsell + Copyright (C) 2006 Eike Hein +*/ + +#ifndef KONVISETTINGSDIALOG_H +#define KONVISETTINGSDIALOG_H + +#include "konviconfigdialog.h" +#include "konvisettingspage.h" + +#include +#include +#include + + +class Warnings_Config; +class ChatWindowAppearance_Config; +class FontAppearance_Config; +class Theme_Config; +class ColorsAppearance_Config; +class GeneralBehavior_Config; +class ConnectionBehavior_Config; +class ChatwindowBehaviour_Config; +class NicklistBehavior_Config; +class Tabs_Config; +class Alias_Config; +class QuickButtons_Config; +class Autoreplace_Config; +class Log_Config; +class DCC_Config; +class WatchedNicknames_Config; +class Highlight_Config; +class OSD_Config; +class Ignore_Config; +class TabNotifications_Config; + +class KDEUI_EXPORT KonviSettingsDialog : public KonviConfigDialog +{ + Q_OBJECT + + protected: + Warnings_Config* m_confWarningsWdg; + ChatWindowAppearance_Config* m_confChatWindowAppearanceWdg; + FontAppearance_Config* m_confFontAppearanceWdg; + Theme_Config* m_confThemeWdg; + ColorsAppearance_Config* m_confColorsAppearanceWdg; + GeneralBehavior_Config* m_confGeneralBehaviorWdg; + ConnectionBehavior_Config* m_confConnectionBehaviorWdg; + ChatwindowBehaviour_Config* m_confChatwindowBehaviourWdg; + NicklistBehavior_Config* m_confNicklistBehaviorWdg; + Tabs_Config* m_confTabBarWdg; + Alias_Config* m_confAliasWdg; + QuickButtons_Config* m_confQuickButtonsWdg; + Autoreplace_Config* m_confAutoreplaceWdg; + Log_Config* m_confLogWdg; + DCC_Config* m_confDCCWdg; + WatchedNicknames_Config* m_confWatchedNicknamesWdg; + Highlight_Config* m_confHighlightWdg; + OSD_Config* m_confOSDWdg; + Ignore_Config* m_confIgnoreWdg; + TabNotifications_Config* m_confTabNotificationsWdg; + + bool m_modified; + + public: + explicit KonviSettingsDialog(QWidget *parent); + ~KonviSettingsDialog(); + + void openWatchedNicknamesPage(); + + protected slots: + virtual void updateSettings(); + virtual void updateWidgets(); + virtual void updateWidgetsDefault(); + void modifiedSlot(); + + protected: + virtual bool hasChanged(); + virtual bool isDefault(); + virtual void showEvent(QShowEvent* e); + + // remember page index + unsigned int m_watchedNicknamesIndex; + QIntDict m_indexToPageMapping; +}; + +#endif //KONVISETTINGSDIALOG_H diff --git a/konversation/src/konvisettingspage.h b/konversation/src/konvisettingspage.h new file mode 100644 index 0000000..e7c6aad --- /dev/null +++ b/konversation/src/konvisettingspage.h @@ -0,0 +1,27 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 John Tapsell +*/ + +#ifndef KONVISETTINGSPAGE_H +#define KONVISETTINGSPAGE_H + +class KonviSettingsPage +{ + public: + virtual void restorePageToDefaults() = 0; // function called when the user klicks "Default" + virtual void saveSettings() = 0; // function called when the user klicks "Ok" or "Apply" + virtual void loadSettings() = 0; // function called when the user opens the page + + virtual bool hasChanged() = 0; // is to return if any non-KConfigXT settings have changed +}; + +#endif + + diff --git a/konversation/src/linkaddressbook/Makefile.am b/konversation/src/linkaddressbook/Makefile.am new file mode 100644 index 0000000..266c2c6 --- /dev/null +++ b/konversation/src/linkaddressbook/Makefile.am @@ -0,0 +1,13 @@ +METASOURCES = AUTO + +INCLUDES = -I$(srcdir)/.. -I.. -I$(srcdir)/../config -I../config +AM_CPPFLAGS = $(all_includes) -I$(top_builddir)/konversation/src + +noinst_LTLIBRARIES = liblinkaddressbookui.la +noinst_HEADERS = linkaddressbookui.h kimiface.h + +liblinkaddressbookui_la_SOURCES = linkaddressbookui_base.ui linkaddressbookui.cpp addressbook_base.cpp addressbook.cpp nicklisttooltip.cpp nicksonlinetooltip.cpp kimiface.skel addresseeitem.cpp +kimiface_DIR = $(kde_includes) +liblinkaddressbookui_la_LDFLAGS = $(all_libraries) -no-undefined + +# vim: set noet: diff --git a/konversation/src/linkaddressbook/addressbook.cpp b/konversation/src/linkaddressbook/addressbook.cpp new file mode 100644 index 0000000..c5608e6 --- /dev/null +++ b/konversation/src/linkaddressbook/addressbook.cpp @@ -0,0 +1,339 @@ +/* + 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 class gives function that interact with kaddressbook. + begin: Fri 2004-07-23 + copyright: (C) 2004 by John Tapsell + email: john@geola.co.uk +*/ + +#include "addressbook.h" +#include "../viewcontainer.h" +#include "../konversationmainwindow.h" +#include "../server.h" +#include "../channel.h" +#include "../konversationapplication.h" + +#include +#include "qwidget.h" + +#include +#include +#include +#include +#include + + +namespace Konversation +{ + + Addressbook *Addressbook::m_instance=0L; + + Addressbook::Addressbook() : DCOPObject( "KIMIface") + { + addressBook = KABC::StdAddressBook::self(true); + m_ticket=NULL; + } + Addressbook::~Addressbook() + { + if (m_instance == this) + sd.setObject(m_instance, 0, false); + } + + Addressbook *Addressbook::self() + { + if (!m_instance) { sd.setObject(m_instance, new Addressbook()); } + return m_instance; + } + + QStringList Addressbook::allContacts() + { + QStringList contactUIDS; + for( KABC::AddressBook::Iterator it = addressBook->begin(); it != addressBook->end(); ++it ) + if(hasAnyNicks(*it)) contactUIDS.append((*it).uid()); + return contactUIDS; + } + //Produces a string list of all the irc nicks that are known. + QStringList Addressbook::allContactsNicks() + { + QStringList contacts; + for( KABC::AddressBook::Iterator it = addressBook->begin(); it != addressBook->end(); ++it ) + contacts += QStringList::split( QChar( 0xE000 ), (*it).custom("messaging/irc", "All") ); + return contacts; + } + + QStringList Addressbook::onlineContacts() + { + QStringList contactUIDS; + for( KABC::AddressBook::Iterator it = addressBook->begin(); it != addressBook->end(); ++it ) + if(isOnline(*it)) contactUIDS.append((*it).uid()); + + return contactUIDS; + } + QStringList Addressbook::reachableContacts() + { + return onlineContacts(); + } + QStringList Addressbook::fileTransferContacts() + { + return onlineContacts(); + } + bool Addressbook::isPresent(const QString &uid) + { + return hasAnyNicks(addressBook->findByUid(uid)); + } + QString Addressbook::displayName(const QString &uid) + { + return getBestNick(addressBook->findByUid(uid)); + } + QString Addressbook::presenceString(const QString &uid) + { + if(uid.isEmpty()) + { + kdDebug() << "Addressbook::presenceString() called with an empty uid" << endl; + return QString("Error"); + } + switch( presenceStatus(uid)) + { + case 0: + return ""; + case 1: + return i18n("Offline"); + case 2: + return i18n("Connecting"); //Shouldn't happen - not supported. + case 3: + return i18n("Away"); + case 4: + return i18n("Online"); + } + return QString("Error"); + } + int Addressbook::presenceStatus(const QString &uid) + { + return presenceStatusByAddressee(addressBook->findByUid(uid)); + } + + bool Addressbook::canReceiveFiles(const QString &uid) + { + if(uid.isEmpty()) + { + kdDebug() << "Addressbook::canReceiveFiles() called with empty uid" << endl; + return false; + } + int presence = presenceStatus(uid); + + return (presence == 4) || (presence == 3); + } + bool Addressbook::canRespond(const QString &uid) + { + if(uid.isEmpty()) + { + kdDebug() << "Addressbook::canRespond called with empty uid" << endl; + return false; + } + //this should return false if they are offline. + int result = presenceStatus(uid); + if(result == 3 || result == 4) return true; + return false; + } + QString Addressbook::locate(const QString &contactId, const QString &protocol) + { + if(contactId.isEmpty()) + { + kdDebug() << "Addressbook::locate called with empty contactId" << endl; + return QString(); + } + if(protocol != "messaging/irc") + return QString(); + + return getKABCAddresseeFromNick(contactId).uid(); + } + QPixmap Addressbook::icon(const QString &uid) + { + + Images* icons = KonversationApplication::instance()->images(); + QIconSet currentIcon; + if(!isPresent(uid)) + return QPixmap(); + + switch(presenceStatus(uid)) + { + case 0: //Unknown + case 1: //Offline + case 2: //connecting - invalid for us? + currentIcon = icons->getKimproxyOffline(); + break; + case 3: //Away + currentIcon = icons->getKimproxyAway(); + break; + case 4: //Online + currentIcon = icons->getKimproxyOnline(); + break; + default: + //error + kdDebug() << "Unknown status " << uid << endl; + return QPixmap(); + } + + QPixmap joinedIcon = currentIcon.pixmap(QIconSet::Automatic, QIconSet::Active, QIconSet::On); + return joinedIcon; + } + QString Addressbook::context(const QString &uid) + { + if(uid.isEmpty()) + { + kdDebug() << "Addressbook::contact called with empty uid" << endl; + return QString(); + } + QString context; + return context; + } + QStringList Addressbook::protocols() + { + QStringList protocols; + protocols.append("messaging/irc"); + return protocols; + } + + // ACTORS + /** + * Send a single message to the specified addressee + * Any response will be handled by the IM client as a normal + * conversation. + * @param uid the KABC uid you want to chat with. + * @param message the message to send them. + */ + void Addressbook::messageContact( const QString &uid, const QString& message ) + { + if(uid.isEmpty()) + { + focusAndShowErrorMessage(i18n("Another KDE application tried to use Konversation for instant messaging, but did not specify any contact to send the message to. This is probably a bug in the other application.")); + return; + } + KABC::Addressee addressee = addressBook->findByUid(uid); + if(addressee.isEmpty()) + { + focusAndShowErrorMessage(i18n("Another KDE application tried to use Konversation for instant messaging, but Konversation could not find the specified contact in the KDE address book.")); + return; + } + NickInfoPtr nickInfo = getNickInfo(addressee); + if(!nickInfo) + { + QString user = addressee.fullEmail(); + if(!user.isEmpty()) user = " (" + user + ')'; + focusAndShowErrorMessage(i18n("Another KDE application tried to use Konversation for instant messaging, but the requested user%1 is not online.").arg(user)); + return; + } + + nickInfo->getServer()->dcopSay(nickInfo->getNickname(), message); + } + + /** + * Open a chat to a contact, and optionally set some initial text + */ + void Addressbook::messageNewContact( const QString &contactId, const QString &/*protocol*/ ) { + if(contactId.isEmpty() ) + { + kdDebug() << "Addressbook::messageNewContact called with empty contactid" << endl; + focusAndShowErrorMessage(i18n("Another KDE application tried to use Konversation for instant messaging, but did not specify any contact to send the message to. This is probably a bug in the other application.")); + return; + } + messageContact(contactId, QString()); +} + +/** + * Start a chat session with the specified addressee + * @param uid the KABC uid you want to chat with. + */ +void Addressbook::chatWithContact( const QString &uid ) +{ + if(uid.isEmpty()) + { + kdDebug() << "Addressbook::chatWithContact called with empty uid" << endl; + focusAndShowErrorMessage(i18n("Another KDE application tried to use Konversation for instant messaging, but did not specify any contact to send the message to. This is probably a bug in the other application.")); + return; + } + messageContact(uid, QString()); +} + +/** + * Send the file to the contact + * @param uid the KABC uid you are sending to. + * @param sourceURL a KURL to send. + * @param altFileName an alternate filename describing the file + * @param fileSize file size in bytes + */ +void Addressbook::sendFile(const QString &uid, const KURL &sourceURL, const QString &altFileName, uint fileSize) +{ + if(uid.isEmpty()) + { + focusAndShowErrorMessage(i18n("Another KDE application tried to use Konversation to send a file to a contact, but did not specify any contact to send the file to. This is probably a bug in the other application.")); + return; + } + KABC::Addressee addressee = addressBook->findByUid(uid); + if(addressee.isEmpty()) + { + focusAndShowErrorMessage(i18n("Another KDE application tried to use Konversation to send a file to a contact, but Konversation could not find the specified contact in the KDE address book.")); + return; + } + NickInfoPtr nickInfo = getNickInfo(addressee); + if(!nickInfo) + { + QString user = addressee.fullEmail(); + if(!user.isEmpty()) user = " (" + user + ')'; + focusAndShowErrorMessage(i18n("Another KDE application tried to use Konversation to send a file to a contact, but the requested user%1 is not currently online.").arg(user)); + return; + } + nickInfo->getServer()->addDccSend(nickInfo->getNickname(), sourceURL, altFileName, fileSize); + QWidget *widget = nickInfo->getServer()->getViewContainer()->getWindow(); + KWin::demandAttention(widget->winId()); //If activeWindow request is denied, at least demand attention! + KWin::activateWindow(widget->winId()); //May or may not work, depending on focus stealing prevention. + +} + +// MUTATORS +// Contact list +/** + * Add a contact to the contact list + * @param contactId the protocol specific identifier for the contact, eg UIN for ICQ, screenname for AIM, nick for IRC. + * @param protocolId the protocol, eg one of "AIMProtocol", "MSNProtocol", "ICQProtocol", ... + * @return whether the add succeeded. False may signal already present, protocol not supported, or add operation not supported. + */ +bool Addressbook::addContact( const QString &/*contactId*/, const QString &/*protocolId*/ ) { +focusAndShowErrorMessage(i18n("Another KDE application tried to use Konversation to add a contact. Konversation does support this.")); +return false; +//Nicks are auto added if they are put in the addressbook - I don' think there is anything useful I can do. +} + +void Addressbook::emitContactPresenceChanged(const QString &uid, int presence) +{ + if(uid.isEmpty()) + { + //This warning below is annoying. FIXME - disabled because it's too verbose + // kdDebug() << "Addressbook::emitContactPresenceChanged was called with empty uid" << endl; + return; + } + Q_ASSERT(kapp->dcopClient()); + emit contactPresenceChanged(uid, kapp->dcopClient()->appId(), presence); + // kdDebug() << "Presence changed for uid " << uid << " to " << presence << endl; +} + +void Addressbook::emitContactPresenceChanged(const QString &uid) +{ + if(uid.isEmpty()) + { + kdDebug() << "Addressbook::emitContactPresenceChanged was called with empty uid" << endl; + return; + }; + + emitContactPresenceChanged(uid, presenceStatus(uid)); +} + +} //NAMESPACE + +#include "addressbook.moc" diff --git a/konversation/src/linkaddressbook/addressbook.h b/konversation/src/linkaddressbook/addressbook.h new file mode 100644 index 0000000..9b906f5 --- /dev/null +++ b/konversation/src/linkaddressbook/addressbook.h @@ -0,0 +1,99 @@ +/* + 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 class contains functions that interact with kaddressbook. + begin: Fri 2004-07-23 + copyright: (C) 2004 by John Tapsell + email: john@geola.co.uk +*/ + +#ifndef ADDRESSBOOK_H +#define ADDRESSBOOK_H + +#include +#include + +#include +#include +#include +#include +#include "kimiface.h" + +#include "../images.h" +#include "../nickinfo.h" +#include "addressbook_base.h" + +namespace Konversation +{ + class Addressbook : public AddressbookBase + { + Q_OBJECT + public: + + virtual ~Addressbook(); // This needs to be public so it can be deleted by our static pointer + static Addressbook *self(); + QStringList allContactsNicks(); + QStringList allContacts(); + QStringList reachableContacts(); + QStringList onlineContacts(); + QStringList fileTransferContacts(); + bool isPresent( const QString &uid ); + QString displayName( const QString &uid ); + QString presenceString( const QString &uid ); + bool canReceiveFiles( const QString &uid ); + bool canRespond( const QString &uid ); + QString locate( const QString &contactId, const QString &protocol ); + // metadata + QPixmap icon( const QString &uid ); + QString context( const QString &uid ); + virtual int presenceStatus(const QString &uid); + // App capabilities + QStringList protocols(); + + /** + * Message a contact by their metaContactId, aka their uid in KABC. + */ + void messageContact( const QString &uid, const QString& message ); + + /** + * Open a chat to a contact, and optionally set some initial text + */ + void messageNewContact( const QString &contactId, const QString &protocolId ); + + /** + * Message a contact by their metaContactId, aka their uid in KABC. + */ + void chatWithContact( const QString &uid ); + + /** + * Send the file to the contact + */ + void sendFile(const QString &uid, const KURL &sourceURL, + const QString &altFileName = QString(), uint fileSize = 0); + + /** + * Lets outsiders tell us to emit presenceChanged signal. + */ + void emitContactPresenceChanged( const QString &uid, int presence); + /** + * Lets outsiders tell us to emit presenceChanged signal. + */ + void emitContactPresenceChanged(const QString &uid); + + bool addContact( const QString &contactId, const QString &protocolId ); + + protected: + Addressbook(); + + static Addressbook *m_instance; + }; + + static KStaticDeleter sd; + +} +#endif diff --git a/konversation/src/linkaddressbook/addressbook_base.cpp b/konversation/src/linkaddressbook/addressbook_base.cpp new file mode 100644 index 0000000..b8f7243 --- /dev/null +++ b/konversation/src/linkaddressbook/addressbook_base.cpp @@ -0,0 +1,516 @@ +/* + 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. +*/ + +/* + addressbook.cpp - This class gives function that interact with kaddressbook. + begin: Fri 2004-07-23 + copyright: (C) 2004 by John Tapsell + email: john@geola.co.uk +*/ + +#include "addressbook.h" +#include "../server.h" +#include "../konversationapplication.h" +#include "../konversationmainwindow.h" +#include "../channel.h" + +#include + +#include +#include +#include +#include +#include +#include + +namespace Konversation +{ + + AddressbookBase::AddressbookBase() + { + KABC::StdAddressBook::setAutomaticSave( false ); + m_ticket=NULL; + } + + AddressbookBase::~AddressbookBase() + { + } + + KABC::AddressBook *AddressbookBase::getAddressBook() { return addressBook; } + + KABC::Addressee AddressbookBase::getKABCAddresseeFromNick(const QString &ircnick, const QString &servername, const QString &servergroup) + { + KABC::AddressBook::Iterator it; + + for( it = addressBook->begin(); it != addressBook->end(); ++it ) + { + if(hasNick(*it, ircnick, servername, servergroup)) + return (*it); + } + return KABC::Addressee(); + } + KABC::Addressee AddressbookBase::getKABCAddresseeFromNick(const QString &nick_server) + { + KABC::AddressBook::Iterator it; + + for( it = addressBook->begin(); it != addressBook->end(); ++it ) + { + if(hasNick(*it, nick_server)) + return (*it); + } + return KABC::Addressee(); + } + + bool AddressbookBase::hasNick(const KABC::Addressee &addressee, const QString &ircnick, const QString &servername, const QString &servergroup) + { + + QString lnick = ircnick.lower(); + QString lnick_servername; + QString lnick_servergroup; + if(!servername.isEmpty()) + lnick_servername = lnick + QChar(0xE120) + servername.lower(); + if(!servergroup.isEmpty()) + lnick_servergroup = lnick + QChar(0xE120) + servergroup.lower(); + + QString lit; + QStringList addresses = QStringList::split( QChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); + QStringList::iterator end = addresses.end(); + for ( QStringList::iterator it = addresses.begin(); it != end; ++it ) + { + lit = (*it).lower(); + if(lit == lnick || lit == lnick_servername || lit == lnick_servergroup) + return true; + } + return false; + + } + + QStringList AddressbookBase::allContactsNicksForServer(const QString &servername, const QString &servergroup) + { + QStringList contacts; + for( KABC::AddressBook::Iterator it = addressBook->begin(); it != addressBook->end(); ++it ) + contacts += getNicks(*it, servername, servergroup); + return contacts; + + } + + QStringList AddressbookBase::getNicks(const KABC::Addressee &addressee, const QString &servername, const QString &servergroup) + { + QStringList nicks; + + QString lservername = servername.lower(); + QString lservergroup = servergroup.lower(); + + QStringList addresses = QStringList::split( QChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); + QStringList::iterator end = addresses.end(); + for ( QStringList::iterator it = addresses.begin(); it != end; ++it ) + { + if(!(*it).contains(QChar( 0xE120))) + nicks.append(*it); + else + { + QString it_server = (*it).section(QChar( 0xE120), 0,0).lower(); + if(it_server == lservername || it_server == lservergroup) + nicks.append((*it).section(QChar( 0xE120 ), 1,1)); + } + } + return nicks; + } + + bool AddressbookBase::hasNick(const KABC::Addressee &addressee, const QString &nick_server) + { + QString lnick_server = nick_server.lower(); + QStringList addresses = QStringList::split( QChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); + QStringList::iterator end = addresses.end(); + for ( QStringList::iterator it = addresses.begin(); it != end; ++it ) + { + QString it_server = (*it).section(QChar( 0xE120), 0,0).lower(); + if(it_server ==lnick_server) + return true; + } + return false; + + } + + QString AddressbookBase::getBestNick(const KABC::Addressee &addressee) + { + //Look for a nickinfo for this nick, and use that. That way we turn a nick that is online. + NickInfoPtr nickInfo = getNickInfo(addressee); + if(nickInfo) + return nickInfo->getNickname(); + //No online nickinfo - not connected to server maybe. just return the first nick. + + QStringList addresses = QStringList::split( QChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); + if(!addresses.empty()) + return addresses.first(); + //No irc nicks- nothing left to try - return null + return QString(); + } + + NickInfoPtr AddressbookBase::getNickInfo(const KABC::Addressee &addressee) + { + NickInfoPtr lastNickInfo; + QStringList addresses = QStringList::split( QChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); + QStringList::iterator end = addresses.end(); + for ( QStringList::iterator it = addresses.begin(); it != end; ++it ) + { + QString ircnick; + QString serverOrGroup; + KonversationApplication::splitNick_Server(*it, ircnick, serverOrGroup); + NickInfoPtr nickInfo = + dynamic_cast(kapp)->getNickInfo(ircnick, serverOrGroup); + if(nickInfo) + { + if(!nickInfo->isAway()) + return nickInfo; + //This nick is away. Keep looking, but use it if we can't find one that's on + lastNickInfo = nickInfo; + } + } + //Use a nick that's either away, or non-existant. + return lastNickInfo; + } + + bool AddressbookBase::hasAnyNicks(const KABC::Addressee &addressee) + { + return !addressee.custom("messaging/irc", "All").isEmpty(); + } + void AddressbookBase::unassociateNick(KABC::Addressee &addressee, const QString &ircnick, const QString &servername, const QString &servergroup) + { + + kdDebug() << "in unassociatenick for '" << ircnick << endl; + if(ircnick.isEmpty()) return; + + QString lnick = ircnick.lower(); + QString lnick_servername; + QString lnick_servergroup; + if(!servername.isEmpty()) + lnick_servername = lnick + QChar(0xE120) + servername.lower(); + if(!servergroup.isEmpty()) + lnick_servergroup = lnick + QChar(0xE120) + servergroup.lower(); + + //We should now have lnick = ircnick, and versions with servername and servergroup - + // like johnflux, johnflux@freenode, or johnflux@irc.kde.org except with the unicode + // separator char 0xe120 instead of the @ + + kdDebug() << "nick" << ircnick<< endl; + bool changed = false; + if(addressee.isEmpty()) + { + kdDebug() << "Ignoring unassociation command for empty addressee for nick " << ircnick << endl; + } + QString lit; + QStringList addresses = QStringList::split( QChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); + QStringList::iterator it = addresses.begin(); + while(it != addresses.end()) + { + lit = (*it).lower(); + if(lit == lnick || lit == lnick_servername || lit == lnick_servergroup) + { + changed = true; + it = addresses.remove(it); + } + else + { + it++; + } + } + if(!changed) + return; + + //if(!getAndCheckTicket()) + // return; + QString new_custom = addresses.join( QChar( 0xE000 )); + if(new_custom.isEmpty()) + addressee.removeCustom("messaging/irc", "All"); + else + addressee.insertCustom("messaging/irc", "All", new_custom); + + addressBook->insertAddressee(addressee); + //saveTicket(); + } + void AddressbookBase::focusAndShowErrorMessage(const QString &errorMsg) + { + static_cast(kapp)->getMainWindow()->focusAndShowErrorMessage(errorMsg); + } + /**For a given contact, adds the ircnick if they don't already have it. If you pass an addressBook, the contact is inserted + * if it has changed. */ + void AddressbookBase::associateNick(KABC::Addressee &addressee, const QString &ircnick, const QString &servername, const QString &servergroup) + { + //It's easiest to just remove it from the list if it's there already + unassociateNick(addressee, ircnick, servername, servergroup); + QString nick_server = ircnick; + if(!servergroup.isEmpty()) + nick_server += QChar(0xE120) + servergroup; + else if(!servername.isEmpty()) + nick_server += QChar(0xE120) + servername; + QStringList addresses = QStringList::split( QChar( 0xE000 ), addressee.custom("messaging/irc", "All") ); + //For sanity reasons, don't let the number of irc nicks go above 10. + //To do this, just remove the irc nick at the end of the list. + if(addresses.count() >= 10) + addresses.pop_back(); + addresses.append(nick_server); + addressee.insertCustom("messaging/irc", "All", addresses.join( QChar( 0xE000 ))); + + addressBook->insertAddressee(addressee); + } + /** This function associates the nick for a person, then iterates over all the contacts unassociating the nick from everyone else. It saves the addressses that have changed.*/ + bool AddressbookBase::associateNickAndUnassociateFromEveryoneElse(KABC::Addressee &addressee, const QString &ircnick, const QString &servername, const QString &servergroup) + { + for( KABC::AddressBook::Iterator it = addressBook->begin(); it != addressBook->end(); ++it ) + if((*it).uid() != addressee.uid()) + unassociateNick(*it, ircnick, servername, servergroup); + associateNick(addressee, ircnick, servername, servergroup); + return true;; + } + + bool AddressbookBase::getAndCheckTicket() + { + if(m_ticket) + { + kdError() << "Internal error - getting new ticket without saving old" << endl; + return false; + } + m_ticket = addressBook->requestSaveTicket(); + if ( !m_ticket ) + { + kdError() << "Resource is locked by other application!" << endl; + //emit error + return false; + } + kdDebug() << "gotTicketSuccessfully" << endl; + return true; + } + void AddressbookBase::releaseTicket() + { + addressBook->releaseSaveTicket(m_ticket); + m_ticket = NULL; + } + + bool AddressbookBase::saveTicket() + { + if(!addressBook->save( m_ticket) ) + { + kdError() << "Saving failed!" << endl; + addressBook->releaseSaveTicket(m_ticket); + m_ticket = NULL; + return false; + } + kdDebug() << "saveTicket() was successful" << endl; + m_ticket= NULL; + emit addresseesChanged(); + return true; + } + + bool AddressbookBase::saveAddressbook() + { + if(m_ticket) + { + kdError() << "Internal error - getting new ticket without saving old" << endl; + return false; + } + m_ticket = addressBook->requestSaveTicket(); + if ( !m_ticket ) + { + kdError() << "Resource is locked by other application!" << endl; + return false; + } + else + { + if ( !addressBook->save( m_ticket ) ) + { + kdError() << "Saving failed!" << endl; + addressBook->releaseSaveTicket(m_ticket); + m_ticket = NULL; + return false; + } + } + kdDebug() << "Save was successful" << endl; + m_ticket = NULL; + emit addresseesChanged(); + return true; + } + + bool AddressbookBase::saveAddressee(KABC::Addressee &addressee) + { + Q_ASSERT(&addressee); + addressBook->insertAddressee(addressee); + bool success = saveAddressbook(); + if(success) + emitContactPresenceChanged(addressee.uid(), presenceStatusByAddressee(addressee)); + return success; + } + + /** + * Indicate the presence as a number. Checks all the nicks that that person has. + * If we find them, return 4 (online). + * If we are connected to any of the servers that they are on, and we don't find them, return 1 (offline) + * If we find them, but they are set to away then return 3 (away) + * If we are connected to none of the servers that they are on, return 0 (unknown) + * @param addressee Addressbook contact you want to know of the presence of + * @return 0 (unknown), 1 (offline), 3 (away), 4 (online) + */ + int AddressbookBase::presenceStatusByAddressee(const KABC::Addressee &addressee) + { + Q_ASSERT(&addressee); + NickInfoPtr nickInfo = getNickInfo(addressee); + + if(!nickInfo) + { + if(hasAnyNicks(addressee)) + return 1; //either offline, or we aren't on the same server. + else + return 0; //Not known to us + } + if(nickInfo->isAway()) return 3; + return 4; + + } + bool AddressbookBase::isOnline(KABC::Addressee &addressee) + { + return !!getNickInfo(addressee); + } + + bool AddressbookBase::editAddressee(const QString &uid) + { + Q_ASSERT(!uid.isEmpty()); + //FIXME: This hack can be removed. I fixed the below mentioned bug in kde 3.4 cvs - 2005-01-02 + // + //Because of stupid bugs in kaddressbook, first load kaddressbook using startServiceByDesktopPath + // then call it on the command line to actually put it in edit mode. This is stupid :( + kapp->startServiceByDesktopName( "kaddressbook" ); + + KProcess *proc = new KProcess; + *proc << "kaddressbook"; + *proc << "--editor-only" << "--uid" << uid; + kdDebug() << "running kaddressbook --editor-only --uid " << uid << endl; + if(!proc->start()) + { + KMessageBox::error(0, i18n("Could not run your addressbook program (kaddressbook). This is most likely because it is not installed. Please install the 'kdepim' packages.")); + return false; + } + return true; + } + + bool AddressbookBase::sendEmail(const KABC::Addressee &addressee) + { + if(addressee.preferredEmail().isEmpty()) + { + KMessageBox::sorry(0, i18n("The contact that you have selected does not have an email address associated with them. "), i18n("Cannot Send Email")); + return false; + } + return runEmailProgram(addressee.fullEmail()); + } + + bool AddressbookBase::runEmailProgram(const QString &mailtoaddress) + { + KRun *proc = new KRun(KURL(QString("mailto:") + KStringHandler::from8Bit(mailtoaddress.ascii()))); + kdDebug() << "Sending email to " << mailtoaddress << endl; + if(proc->hasError()) + { + KMessageBox::error(0, i18n("Could not run your email program. This is possibly because one is not installed. To install the KDE email program (kmail) please install the 'kdepim' packages.")); + return false; + } + return true; + + } + bool AddressbookBase::sendEmail(const ChannelNickList &nickList) + { + if(nickList.isEmpty()) return false; + QString mailto; + + QStringList nicksWithoutAddressee; + QStringList nicksWithoutEmails; + QStringList nicksWithEmails; + for(ChannelNickList::ConstIterator it=nickList.begin();it!=nickList.end();++it) + { + NickInfoPtr nickInfo = (*it)->getNickInfo(); + Q_ASSERT(nickInfo); if(!nickInfo) return false; + KABC::Addressee addr = nickInfo->getAddressee(); + if(addr.isEmpty()) + { + nicksWithoutAddressee.append(nickInfo->getNickname()); + } + else if(addr.preferredEmail().isEmpty()) + { + nicksWithoutEmails.append(nickInfo->getNickname()); + } + else + { + nicksWithEmails.append(nickInfo->getNickname()); + if(!mailto.isEmpty()) + mailto += ", "; + mailto += addr.fullEmail(); + + } + } + if(!nicksWithoutAddressee.isEmpty() || !nicksWithoutEmails.isEmpty()) + { + QString message; + if(nicksWithoutEmails.isEmpty()) + { + if(nicksWithEmails.isEmpty()) + { + if(nicksWithoutAddressee.count() > 1) + message = i18n("None of the contacts that you have selected were associated with an addressbook contacts. "); + else + message = i18n("The contact that you have selected is not associated with an addressbook contact. "); + } + else + { + if(nicksWithoutAddressee.count() > 1) + message = i18n("Some of the contacts (%1) that you have selected are not associated with addressbook contacts. ").arg(nicksWithoutAddressee.join(", ")); + else + message = i18n("One of the contacts (%1) that you have selected is not associated with an addressbook contact. ").arg(nicksWithoutAddressee.join(", ")); + } + message += i18n("You can right click on a contact, and choose to edit the Addressbook Associations to link them to a contact in your addressbook."); + } + else if(nicksWithoutAddressee.isEmpty()) + { + if(nicksWithEmails.isEmpty()) + { + if(nicksWithoutEmails.count() > 1) + message = i18n("None of the contacts that you have selected have an email address associated with them. "); + else + message = i18n("The contact that you have selected does not have an email address associated with them. "); + } + else + { + if(nicksWithoutEmails.count() > 1) + message = i18n("Some of the contacts (%1) that you have selected do not have an email address associated with them. ").arg(nicksWithoutEmails.join(", ")); + else + message = i18n("One of the contacts (%1) that you have selected does not have an email address associated with them. ").arg(nicksWithoutEmails.join(", ")); + } + message += i18n("You can right click on a contact, and choose to edit the addressbook contact, adding an email for them."); + } + else + { + message = i18n("Some of the contacts (%1) that you have selected are not associated with addressbook contacts, and some of the contacts (%2) do not have an email address associated with them. ").arg(nicksWithoutAddressee.join(", ").arg(nicksWithoutEmails.join(", "))); + message += i18n("You can right click on a contact, and choose to edit the Addressbook Associations to link them to a contact in your addressbook, and choose to edit the addressbook contact, adding an email for them."); + } + if(nicksWithEmails.isEmpty()) + { + KMessageBox::sorry(0, message, i18n("Cannot Send Email")); + return false; + } + else + { + message += i18n("\nDo you want to send an email anyway to the nicks that do have an email address?"); + int result = KMessageBox::questionYesNo(0, message, i18n("Send Email"), KGuiItem(i18n("&Send Email...")), KGuiItem(i18n("&Cancel"))); + if(result == KMessageBox::No) + { + return false; + } + } + } + + return runEmailProgram(mailto); + } + +} // NAMESPACE + +#include "addressbook_base.moc" diff --git a/konversation/src/linkaddressbook/addressbook_base.h b/konversation/src/linkaddressbook/addressbook_base.h new file mode 100644 index 0000000..d7db6c8 --- /dev/null +++ b/konversation/src/linkaddressbook/addressbook_base.h @@ -0,0 +1,128 @@ +/* + 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. +*/ + +/* + addressbook.cpp - This class contains functions that interact with kaddressbook. + begin: Fri 2004-07-23 + copyright: (C) 2004 by John Tapsell + email: john@geola.co.uk +*/ + +#ifndef ADDRESSBOOKBASE_H +#define ADDRESSBOOKBASE_H + +#include "../images.h" +#include "../nickinfo.h" +#include "../channelnick.h" + +#include +#include +#include +#include + + +#include +#include + + +namespace Konversation +{ + class AddressbookBase : public QObject, public KIMIface + { + Q_OBJECT + public: + virtual ~AddressbookBase(); // This needs to be public so it can be deleted by our static pointer + KABC::Addressee getKABCAddresseeFromNick(const QString &ircnick, const QString &servername, const QString &servergroup); + KABC::Addressee getKABCAddresseeFromNick(const QString &nick_server); + bool hasNick(const KABC::Addressee &addressee, const QString &ircnick, const QString &servername, const QString &servergroup); + bool hasNick(const KABC::Addressee &addressee, const QString &nick_server); + + /** For a given contact, remove the ircnick if they have it. If you + * pass an addressBook, the contact is inserted if it has changed. + */ + void unassociateNick(KABC::Addressee &addressee, const QString &ircnick, const QString &servername, const QString &servergroup); + void associateNick(KABC::Addressee &addressee, const QString &ircnick, const QString &servername, const QString &servergroup); + bool associateNickAndUnassociateFromEveryoneElse(KABC::Addressee &addressee, const QString &ircnick, const QString &servername, const QString &servergroup); + /** If this user is online, return one of the nicks that they are + * using. Otherwise return the first nick listed. + * If there are multiple matches, it will prefer ones that are not set to away. + * @return online nick, first nick, or QString::null if they aren't known at all. + */ + QString getBestNick(const KABC::Addressee &addressee); + bool hasAnyNicks(const KABC::Addressee &addresse); + int presenceStatusByAddressee(const KABC::Addressee &addressee); + bool isOnline(KABC::Addressee &addressee); + bool getAndCheckTicket(); + bool saveTicket(); + void releaseTicket(); + bool saveAddressee(KABC::Addressee &addressee); + bool saveAddressbook(); + + QStringList allContactsNicksForServer(const QString &servername, const QString &servergroup); + QStringList getNicks(const KABC::Addressee &addressee, const QString &servername, const QString &servergroup); + + KABC::AddressBook *getAddressBook(); + + /** Return an online NickInfo for this addressee. + * If there are multiple matches, it tries to pick one that is not away. + * Note: No NickInfo is returned if the addressee is offline. + * NickInfo's are for online and away nicks only. + * @param addressee The addressee to get a nickInfo for + * @return A nickInfo. It tries hard to return a nickInfo that is not away if one exists. + */ + static NickInfoPtr getNickInfo(const KABC::Addressee &addressee); + /** + * Lets outsiders tell us to emit presenceChanged signal. + */ + virtual void emitContactPresenceChanged(const QString &uid, int presence) = 0; + /** + * Lets outsiders tell us to emit presenceChanged signal. + */ + virtual void emitContactPresenceChanged(const QString &uid) = 0; + + /** + * Run kmail (or whatever the users email client is) + * to create a single email addressed to all of the nicks passed in. + * Gives an error dialog to the user if any of the contacts don't have an + * email address associated, and gives the user the option to continue + * with the contacts that did have email addresses. + */ + bool sendEmail(const ChannelNickList &nicklist); + /** + * Run kmail (or whatever the users email client is) + * to create a single email addressed to the addressee passed in. + * Gives an error dialog to the user if the addressee doesn't have an email address associated. + */ + bool sendEmail(const KABC::Addressee &addressee); + /** + * Run kaddressbook to edit the addressee passed in. + */ + bool editAddressee(const QString &uid); + /** + * Run the users email program (e.g. kmail) passing "mailto:" + mailtoaddress. + * Note that mailto: will be prepended for you. + * @param mailtoaddress A comma delimited set of email address topass as "mailto:" + * @return True if there were no problems running the email program. An error will be shown to the user if there was. + */ + bool runEmailProgram(const QString &mailtoaddress); + + /** Just calls KonversationMainWindow::focusAndShowErrorMessage(const QString *errorMsg) + * + * @see KonversationMainWindow::focusAndShowErrorMessage(const QString *errorMsg) + */ + void focusAndShowErrorMessage(const QString &errorMsg); + signals: + void addresseesChanged(); + + protected: + AddressbookBase(); + KABC::AddressBook* addressBook; + KABC::Ticket *m_ticket; + }; + +} //NAMESPACE +#endif diff --git a/konversation/src/linkaddressbook/addresseeitem.cpp b/konversation/src/linkaddressbook/addresseeitem.cpp new file mode 100644 index 0000000..9c9c6b4 --- /dev/null +++ b/konversation/src/linkaddressbook/addresseeitem.cpp @@ -0,0 +1,63 @@ +/* + Copyright (c) 2001 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "addresseeitem.h" + +#include +#include +#include +#include + +#include +#include + + +AddresseeItem::AddresseeItem( QListView *parent, const KABC::Addressee &addressee) : +KListViewItem( parent ), +mAddressee( addressee ) +{ + //We can't save showphoto because we don't have a d pointer + KABC::Picture pic = mAddressee.photo(); + if(!pic.isIntern()) + pic = mAddressee.logo(); + if(pic.isIntern()) + { + //60 pixels seems okay.. kmail uses 60 btw + QPixmap qpixmap( pic.data().scaleWidth(60) ); + setPixmap( Photo,qpixmap ); + } + + setText( Name, addressee.realName() ); + setText( Email, addressee.preferredEmail() ); +} + +QString AddresseeItem::key( int column, bool ) const +{ + if (column == Email) + { + QString value = text(Email); + QRegExp emailRe("<\\S*>"); + int match = emailRe.search(value); + if (match > -1) + value = value.mid(match + 1, emailRe.matchedLength() - 2); + + return value.lower(); + } + + return text(column).lower(); +} diff --git a/konversation/src/linkaddressbook/addresseeitem.h b/konversation/src/linkaddressbook/addresseeitem.h new file mode 100644 index 0000000..2e2aec3 --- /dev/null +++ b/konversation/src/linkaddressbook/addresseeitem.h @@ -0,0 +1,66 @@ +/* + This file is part of libkabc. + Copyright (c) 2001 Cornelius Schumacher + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KABC_ADDRESSEEDIALOG_H +#define KABC_ADDRESSEEDIALOG_H + +#include + +#include +#include +#include + +#include + +/** + @short Special ListViewItem +*/ +class AddresseeItem : public KListViewItem +{ + public: + + /** + Type of column + @li @p Name - Name in Addressee + @li @p Email - Email in Addressee + */ + enum columns { Photo =0, Name = 1, Email = 2 }; + + /** + Constructor. + + @param parent The parent listview. + @param addressee The associated addressee. + */ + AddresseeItem( QListView *parent, const KABC::Addressee &addressee ); + + /** + Returns the addressee. + */ + KABC::Addressee addressee() const { return mAddressee; } + + /** + Method used by QListView to sort the items. + */ + virtual QString key( int column, bool ascending ) const; + + private: + KABC::Addressee mAddressee; +}; +#endif diff --git a/konversation/src/linkaddressbook/kimiface.h b/konversation/src/linkaddressbook/kimiface.h new file mode 100644 index 0000000..990f980 --- /dev/null +++ b/konversation/src/linkaddressbook/kimiface.h @@ -0,0 +1,191 @@ +/* + kimiface.h - KDE Instant Messenger DCOP Interface + + Copyright (c) 2004 Will Stephenson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KIMIFACE_H +#define KIMIFACE_H + +#include +#include +#include +#include + +/** + * Generic DCOP interface for KDE instant messenger applications + * Note one omission of this interface is the lack of control over the range of values used for protocols' names. + * @author Will Stephenson + */ +class KIMIface : virtual public DCOPObject +{ + K_DCOP + + k_dcop: + // ACCESSORS + // contact list + /** + * Obtain a list of IM-contactable entries in the KDE + * address book. + * @return a list of KABC uids. + */ + virtual QStringList allContacts() = 0; + /** + * Obtain a list of KDE address book entries who are + * currently reachable. + * @return a list of KABC uids who can receive a message, even if online. + */ + virtual QStringList reachableContacts() = 0; + /** + * Obtain a list of KDE address book entries who are + * currently online. + * @return a list of KABC uids who are online with unspecified presence. + */ + virtual QStringList onlineContacts() = 0; + /** + * Obtain a list of KDE address book entries who may + * receive file transfers. + * @return a list of KABC uids capable of file transfer. + */ + virtual QStringList fileTransferContacts() = 0; + + // individual + /** + * Confirm if a given KABC uid is known to KIMProxy + * @param uid the KABC uid you are interested in. + * @return whether one of the chat programs KIMProxy talks to knows of this KABC uid. + */ + virtual bool isPresent( const QString & uid ) = 0; + /** + * Obtain the IM app's idea of the contact's display name + * Useful if KABC lookups may be too slow + * @param uid KABC uid. + * @return The corresponding display name. + */ + virtual QString displayName( const QString & uid ) = 0; + /** + * Obtain the IM presence as a i18ned string for the specified addressee + * @param uid the KABC uid you want the presence for. + * @return the i18ned string describing presence. + */ + virtual QString presenceString( const QString & uid ) = 0; + /** + * Obtain the IM presence as a number (see KIMIface) for the specified addressee + * @param uid the KABC uid you want the presence for. + * @return a numeric representation of presence - currently one of 0 (Unknown), 1 (Offline), 2 (Connecting), 3 (Away), 4 (Online) + */ + virtual int presenceStatus( const QString & uid ) = 0; + /** + * Indicate if a given uid can receive files + * @param uid the KABC uid you are interested in. + * @return Whether the specified addressee can receive files. + */ + virtual bool canReceiveFiles( const QString & uid ) = 0; + /** + * Some media are unidirectional (eg, sending SMS via a web interface). + * @param uid the KABC uid you are interested in. + * @return Whether the specified addressee can respond. + */ + virtual bool canRespond( const QString & uid ) = 0; + /** + * Get the KABC uid corresponding to the supplied IM address + * Protocols should be + * @param contactId the protocol specific identifier for the contact, eg UIN for ICQ, screenname for AIM, nick for IRC. + * @param protocol the protocol, eg one of "AIMProtocol", "MSNProtocol", "ICQProtocol", + * @return a KABC uid or null if none found/ + */ + virtual QString locate( const QString & contactId, const QString & protocol ) = 0; + // metadata + /** + * Obtain the icon representing IM presence for the specified addressee + * @param uid the KABC uid you want the presence for. + * @return a pixmap representing the uid's presence. + */ + virtual QPixmap icon( const QString & uid ) = 0; + /** + * Get the supplied addressee's current context (home, work, or any). + * @param uid the KABC uid you want the context for. + * @return A QString describing the context, or null if not supported. + */ + virtual QString context( const QString & uid ) = 0; + // App capabilities + /** + * Discover what protocols the application supports + * @return the set of protocols that the application supports + */ + virtual QStringList protocols() = 0; + + // ACTORS + /** + * Send a single message to the specified addressee + * Any response will be handled by the IM client as a normal + * conversation. + * @param uid the KABC uid you want to chat with. + * @param message the message to send them. + */ + virtual void messageContact( const QString &uid, const QString& message ) = 0; + + /** + * Open a chat to a contact, and optionally set some initial text + */ + virtual void messageNewContact( const QString &contactId, const QString &protocol ) = 0; + + /** + * Start a chat session with the specified addressee + * @param uid the KABC uid you want to chat with. + */ + virtual void chatWithContact( const QString &uid ) = 0; + + /** + * Send the file to the contact + * @param uid the KABC uid you are sending to. + * @param sourceURL a KURL to send. + * @param altFileName an alternate filename describing the file + * @param fileSize file size in bytes + */ + virtual void sendFile(const QString &uid, const KURL &sourceURL, + const QString &altFileName = QString(), uint fileSize = 0) = 0; + + // MUTATORS + // Contact list + /** + * Add a contact to the contact list + * @param contactId the protocol specific identifier for the contact, eg UIN for ICQ, screenname for AIM, nick for IRC. + * @param protocol the protocol, eg one of "AIMProtocol", "MSNProtocol", "ICQProtocol", ... + * @return whether the add succeeded. False may signal already present, protocol not supported, or add operation not supported. + */ + virtual bool addContact( const QString &contactId, const QString &protocol ) = 0; + // SIGNALS + k_dcop_signals: + /** + * Indicates that a contact's presence has changed + * @param uid the contact whose presence changed. + * @param appId the dcop application id of the program the signal originates from. + * @param presence the new numeric presence @ref presenceStatus + */ + void contactPresenceChanged( QString uid, QCString appId, int presence ); +}; +#endif + +/* + * Local variables: + * c-indentation-style: k&r + * c-basic-offset: 8 + * indent-tabs-mode: t + * End: + */ +// vim: set noet ts=4 sts=4 sw=4: diff --git a/konversation/src/linkaddressbook/linkaddressbookui.cpp b/konversation/src/linkaddressbook/linkaddressbookui.cpp new file mode 100644 index 0000000..9347075 --- /dev/null +++ b/konversation/src/linkaddressbook/linkaddressbookui.cpp @@ -0,0 +1,191 @@ +/* + Kontact's Link IRC Nick to Addressbook contact Wizard + + This code was shamelessly stolen from kopete's add new contact wizard. + + Copyright (c) 2004 by John Tapsell + + Copyright (c) 2003 by Will Stephenson + Copyright (c) 2002 by Nick Betcher + Copyright (c) 2002 by Duncan Mac-Vicar Prett + +Kopete (c) 2002-2004 by the Kopete developers + +************************************************************************* +* * +* 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. * +* * +************************************************************************* +*/ + +#include "linkaddressbookui.h" +#include "addressbook.h" +#include "linkaddressbookui_base.h" +#include "addresseeitem.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +LinkAddressbookUI::LinkAddressbookUI( QWidget *parent, const char *name, const QString &ircnick, const QString &servername, const QString &servergroup, const QString &suggested_realname ) +: KDialogBase(Plain, i18n("Link IRC Nick to Addressbook Contact"), Ok|Cancel|Help, Ok, parent, name) +{ + QFrame* page = plainPage(); + QGridLayout* pageLayout = new QGridLayout(page, 1, 1, 0, 0); + m_mainWidget = new LinkAddressbookUI_Base(page); + pageLayout->addWidget(m_mainWidget, 0, 0); + + enableButtonOK(false); + setHelp("linkaddressbook"); + m_addressBook = Konversation::Addressbook::self()->getAddressBook(); + + // Addressee validation connections + connect( m_mainWidget->addAddresseeButton, SIGNAL( clicked() ), SLOT( slotAddAddresseeClicked() ) ); + connect( m_mainWidget->addresseeListView, SIGNAL( clicked(QListViewItem * ) ), + SLOT( slotAddresseeListClicked( QListViewItem * ) ) ); + connect( m_mainWidget->addresseeListView, SIGNAL( selectionChanged( QListViewItem * ) ), + SLOT( slotAddresseeListClicked( QListViewItem * ) ) ); + connect( m_mainWidget->addresseeListView, SIGNAL( spacePressed( QListViewItem * ) ), + SLOT( slotAddresseeListClicked( QListViewItem * ) ) ); + + connect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( slotLoadAddressees() ) ); + connect( Konversation::Addressbook::self(), SIGNAL(addresseesChanged()), this, SLOT(slotLoadAddressees())); + + //We should add a clear KAction here. But we can't really do that with a designer file :\ this sucks + + m_ircnick = ircnick; + m_lower_ircnick = m_ircnick.lower(); + m_servername = servername; + m_servergroup = servergroup; + m_suggested_realname = suggested_realname; + + m_mainWidget->addresseeListView->setColumnText(2, SmallIconSet("email"), i18n("Email") ); + + if(m_suggested_realname.isEmpty()) m_suggested_realname = suggested_realname; + Q_ASSERT(!ircnick.isEmpty()); + m_mainWidget->kListViewSearchLine->setListView(m_mainWidget->addresseeListView); + slotLoadAddressees(); + + m_mainWidget->addresseeListView->setColumnWidthMode(0, QListView::Manual); + //Photo is 60, and it's nice to have a small gap, imho + m_mainWidget->addresseeListView->setColumnWidth(0, 63); + +} + +LinkAddressbookUI::~LinkAddressbookUI() +{ +} + +/** Read in contacts from addressbook, and select the contact that is for our nick. */ +void LinkAddressbookUI::slotLoadAddressees() +{ + m_mainWidget->addresseeListView->clear(); + + QString realname; + int num_contacts_with_nick=0; //There shouldn't be more than 1 contact with this irc nick. Warn the user if there is. + + KABC::AddressBook::Iterator it; + for( it = m_addressBook->begin(); it != m_addressBook->end(); ++it ) + if(Konversation::Addressbook::self()->hasNick(*it, m_lower_ircnick, m_servername, m_servergroup)) + { + realname = (*it).realName(); + num_contacts_with_nick++; + (new AddresseeItem( m_mainWidget->addresseeListView, (*it) ))->setSelected(true); + } else + /*AddresseeItem *item =*/ new AddresseeItem( m_mainWidget->addresseeListView, (*it)); + + if(num_contacts_with_nick == 0) + m_mainWidget->lblHeader->setText(i18n("Choose the person who '%1' is.").arg(m_ircnick)); + else if(num_contacts_with_nick == 1 && realname.isEmpty()) + m_mainWidget->lblHeader->setText(i18n("Currently '%1' is associated with a contact.").arg(m_ircnick)); + else if(num_contacts_with_nick == 1 && !realname.isEmpty()) + m_mainWidget->lblHeader->setText(i18n("Currently '%1' is associated with contact '%2'.").arg(m_ircnick).arg(realname)); + else + m_mainWidget->lblHeader->setText(i18n("Warning: '%1' is currently being listed as belonging to multiple contacts. Please select the correct contact.").arg(m_ircnick)); + +} + +void LinkAddressbookUI::slotAddAddresseeClicked() +{ + // Pop up add addressee dialog + if(!Konversation::Addressbook::self()->getAndCheckTicket()) return; + QString addresseeName = KInputDialog::getText( i18n( "New Address Book Entry" ), + i18n( "Name the new entry:" ), + m_suggested_realname, 0, this ); + + if ( !addresseeName.isEmpty() ) + { + KABC::Addressee addr; + addr.setNameFromString( addresseeName ); + m_addressBook->insertAddressee(addr); + Konversation::Addressbook::self()->saveTicket(); + slotLoadAddressees(); + } + else + { + Konversation::Addressbook::self()->releaseTicket(); + } +} + +void LinkAddressbookUI::slotAddresseeListClicked( QListViewItem *addressee ) +{ + // enable ok if a valid addressee is selected + enableButtonOK(addressee ? addressee->isSelected() : false); +} + +void LinkAddressbookUI::slotOk() +{ + //// set the KABC uid in the metacontact + AddresseeItem *item = 0L; + item = static_cast( m_mainWidget->addresseeListView->selectedItem() ); + + KABC::Addressee addr; + if ( item ) + { + + addr = item->addressee(); + if(!Konversation::Addressbook::self()->getAndCheckTicket()) + { + return; + } + Konversation::Addressbook::self()->associateNickAndUnassociateFromEveryoneElse(addr, m_ircnick, m_servername, m_servergroup); + if(!Konversation::Addressbook::self()->saveTicket()) + { + return; + } + } + disconnect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( slotLoadAddressees() ) ); + deleteLater(); + accept(); +} + +void LinkAddressbookUI::slotCancel() +{ + disconnect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( slotLoadAddressees() ) ); + deleteLater(); + reject(); +} + +#include "linkaddressbookui.moc" + +// vim: set noet ts=4 sts=4 sw=4: diff --git a/konversation/src/linkaddressbook/linkaddressbookui.h b/konversation/src/linkaddressbook/linkaddressbookui.h new file mode 100644 index 0000000..87ebd52 --- /dev/null +++ b/konversation/src/linkaddressbook/linkaddressbookui.h @@ -0,0 +1,68 @@ +/* + linkaddressbookwizard.h - Kontact's Link IRC Nick to Addressbook contact Wizard + + This code was shamelessly stolen from kopete's add new contact wizard. + + Copyright (c) 2004 by John Tapsell + + Copyright (c) 2003 by Will Stephenson + Copyright (c) 2002 by Nick Betcher + Copyright (c) 2002 by Duncan Mac-Vicar Prett + +Kopete (c) 2002-2004 by the Kopete developers + +************************************************************************* +* * +* 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. * +* * +************************************************************************* +*/ + +#ifndef LINKADDRESSBOOKUI_H +#define LINKADDRESSBOOKUI_H + +#include +#include +#include + +#include +#include +#include + +class QCheckListItem; +class LinkAddressbookUI_Base; + +class LinkAddressbookUI : public KDialogBase +{ + Q_OBJECT + + public: + LinkAddressbookUI( QWidget *parent, const char *name, const QString &ircnick, const QString &servername, const QString &servergroup, const QString &suggested_realname); + ~LinkAddressbookUI(); + + private: + KABC::AddressBook* m_addressBook; + QString m_ircnick; + QString m_lower_ircnick; //Same as above, but in lower case, for comparisons. + QString m_servername; + QString m_servergroup; + QString m_suggested_realname; + LinkAddressbookUI_Base* m_mainWidget; + + protected slots: + virtual void slotOk(); + virtual void slotCancel(); + void slotAddAddresseeClicked(); + void slotAddresseeListClicked( QListViewItem *addressee ); + /** + * Utility function, populates the addressee list + */ + void slotLoadAddressees(); + +}; +#endif + +// vim: set noet ts=4 sts=4 sw=4: diff --git a/konversation/src/linkaddressbook/linkaddressbookui_base.ui b/konversation/src/linkaddressbook/linkaddressbookui_base.ui new file mode 100644 index 0000000..6e82416 --- /dev/null +++ b/konversation/src/linkaddressbook/linkaddressbookui_base.ui @@ -0,0 +1,174 @@ + +LinkAddressbookUI_Base + + + LinkAddressbookUI_Base + + + + 0 + 0 + 596 + 572 + + + + + 5 + 1 + 0 + 0 + + + + + unnamed + + + 0 + + + + spacer11 + + + Horizontal + + + Expanding + + + + 405 + 20 + + + + + + addAddresseeButton + + + Create New &Entry... + + + Create a new entry in your address book + + + + + lblHeader + + + + 7 + 4 + 0 + 0 + + + + + + + Photo + + + false + + + true + + + + + Name + + + true + + + true + + + + + Email + + + true + + + true + + + + addresseeListView + + + + 7 + 7 + 0 + 10 + + + + true + + + LastColumn + + + Select the contact you want to communicate with via Instant Messaging + + + + + layout1 + + + + unnamed + + + + lblSearch + + + + 1 + 5 + 0 + 0 + + + + S&earch: + + + kListViewSearchLine + + + + + kListViewSearchLine + + + + + + + + + + + + kactivelabel.h + klistview.h + klistviewsearchline.h + + + klistviewsearchline.h + + diff --git a/konversation/src/linkaddressbook/nicklisttooltip.cpp b/konversation/src/linkaddressbook/nicklisttooltip.cpp new file mode 100644 index 0000000..c2fcde7 --- /dev/null +++ b/konversation/src/linkaddressbook/nicklisttooltip.cpp @@ -0,0 +1,68 @@ +/* + 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. +*/ + +/* + The class that controls what the tooltip looks like when you hover over a person in the nicklistview. This is used to show contact information about the person from the addressbook. + begin: Sun 25 July 2004 + copyright: (C) 2004 by John Tapsell + email: john@geola.co.uk +*/ + +#include "nicklisttooltip.h" +#include "../nick.h" +#include "../nicklistview.h" +#include "../nickinfo.h" +#include "../common.h" + +#include +#include +#include + + +class NickListView; + +namespace Konversation +{ + KonversationNickListViewToolTip::KonversationNickListViewToolTip(QWidget *parent, NickListView *lv) : QToolTip(parent) + { + m_listView = lv; + } + + KonversationNickListViewToolTip::~KonversationNickListViewToolTip() + { + } + + void KonversationNickListViewToolTip::maybeTip( const QPoint &pos ) + { + if( !parentWidget() || !m_listView ) + return; + + QListViewItem *item = m_listView->itemAt( pos ); + + if( !item ) + return; + + Nick *nick = dynamic_cast( item ); + + if(! nick ) + return; + + QString toolTip; + QRect itemRect = m_listView->itemRect( item ); + + uint leftMargin = m_listView->treeStepSize() * + ( item->depth() + ( m_listView->rootIsDecorated() ? 1 : 0 ) ) + + m_listView->itemMargin(); + uint xAdjust = itemRect.left() + leftMargin; + uint yAdjust = itemRect.top(); + QPoint relativePos( pos.x() - xAdjust, pos.y() - yAdjust ); + toolTip = Konversation::removeIrcMarkup(nick->getChannelNick()->tooltip()); + if(!toolTip.isEmpty()) + tip(itemRect, toolTip); + } + +} // namespace Konversation diff --git a/konversation/src/linkaddressbook/nicklisttooltip.h b/konversation/src/linkaddressbook/nicklisttooltip.h new file mode 100644 index 0000000..068850c --- /dev/null +++ b/konversation/src/linkaddressbook/nicklisttooltip.h @@ -0,0 +1,45 @@ +/* + 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. +*/ + +/* + nicklisttooltip.h - The class that controls what the tooltip looks like when you hover over a person in the nicklistview. This is used to show contact information about the person from the addressbook. + begin: Sun 25 July 2004 + copyright: (C) 2004 by John Tapsell + email: john@geola.co.uk +*/ + +#ifndef KONVERSATIONNICKLISTTOOLTIP_H +#define KONVERSATIONNICKLISTTOOLTIP_H + +#include "addressbook.h" + +#include +#include +#include +#include + +#include + + +class NickListView; + +namespace Konversation +{ + + class KonversationNickListViewToolTip : public QToolTip + { + public: + KonversationNickListViewToolTip(QWidget *parent, NickListView *lv); + virtual ~KonversationNickListViewToolTip(); + + void maybeTip( const QPoint &pos ); + + private: + NickListView *m_listView; + }; +} +#endif diff --git a/konversation/src/linkaddressbook/nicksonlinetooltip.cpp b/konversation/src/linkaddressbook/nicksonlinetooltip.cpp new file mode 100644 index 0000000..b89cab6 --- /dev/null +++ b/konversation/src/linkaddressbook/nicksonlinetooltip.cpp @@ -0,0 +1,67 @@ +/* + 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. +*/ + +/* + The class that controls what the tooltip looks like when you hover over a person in the nicklistview. This is used to show contact information about the person from the addressbook. + begin: Sun 25 July 2004 + copyright: (C) 2004 by John Tapsell + email: john@geola.co.uk +*/ + + +#include "nicklisttooltip.h" +#include "../nick.h" +#include "../nicklistview.h" +#include "../nickinfo.h" +#include "../nicksonline.h" + +#include +#include +#include +#include + + +class NickListView; + +namespace Konversation +{ + KonversationNicksOnlineToolTip::KonversationNicksOnlineToolTip(QWidget *parent, NicksOnline *nicksOnline) : QToolTip(parent) + { + m_nicksOnline = nicksOnline; + } + + KonversationNicksOnlineToolTip::~KonversationNicksOnlineToolTip() + { + } + + void KonversationNicksOnlineToolTip::maybeTip( const QPoint &pos ) + { + if( !parentWidget() || !m_nicksOnline || !m_nicksOnline->getNickListView() ) + return; + KListView *m_listView = m_nicksOnline->getNickListView(); + QListViewItem *item = m_listView->itemAt( pos ); + if( !item ) + return; + NickInfoPtr nickInfo = m_nicksOnline->getNickInfo(item); + + if(!nickInfo ) + return; + QString toolTip; + QRect itemRect = m_listView->itemRect( item ); + + uint leftMargin = m_listView->treeStepSize() * + ( item->depth() + ( m_listView->rootIsDecorated() ? 1 : 0 ) ) + + m_listView->itemMargin(); + uint xAdjust = itemRect.left() + leftMargin; + uint yAdjust = itemRect.top(); + QPoint relativePos( pos.x() - xAdjust, pos.y() - yAdjust ); + toolTip = nickInfo->tooltip(); + if(!toolTip.isEmpty()) + tip(itemRect, toolTip); + } + +} // namespace Konversation diff --git a/konversation/src/linkaddressbook/nicksonlinetooltip.h b/konversation/src/linkaddressbook/nicksonlinetooltip.h new file mode 100644 index 0000000..79f0888 --- /dev/null +++ b/konversation/src/linkaddressbook/nicksonlinetooltip.h @@ -0,0 +1,45 @@ +/* + 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. +*/ + +/* + nicklisttooltip.h - The class that controls what the tooltip looks like when you hover over a person in the nicklistview. This is used to show contact information about the person from the addressbook. + begin: Sun 25 July 2004 + copyright: (C) 2004 by John Tapsell + email: john@geola.co.uk +*/ + +#ifndef KONVERSATIONNICKSONLINETOOLTIP_H +#define KONVERSATIONNICKSONLINETOOLTIP_H + +#include "addressbook.h" + +#include +#include +#include +#include + +#include + + +class NicksOnline; + +namespace Konversation +{ + + class KonversationNicksOnlineToolTip : public QToolTip + { + public: + KonversationNicksOnlineToolTip(QWidget *parent, NicksOnline *nicksOnline); + virtual ~KonversationNicksOnlineToolTip(); + + void maybeTip( const QPoint &pos ); + + private: + NicksOnline *m_nicksOnline; + }; +} +#endif diff --git a/konversation/src/log_preferences.ui b/konversation/src/log_preferences.ui new file mode 100644 index 0000000..3af0047 --- /dev/null +++ b/konversation/src/log_preferences.ui @@ -0,0 +1,116 @@ + +Log_Config +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. + + + Log_Config + + + + 0 + 0 + 528 + 310 + + + + + unnamed + + + 0 + + + + kcfg_Log + + + &Enable Logging + + + true + + + + unnamed + + + + kcfg_LowerLog + + + Enable &lower case logfile names + + + + + kcfg_AddHostnameToLog + + + &Append hostname to logfile names + + + + + textLabel1 + + + Logfile &path: + + + kcfg_LogfilePath + + + + + kcfg_LogfilePath + + + + 7 + 5 + 0 + 0 + + + + 26 + + + + + + + spacer1 + + + Vertical + + + Expanding + + + + 21 + 10 + + + + + + + kcfg_LowerLog + kcfg_AddHostnameToLog + kcfg_LogfilePath + + + + + kurlrequester.h + klineedit.h + kpushbutton.h + + diff --git a/konversation/src/logfilereader.cpp b/konversation/src/logfilereader.cpp new file mode 100644 index 0000000..22357f4 --- /dev/null +++ b/konversation/src/logfilereader.cpp @@ -0,0 +1,187 @@ +/* + 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. +*/ + +/* + Shows the content of a log file + begin: Fri Dec 5 2003 + copyright: (C) 2003 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include "logfilereader.h" +#include "konversationapplication.h" +#include "ircview.h" +#include "ircviewbox.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +LogfileReader::LogfileReader(QWidget* parent, const QString& log) : ChatWindow(parent) +{ + setType(ChatWindow::LogFileReader); + + fileName = log; + QDockArea* toolBarDock = new QDockArea(Qt::Horizontal,QDockArea::Normal,this,"logfile_toolbar_dock"); + toolBar = new KToolBar(toolBarDock,"logfile_toolbar",true,true); + + toolBar->insertButton("filesaveas",0,SIGNAL(clicked()),this,SLOT(saveLog()),true,i18n("Save As...")); + + new QLabel(i18n("Show last:"),toolBar,"logfile_size_label"); + sizeSpin = new QSpinBox(10,1000,10,toolBar,"logfile_size_spinbox"); + QWhatsThis::add(sizeSpin, i18n("Use this box to set the maximum size of the log file. This setting does not take effect until you restart Konversation. Each log file may have a separate setting.")); + sizeSpin->setValue(Preferences::logfileBufferSize()); + sizeSpin->setSuffix(i18n(" KB")); + sizeSpin->installEventFilter(this); + + toolBar->insertButton("reload",0,SIGNAL(clicked()),this,SLOT(updateView()),true,i18n("Reload")); + toolBar->insertButton("editdelete",0,SIGNAL(clicked()),this,SLOT(clearLog()),true,i18n("Clear Logfile")); + + IRCViewBox* ircBox = new IRCViewBox(this, 0); + setTextView(ircBox->ircView()); + QWhatsThis::add(getTextView(), i18n("The messages in the log file are displayed here. The oldest messages are at the top and the most recent are at the bottom.")); + + updateView(); + resize(Preferences::logfileReaderSize()); + ircBox->ircView()->setFocusPolicy(QWidget::StrongFocus); + setFocusPolicy(QWidget::StrongFocus); + setFocusProxy(ircBox->ircView()); + + connect(getTextView(), SIGNAL(gotFocus()), getTextView(), SLOT(setFocus())); +} + +LogfileReader::~LogfileReader() +{ + Preferences::setLogfileReaderSize(size()); + Preferences::setLogfileBufferSize(sizeSpin->value()); + + delete toolBar; +} + +bool LogfileReader::eventFilter(QObject* /* watched */, QEvent* e) +{ + if (e->type() == QEvent::KeyPress) + { + QKeyEvent* ke = static_cast(e); + + if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter) + { + updateView(); + + return true; + } + else + return false; + } + + return false; +} + +void LogfileReader::updateView() +{ + // get maximum size of logfile to display + unsigned long pos=sizeSpin->value()*1024; + getTextView()->clear(); + + QFile file(fileName); + + if(file.open(IO_ReadOnly)) + { + QTextStream stream(&file); + stream.setEncoding(QTextStream::UnicodeUTF8); + + // Set file pointer to bytes from the end + if(stream.device()->size()>pos) + stream.device()->at(stream.device()->size()-pos); + // Skip first line, since it may be incomplete + stream.readLine(); + QString str; + + while(!stream.eof()) + { + str = QStyleSheet::escape(stream.readLine()); + getTextView()->appendRaw(str, true); + } + + stream.unsetDevice(); + file.close(); + } +} + +void LogfileReader::clearLog() +{ + if(KMessageBox::warningContinueCancel(this, + i18n("Do you really want to permanently discard all log information of this file?"), + i18n("Clear Logfile"), + KStdGuiItem::del(), + "ClearLogfileQuestion")==KMessageBox::Continue) + { + QFile::remove(fileName); + updateView(); + } +} + +void LogfileReader::saveLog() +{ + KMessageBox::information(this, + i18n("Note: By saving the logfile you will save all data in the file, not only the part you can see in this viewer."), + i18n("Save Logfile"), + "SaveLogfileNote"); + + QString destination=KFileDialog::getSaveFileName(fileName, + QString(), + this, + i18n("Choose Destination Folder")); + if(!destination.isEmpty()) + { + // replace # with %25 to make it URL conforming + KIO::Job* job=KIO::copy(KURL(fileName.replace("#","%23")), + KURL(destination), + true); + + connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(copyResult(KIO::Job*))); + } +} + +void LogfileReader::copyResult(KIO::Job* job) +{ + if(job->error()) job->showErrorDialog(this); + + job->deleteLater(); +} + +void LogfileReader::closeLog() +{ + delete this; +} + +void LogfileReader::childAdjustFocus() +{ + getTextView()->setFocus(); +} + +int LogfileReader::margin() { return KDialog::marginHint(); } +int LogfileReader::spacing() { return KDialog::spacingHint(); } +bool LogfileReader::searchView() { return true; } + +#include "logfilereader.moc" diff --git a/konversation/src/logfilereader.h b/konversation/src/logfilereader.h new file mode 100644 index 0000000..0327c74 --- /dev/null +++ b/konversation/src/logfilereader.h @@ -0,0 +1,59 @@ +/* + 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. +*/ + +/* + Shows the content of a log file + begin: Fri Dec 5 2003 + copyright: (C) 2003 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#ifndef LOGFILEREADER_H +#define LOGFILEREADER_H + +#include "chatwindow.h" + +#include + + +class KToolBar; +class QSpinBox; + +class LogfileReader : public ChatWindow +{ + Q_OBJECT + + public: + LogfileReader(QWidget* parent, const QString& log); + ~LogfileReader(); + + virtual bool closeYourself() { closeLog(); return true; } + virtual bool searchView(); + + virtual bool eventFilter(QObject* watched, QEvent* e); + + + protected slots: + void updateView(); + void clearLog(); + void saveLog(); + void closeLog(); + void copyResult(KIO::Job* job); + + + protected: + int margin(); + int spacing(); + + /** Called from ChatWindow adjustFocus */ + virtual void childAdjustFocus(); + + KToolBar* toolBar; + QSpinBox* sizeSpin; + QString fileName; +}; +#endif diff --git a/konversation/src/main.cpp b/konversation/src/main.cpp new file mode 100644 index 0000000..2deede7 --- /dev/null +++ b/konversation/src/main.cpp @@ -0,0 +1,103 @@ +/* + 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. +*/ + +/* + Where it all began ... + begin: Die Jan 15 05:59:05 CET 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "konversationapplication.h" +#include "version.h" +#include "commit.h" + +/* + Don't use i18n() here, use I18N_NOOP() instead! + i18n() will only work as soon as a kapplication object was made. +*/ + +static const char* shortDescription=I18N_NOOP("A user friendly IRC client"); + +static const KCmdLineOptions options[] = +{ + { "+[url]", I18N_NOOP("irc:// URL or server hostname"), 0 }, + { "server ", I18N_NOOP("Server to connect"), 0 }, + { "port ", I18N_NOOP("Port to use"), "6667"}, + { "channel ", I18N_NOOP("Channel to join after connection"), ""}, + { "nick ", I18N_NOOP("Nickname to use"),""}, + { "password ", I18N_NOOP("Password for connection"),""}, + { "ssl", I18N_NOOP("Use SSL for connection"),"false"}, + KCmdLineLastOption +}; + +int main(int argc, char* argv[]) +{ + KAboutData aboutData("konversation", + I18N_NOOP("Konversation"), + KONVI_VERSION, + shortDescription, + KAboutData::License_GPL, + I18N_NOOP("(C) 2002-2008 by the Konversation team"), + I18N_NOOP("Konversation is a client for the Internet Relay Chat (IRC) protocol.\n" + "Meet friends on the net, make new acquaintances and lose yourself in\n" + "talk about your favorite subject."), + "http://konversation.kde.org/"); + + aboutData.addAuthor("Dario Abatianni",I18N_NOOP("Original Author, Project Founder"),"eisfuchs@tigress.com"); + aboutData.addAuthor("Peter Simonsson",I18N_NOOP("Maintainer"),"psn@linux.se"); + aboutData.addAuthor("Eike Hein",I18N_NOOP("Maintainer, Release Manager, User interface, Protocol handling"),"hein@kde.org"); + aboutData.addAuthor("Shintaro Matsuoka",I18N_NOOP("DCC, Encoding handling, OSD positioning"),"shin@shoegazed.org"); + aboutData.addAuthor("Eli MacKenzie",I18N_NOOP("Protocol handling, Input line"),"argonel@gmail.com"); + aboutData.addAuthor("İsmail Dönmez",I18N_NOOP("Blowfish, SSL support, KNetwork port, Colored nicks, Nicklist themes"),"ismail@kde.org"); + aboutData.addAuthor("John Tapsell",I18N_NOOP("Refactoring, KAddressBook/Kontact integration"), "john@geola.co.uk"); + + aboutData.addCredit("Olivier Bédard",I18N_NOOP("Website hosting")); + aboutData.addCredit("Jędrzej Lisowski",I18N_NOOP("Website maintenance"),"yesoos@gmail.com"); + aboutData.addCredit("Christian Muehlhaeuser",I18N_NOOP("Multiple modes extension, Close widget placement, OSD functionality"),"chris@chris.de"); + aboutData.addCredit("Gary Cramblitt",I18N_NOOP("Documentation, Watched nicks online improvements, Custom web browser extension"),"garycramblitt@comcast.net"); + aboutData.addCredit("Matthias Gierlings",I18N_NOOP("Color configurator, Highlight dialog"),"gismore@users.sourceforge.net"); + aboutData.addCredit("Alex Zepeda",I18N_NOOP("DCOP interface"),"garbanzo@hooked.net"); + aboutData.addCredit("Stanislav Karchebny",I18N_NOOP("Non-Latin1-Encodings"),"berkus@users.sourceforge.net"); + aboutData.addCredit("Mickael Marchand",I18N_NOOP("Konsole part view"),"marchand@kde.org"); + aboutData.addCredit("Michael Goettsche",I18N_NOOP("Quick connect, Ported new OSD, other features and bugfixes"),"michael.goettsche@kdemail.net"); + aboutData.addCredit("Benjamin Meyer",I18N_NOOP("A Handful of fixes and code cleanup"),"ben+konversation@meyerhome.net"); + aboutData.addCredit("Jakub Stachowski",I18N_NOOP("Drag&Drop improvements"),"qbast@go2.pl"); + aboutData.addCredit("Sebastian Sariego",I18N_NOOP("Artwork"),"segfault@kde.cl"); + aboutData.addCredit("Renchi Raju",I18N_NOOP("Firefox style searchbar")); + aboutData.addCredit("Michael Kreitzer",I18N_NOOP("Raw modes, Tab grouping per server, Ban list"),"mrgrim@gr1m.org"); + aboutData.addCredit("Frauke Oster",I18N_NOOP("System tray patch"),"frauke@frsv.de"); + aboutData.addCredit("Lucijan Busch",I18N_NOOP("Bug fixes"),"lucijan@kde.org"); + aboutData.addCredit("Sascha Cunz",I18N_NOOP("Extended user modes patch"),"mail@sacu.de"); + aboutData.addCredit("Steve Wollkind",I18N_NOOP("Close visible tab with shortcut patch"),"steve@njord.org"); + aboutData.addCredit("Thomas Nagy",I18N_NOOP("Cycle tabs with mouse scroll wheel"),"thomas.nagy@eleve.emn.fr"); + aboutData.addCredit("Tobias Olry",I18N_NOOP("Channel ownership mode patch"),"tobias.olry@web.de"); + aboutData.addCredit("Ruud Nabben",I18N_NOOP("Option to enable IRC color filtering"),"r.nabben@gawab.com"); + aboutData.addCredit("Lothar Braun",I18N_NOOP("Bug fixes"),"mail@lobraun.de"); + aboutData.addCredit("Ivor Hewitt",I18N_NOOP("Bug fixes, OSD work, clearing topics"),"ivor@ivor.org"); + aboutData.addCredit("Emil Obermayr",I18N_NOOP("Sysinfo script"),"nobs@tigress.com"); + aboutData.addCredit("Stanislav Nikolov",I18N_NOOP("Bug fixes"),"valsinats@gmail.com"); + aboutData.addCredit("Juan Carlos Torres",I18N_NOOP("Auto-join context menu"),"carlosdgtorres@gmail.com"); + + KCmdLineArgs::init(argc, argv, &aboutData); + KCmdLineArgs::addCmdLineOptions(options); + KApplication::addCmdLineOptions(); + + if (!KUniqueApplication::start()) return 0; + + KonversationApplication app; + + return app.exec(); +} diff --git a/konversation/src/modebutton.cpp b/konversation/src/modebutton.cpp new file mode 100644 index 0000000..445db55 --- /dev/null +++ b/konversation/src/modebutton.cpp @@ -0,0 +1,44 @@ +/* + 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. +*/ + +/* + begin: Wed Feb 6 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include "modebutton.h" + + +ModeButton::ModeButton(const QString& label,QWidget* parent,int newId) : +QPushButton::QPushButton(label,parent) +{ + id=newId; + on=false; + setToggleButton(true); + connect(this,SIGNAL (clicked()),this,SLOT (wasClicked()) ); +} + +ModeButton::~ModeButton() +{ +} + +void ModeButton::setOn(bool state) +{ + on=state; + QPushButton::setOn(state); +} + +void ModeButton::wasClicked() +{ + emit clicked(id,!on); + // Keep button in old state, since we don't know if mode change will + // eventually work. If we aren't channel operator, it won't. + setOn(on); +} + +#include "modebutton.moc" diff --git a/konversation/src/modebutton.h b/konversation/src/modebutton.h new file mode 100644 index 0000000..e8895d6 --- /dev/null +++ b/konversation/src/modebutton.h @@ -0,0 +1,40 @@ +/* + 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. +*/ + +/* + begin: Wed Feb 6 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#ifndef MODEBUTTON_H +#define MODEBUTTON_H + +#include + + +class ModeButton : public QPushButton +{ + Q_OBJECT + + public: + ModeButton(const QString& label,QWidget* parent,int id); + ~ModeButton(); + + void setOn(bool state); + + signals: + void clicked(int id,bool on); + + public slots: + void wasClicked(); + + protected: + int id; + bool on; +}; +#endif diff --git a/konversation/src/multilineedit.cpp b/konversation/src/multilineedit.cpp new file mode 100644 index 0000000..19e1eef --- /dev/null +++ b/konversation/src/multilineedit.cpp @@ -0,0 +1,79 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni +*/ + +#include "multilineedit.h" +#include "multilinetextedit.h" +#include "konversationapplication.h" + +#include + +#include + + +QString MultilineEdit::returnText; // static + +MultilineEdit::MultilineEdit(QWidget* parent, const QString& text) : +KDialogBase(parent,"multiline_edit_dialog",true,i18n("Edit Multiline Paste"), +KDialogBase::User1 | KDialogBase::Ok | KDialogBase::Cancel,KDialogBase::Ok,true, +KGuiItem(i18n("Add &Quotation Indicators"))) +{ + // Create the top level widget + QWidget* page=new QWidget(this); + setMainWidget(page); + // Add the layout to the widget + QVBoxLayout* dialogLayout=new QVBoxLayout(page); + dialogLayout->setSpacing(spacingHint()); + // add the text editor + textEditor=new MultilineTextEdit(page,"multiline_text_editor"); + textEditor->setTextFormat(PlainText); + textEditor->setText(text); + returnText=text; + + dialogLayout->addWidget(textEditor); + + setInitialSize(Preferences::multilineEditSize()); + show(); +} + +MultilineEdit::~MultilineEdit() +{ + Preferences::setMultilineEditSize(size()); +} + +void MultilineEdit::slotCancel() +{ + returnText=QString(); + KDialogBase::slotCancel(); +} + +void MultilineEdit::slotOk() +{ + returnText=textEditor->text(); + KDialogBase::slotOk(); +} + +void MultilineEdit::slotUser1() +{ + QStringList lines=QStringList::split("\n",textEditor->text(),true); + for( QStringList::iterator it=lines.begin() ; it!=lines.end() ; ++it ) + (*it) = "> " + (*it); + textEditor->setText(lines.join("\n")); +} + +QString MultilineEdit::edit(QWidget* parent, const QString& text) +{ + MultilineEdit dlg(parent,text); + dlg.exec(); + + return returnText; +} + +#include "multilineedit.moc" diff --git a/konversation/src/multilineedit.h b/konversation/src/multilineedit.h new file mode 100644 index 0000000..db86cc0 --- /dev/null +++ b/konversation/src/multilineedit.h @@ -0,0 +1,40 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni +*/ + +#ifndef MULTILINEEDIT_H +#define MULTILINEEDIT_H + +#include + + +class QWidget; +class MultilineTextEdit; + +class MultilineEdit : public KDialogBase +{ + Q_OBJECT + + public: + MultilineEdit(QWidget* parent, const QString& text); + ~MultilineEdit(); + + static QString edit(QWidget* parent, const QString& text); + + protected slots: + void slotOk(); + void slotCancel(); + void slotUser1(); + + protected: + MultilineTextEdit* textEditor; + static QString returnText; +}; +#endif diff --git a/konversation/src/multilinetextedit.cpp b/konversation/src/multilinetextedit.cpp new file mode 100644 index 0000000..d5f7869 --- /dev/null +++ b/konversation/src/multilinetextedit.cpp @@ -0,0 +1,175 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni +*/ + +#include "multilinetextedit.h" + +#include +#include + +#include + + +MultilineTextEdit::MultilineTextEdit(QWidget* parent,const char* name) : QTextEdit(parent,name) +{ + // make sure, our whitespace highlighting gets called whenever needed + connect(this,SIGNAL(textChanged()),this,SLOT(drawWhitespaces())); + connect(this,SIGNAL(cursorPositionChanged(int,int)),this,SLOT(cursorChanged(int,int))); +} + +MultilineTextEdit::~MultilineTextEdit() +{ +} + +void MultilineTextEdit::drawContents(QPainter* p,int clipx,int clipy,int clipw,int cliph) +{ + // redraw text + QTextEdit::drawContents(p,clipx,clipy,clipw,cliph); + // overlay whitespace markup + drawWhitespaces(); +} + +void MultilineTextEdit::drawWhitespaces() +{ + // prepare a rectangle to store the width of the whitespace found + QRect space; + // get the painter for the text area + QPainter pa(viewport()); + + // get a sane color + QColor col=colorGroup().link(); + // and a brush of the same color + QBrush fillBrush(col); + // use it for line drawing + pa.setPen(col); + // and for filling + pa.setBrush(fillBrush); + + // prepare the carriage return coordinates array + QPointArray cr(4); + // and the tabulator arrow coordinate array + QPointArray tab(7); + + // whitespace expression + QRegExp regex("\\s"); + + // line buffer + QString line; + + int x,y,pos,paragraph; + // start looking in every paragraph + for(paragraph=0;paragraph paragraphs() || + index < 0 || index > paragraphLength(para) ) + return QRect(); //invalid rectangle + + const QFontMetrics& fm = fontMetrics(); + const QString& paratext = text(para); + + // Find index of the first character on the same line as parameter + // 'index' using binary search. Very fast, even for long texts. + int linestart = 0; + int indexline = lineOfChar( para, index ); + if ( indexline > 0 ) + { + int min = 0, max = index; + int i = (min + max)/2; + int iline = lineOfChar( para, i ); + while ( iline != indexline-1 || + lineOfChar( para, i+1 ) != indexline ) + { + Q_ASSERT( min != max && min != i && max != i ); + if ( iline < indexline ) + min = i; + else + max = i; + i = (min + max)/2; + iline = lineOfChar( para, i ); + } + linestart = i+1; + } + Q_ASSERT( linestart >= 0 ); + + int linewidth = fm.size(ExpandTabs, paratext.mid( linestart, index-linestart )).width(); + int linewidth2 = fm.size(ExpandTabs, paratext.mid( linestart, index-linestart+1 )).width(); + + // FIXME as soon as it's possible to ask real margins from QTextEdit: + const int left_margin = 4; + // const int top_margin = 4; + + QPainter painter( viewport()); + const QRect& linerect = paragraphRect(para); + + return QRect( + contentsToViewport( QPoint( + left_margin + linerect.left() + linewidth , + /*top_margin + */linerect.top() + indexline * fm.lineSpacing() + fm.leading())), + QSize( + linewidth2-linewidth, + fm.lineSpacing() + )); +} + +#include "multilinetextedit.moc" diff --git a/konversation/src/multilinetextedit.h b/konversation/src/multilinetextedit.h new file mode 100644 index 0000000..e0f71aa --- /dev/null +++ b/konversation/src/multilinetextedit.h @@ -0,0 +1,41 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni +*/ + +#ifndef MULTILINETEXTEDIT_H +#define MULTILINETEXTEDIT_H + +#include + + +class QPaintEvent; +class QWheelEvent; + +class MultilineTextEdit : public QTextEdit +{ + Q_OBJECT + + public: + explicit MultilineTextEdit(QWidget* parent=0,const char* name=0); + ~MultilineTextEdit(); + + protected slots: + void drawWhitespaces(); + void cursorChanged(int,int); + + protected: + // reimplemented + virtual void drawContents(QPainter* p,int clipx,int clipy,int clipw,int cliph); + + // the stuff below is copied from kbabel. Thanks, guys! + QRect mapToView(int paragraph,int index); +}; + +#endif diff --git a/konversation/src/nick.cpp b/konversation/src/nick.cpp new file mode 100644 index 0000000..1ea7ffc --- /dev/null +++ b/konversation/src/nick.cpp @@ -0,0 +1,262 @@ +/* + 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. +*/ + +/* + begin: Fri Jan 25 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include "nick.h" +#include "addressbook.h" + +#include + +#include +#include +#include +#include + +#include "konversationapplication.h" +#include "preferences.h" + +Nick::Nick(KListView *listView, +const ChannelNickPtr& channelnick) + : QObject (), + KListViewItem (listView, listView->lastItem(), QString::null, + channelnick->getNickname(), channelnick->getHostmask()) +{ + m_channelnickptr = channelnick; + + Q_ASSERT(channelnick); + if(!channelnick) return; + + m_flags = 0; + m_height = height(); + + refresh(); + + connect(this, SIGNAL(refreshed()), listView, SLOT(startResortTimer())); + connect(getChannelNick(), SIGNAL(channelNickChanged()), SLOT(refresh())); + connect(getChannelNick()->getNickInfo(), SIGNAL(nickInfoChanged()), SLOT(refresh())); +} + +Nick::~Nick() +{ +} + +ChannelNickPtr Nick::getChannelNick() const +{ + Q_ASSERT(m_channelnickptr); + return m_channelnickptr; +} + +void Nick::refresh() +{ + int flags = 0; + NickInfo* nickInfo = getChannelNick()->getNickInfo(); + bool away = false; + + if ( nickInfo ) + away = nickInfo->isAway(); + + if(away) + flags=1; + + Images* images = KonversationApplication::instance()->images(); + QPixmap icon; + + if ( getChannelNick()->isOwner() ) + { + flags += 64; + icon = images->getNickIcon( Images::Owner, away ); + } + else if ( getChannelNick()->isAdmin() ) + { + flags += 128; + icon = images->getNickIcon( Images::Admin, away ); + } + else if ( getChannelNick()->isOp() ) + { + flags += 32; + icon = images->getNickIcon( Images::Op, away ); + } + else if ( getChannelNick()->isHalfOp() ) + { + flags += 16; + icon = images->getNickIcon( Images::HalfOp, away ); + } + else if ( getChannelNick()->hasVoice() ) + { + flags += 8; + icon = images->getNickIcon( Images::Voice, away ); + } + else + { + flags += 4; + icon = images->getNickIcon( Images::Normal, away ); + } + + setPixmap( 0, icon ); + + KABC::Picture pic = nickInfo->getAddressee().photo(); + + if(!pic.isIntern()) + { + pic = nickInfo->getAddressee().logo(); + } + + if(pic.isIntern()) + { + QPixmap qpixmap(pic.data().scaleHeight(m_height)); + setPixmap(1,qpixmap); + } + + QString newtext1 = calculateLabel1(); + if(newtext1 != text(1)) + { + setText(1, newtext1); + flags += 2; + } + + setText(2, calculateLabel2()); + repaint(); + + if(m_flags != flags) + { + m_flags = flags; + emit refreshed(); // Resort nick list + } +} + +QString Nick::calculateLabel1() +{ + NickInfoPtr nickinfo = getChannelNick()->getNickInfo(); + KABC::Addressee addressee = nickinfo->getAddressee(); + + if(!addressee.realName().isEmpty()) //if no addressee, realName will be empty + { + return nickinfo->getNickname() + " (" + addressee.realName() + ')'; + } + else if(Preferences::showRealNames() && !nickinfo->getRealName().isEmpty()) + { + return nickinfo->getNickname() + " (" + nickinfo->getRealName() + ')'; + } + + return nickinfo->getNickname(); +} + +QString Nick::calculateLabel2() +{ + return getChannelNick()->getNickInfo()->getHostmask(); +} + +int Nick::compare(QListViewItem* item,int col,bool ascending) const +{ + Nick* otherItem = static_cast(item); + + if(Preferences::sortByActivity()) + { + uint thisRecentActivity = getChannelNick()->recentActivity(); + uint otherRecentActivity = otherItem->getChannelNick()->recentActivity(); + if(thisRecentActivity > otherRecentActivity) + { + return -1; + } + if(thisRecentActivity < otherRecentActivity) + { + return 1; + } + uint thisTimestamp = getChannelNick()->timeStamp(); + uint otherTimestamp = otherItem->getChannelNick()->timeStamp(); + if(thisTimestamp > otherTimestamp) + { + return -1; + } + if(thisTimestamp < otherTimestamp) + { + return 1; + } + } + + if(Preferences::sortByStatus()) + { + int thisFlags = getSortingValue(); + int otherFlags = otherItem->getSortingValue(); + + if(thisFlags > otherFlags) + { + return 1; + } + if(thisFlags < otherFlags) + { + return -1; + } + } + + QString thisKey; + QString otherKey; + + if(col > 1) //the reason we need this: enabling hostnames adds another column + { + if(Preferences::sortCaseInsensitive()) + { + thisKey = thisKey.lower(); + otherKey = otherKey.lower(); + } + else + { + thisKey = key(col, ascending); + otherKey = otherItem->key(col, ascending); + } + } + else if(col == 1) + { + if(Preferences::sortCaseInsensitive()) + { + thisKey = getChannelNick()->loweredNickname(); + otherKey = otherItem->getChannelNick()->loweredNickname(); + } + else + { + thisKey = key(col, ascending); + otherKey = otherItem->key(col, ascending); + } + } + + return thisKey.compare(otherKey); +} + +void Nick::paintCell(QPainter * p, const QColorGroup & cg, int column, int width, int align ) +{ + QColorGroup cg2 = cg; + NickInfo* nickInfo = getChannelNick()->getNickInfo(); + + if(nickInfo->isAway()) + { + cg2.setColor(QColorGroup::Text, kapp->palette(listView()).disabled().text()); + } + + KListViewItem::paintCell(p,cg2,column,width,align); +} + +int Nick::getSortingValue() const +{ + int flags; + QString sortingOrder = Preferences::sortOrder(); + + if(getChannelNick()->isOwner()) flags=sortingOrder.find('q'); + else if(getChannelNick()->isAdmin()) flags=sortingOrder.find('p'); + else if(getChannelNick()->isOp() ) flags=sortingOrder.find('o'); + else if(getChannelNick()->isHalfOp()) flags=sortingOrder.find('h'); + else if(getChannelNick()->hasVoice()) flags=sortingOrder.find('v'); + else flags=sortingOrder.find('-'); + + return flags; +} + +#include "nick.moc" diff --git a/konversation/src/nick.h b/konversation/src/nick.h new file mode 100644 index 0000000..1a5ae59 --- /dev/null +++ b/konversation/src/nick.h @@ -0,0 +1,55 @@ +/* + 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. +*/ + +/* + begin: Fri Jan 25 2002 + copyright: (C) 2002 by Dario Abatianni + (C) 2007 Peter Simonsson + email: eisfuchs@tigress.com +*/ + +#ifndef NICK_H +#define NICK_H + +#include +#include + +#include "channelnick.h" + +class Nick : public QObject, public KListViewItem +{ + Q_OBJECT + public: + Nick(KListView *listView, + const ChannelNickPtr& channelnick); + ~Nick(); + + ChannelNickPtr getChannelNick() const; + int getSortingValue() const; + + virtual void paintCell(QPainter * p, const QColorGroup & cg, int column, int width, int align); + virtual int compare(QListViewItem* item,int col,bool ascending) const; + + public slots: + void refresh(); + + signals: + void refreshed(); + + protected: + QString calculateLabel1(); + QString calculateLabel2(); + + protected: + ChannelNickPtr m_channelnickptr; + + QString label; + int m_height; + int m_flags; + bool m_away; +}; +#endif diff --git a/konversation/src/nickinfo.cpp b/konversation/src/nickinfo.cpp new file mode 100644 index 0000000..72853aa --- /dev/null +++ b/konversation/src/nickinfo.cpp @@ -0,0 +1,445 @@ +/* + 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. +*/ + +/* + Nick Information + begin: Sat Jan 17 2004 + copyright: (C) 2004 by Gary Cramblitt + email: garycramblitt@comcast.net +*/ + +/* + The NickInfo object is a data container for information about a single nickname. + It is owned by the Server object and should NOT be deleted by anything other than Server. + Store a pointer to this with NickInfoPtr +*/ + +#include "nickinfo.h" +#include "konversationapplication.h" +#include "linkaddressbook/addressbook.h" +#include "linkaddressbook/linkaddressbookui.h" +#include "konversationmainwindow.h" +#include "viewcontainer.h" +#include "server.h" + +#include + +#include + + +NickInfo::NickInfo(const QString& nick, Server* server): KShared() +{ + m_addressee=Konversation::Addressbook::self()->getKABCAddresseeFromNick(nick, server->getServerName(), server->getDisplayName()); + m_nickname = nick; + m_loweredNickname = nick.lower(); + m_owningServer = server; + m_away = false; + m_notified = false; + m_identified = false; + m_printedOnline = true; + + if(!m_addressee.isEmpty()) + Konversation::Addressbook::self()->emitContactPresenceChanged(m_addressee.uid(), 4); + + connect( Konversation::Addressbook::self()->getAddressBook(), SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( refreshAddressee() ) ); + connect( Konversation::Addressbook::self(), SIGNAL(addresseesChanged()), this, SLOT(refreshAddressee())); + + m_changedTimer = new QTimer( this); + connect(m_changedTimer, SIGNAL( timeout()), SLOT(emitNickInfoChanged())); + + // reset nick color + m_nickColor = 0; +} + +NickInfo::~NickInfo() +{ + if(!m_addressee.isEmpty()) + Konversation::Addressbook::self()->emitContactPresenceChanged(m_addressee.uid(), 1); +} + +// Get properties of NickInfo object. +QString NickInfo::getNickname() const { return m_nickname; } +QString NickInfo::loweredNickname() const { return m_loweredNickname; } +QString NickInfo::getHostmask() const { return m_hostmask; } + +bool NickInfo::isAway() const { return m_away; } +QString NickInfo::getAwayMessage() const { return m_awayMessage; } +QString NickInfo::getIdentdInfo() const { return m_identdInfo; } +QString NickInfo::getVersionInfo() const { return m_versionInfo; } +bool NickInfo::isNotified() const { return m_notified; } +QString NickInfo::getRealName() const { return m_realName; } +QString NickInfo::getNetServer() const { return m_netServer; } +QString NickInfo::getNetServerInfo() const { return m_netServerInfo; } +QDateTime NickInfo::getOnlineSince() const { return m_onlineSince; } + +uint NickInfo::getNickColor() +{ + // do we already have a color? + if(!m_nickColor) + { + int nickvalue = 0; + + for (uint index = 0; index < m_nickname.length(); index++) + { + nickvalue += m_nickname[index].unicode(); + } + + m_nickColor = (nickvalue % 8) + 1; + } + // return color offset -1 (since we store it +1 for 0 checking) + return m_nickColor-1; +} + +bool NickInfo::isIdentified() const { return m_identified; } + +QString NickInfo::getPrettyOnlineSince() const +{ + QString prettyOnlineSince; + int daysto = m_onlineSince.date().daysTo( QDate::currentDate()); + if(daysto == 0) prettyOnlineSince = i18n("Today"); + else if(daysto == 1) prettyOnlineSince = i18n("Yesterday"); + else prettyOnlineSince = m_onlineSince.toString("ddd d MMMM yyyy"); + //TODO - we should use KLocale for this + prettyOnlineSince += ", " + m_onlineSince.toString("h:mm ap"); + + return prettyOnlineSince; +} + +// Return the Server object that owns this NickInfo object. +Server* NickInfo::getServer() const { return m_owningServer; } + +// Set properties of NickInfo object. +void NickInfo::setNickname(const QString& newNickname) +{ + Q_ASSERT(!newNickname.isEmpty()); + if(newNickname == m_nickname) return; + + KABC::Addressee newaddressee = Konversation::Addressbook::self()->getKABCAddresseeFromNick(newNickname, m_owningServer->getServerName(), m_owningServer->getDisplayName()); + //We now know who this person is + if(m_addressee.isEmpty() && !newaddressee.isEmpty()) + { + //Associate the old nickname with new contact + Konversation::Addressbook::self()->associateNick(newaddressee,m_nickname, m_owningServer->getServerName(), m_owningServer->getDisplayName()); + Konversation::Addressbook::self()->saveAddressee(newaddressee); + } + else if(!m_addressee.isEmpty() && newaddressee.isEmpty()) + { + Konversation::Addressbook::self()->associateNick(m_addressee, newNickname, m_owningServer->getServerName(), m_owningServer->getDisplayName()); + Konversation::Addressbook::self()->saveAddressee(newaddressee); + newaddressee = m_addressee; + } + + m_addressee = newaddressee; + m_nickname = newNickname; + m_loweredNickname = newNickname.lower(); + + QString realname = m_addressee.realName(); + startNickInfoChangedTimer(); +} + +void NickInfo::emitNickInfoChanged() +{ + m_owningServer->emitNickInfoChanged(this); + emit nickInfoChanged(); +} + +void NickInfo::startNickInfoChangedTimer() +{ + if(!m_changedTimer->isActive()) + m_changedTimer->start(3000, true /*single shot*/); +} + +void NickInfo::setHostmask(const QString& newMask) +{ + if (newMask.isEmpty() || newMask == m_hostmask) return; + m_hostmask = newMask; + + startNickInfoChangedTimer(); +} + +void NickInfo::setAway(bool state) +{ + if(state == m_away) return; + m_away = state; + + startNickInfoChangedTimer(); + if(!m_addressee.isEmpty()) + Konversation::Addressbook::self()->emitContactPresenceChanged(m_addressee.uid()); +} + +void NickInfo::setIdentified(bool identified) +{ + if(identified == m_identified) return; + m_identified = identified; + startNickInfoChangedTimer(); +} + +void NickInfo::setAwayMessage(const QString& newMessage) +{ + if(m_awayMessage == newMessage) return; + m_awayMessage = newMessage; + + startNickInfoChangedTimer(); +} + +void NickInfo::setIdentdInfo(const QString& newIdentdInfo) +{ + if(m_identdInfo == newIdentdInfo) return; + m_identdInfo = newIdentdInfo; + startNickInfoChangedTimer(); +} + +void NickInfo::setVersionInfo(const QString& newVersionInfo) +{ + if(m_versionInfo == newVersionInfo) return; + m_versionInfo = newVersionInfo; + + startNickInfoChangedTimer(); +} + +void NickInfo::setNotified(bool state) +{ + if(state == m_notified) return; + m_notified = state; + startNickInfoChangedTimer(); +} + +void NickInfo::setRealName(const QString& newRealName) +{ + if (newRealName.isEmpty() || m_realName == newRealName) return; + m_realName = newRealName; + startNickInfoChangedTimer(); +} + +void NickInfo::setNetServer(const QString& newNetServer) +{ + if (newNetServer.isEmpty() || m_netServer == newNetServer) return; + m_netServer = newNetServer; + startNickInfoChangedTimer(); +} + +void NickInfo::setNetServerInfo(const QString& newNetServerInfo) +{ + if (newNetServerInfo.isEmpty() || newNetServerInfo == m_netServerInfo) return; + m_netServerInfo = newNetServerInfo; + startNickInfoChangedTimer(); +} + +void NickInfo::setOnlineSince(const QDateTime& datetime) +{ + if (datetime.isNull() || datetime == m_onlineSince) return; + m_onlineSince = datetime; + + startNickInfoChangedTimer(); +} + +KABC::Addressee NickInfo::getAddressee() const { return m_addressee;} + +void NickInfo::refreshAddressee() +{ + //m_addressee might not have changed, but information inside it may have. + KABC::Addressee addressee=Konversation::Addressbook::self()->getKABCAddresseeFromNick(m_nickname, m_owningServer->getServerName(), m_owningServer->getDisplayName()); + if(!addressee.isEmpty() && addressee.uid() != m_addressee.uid()) + { + //This nick now belongs to a different addressee. We need to update the status for both the old and new addressees. + Konversation::Addressbook::self()->emitContactPresenceChanged(addressee.uid()); + } + m_addressee = addressee; + + startNickInfoChangedTimer(); + + if(!m_addressee.isEmpty()) + Konversation::Addressbook::self()->emitContactPresenceChanged(m_addressee.uid()); +} + +QString NickInfo::tooltip() const +{ + + QString strTooltip; + QTextStream tooltip( &strTooltip, IO_WriteOnly ); + tooltip << ""; + + tooltip << ""; + tooltipTableData(tooltip); + tooltip << "
"; + return strTooltip; +} + +QString NickInfo::getBestAddresseeName() +{ + if(!m_addressee.formattedName().isEmpty()) + { + return m_addressee.formattedName(); + } + else if(!m_addressee.realName().isEmpty()) + { + return m_addressee.realName(); + } + else if(!getRealName().isEmpty()) + { + return getRealName(); + } + else + { + return getNickname(); + } + +} + +void NickInfo::tooltipTableData(QTextStream &tooltip) const +{ + tooltip << ""; + + bool dirty = false; + KABC::Picture photo = m_addressee.photo(); + KABC::Picture logo = m_addressee.logo(); + bool isimage=false; + if(photo.isIntern()) + { + QMimeSourceFactory::defaultFactory()->setImage( "photo", photo.data() ); + tooltip << ""; + dirty=true; + isimage=true; + } + else if(!photo.url().isEmpty()) + { + //JOHNFLUX FIXME TODO: + //Are there security problems with this? loading from an external refrence? + //Assuming not. + tooltip << ""; + dirty=true; + isimage=true; + } + if(logo.isIntern()) + { + QMimeSourceFactory::defaultFactory()->setImage( "logo", logo.data() ); + tooltip << ""; + dirty=true; + isimage=true; + } + else if(!logo.url().isEmpty()) + { + //JOHNFLUX FIXME TODO: + //Are there security problems with this? loading from an external refrence? + //Assuming not. + tooltip << ""; + dirty=true; + isimage=true; + } + tooltip << "" << (isimage?"":"
"); + if(!m_addressee.formattedName().isEmpty()) + { + tooltip << m_addressee.formattedName(); + dirty = true; + } + else if(!m_addressee.realName().isEmpty()) + { + tooltip << m_addressee.realName(); + dirty = true; + } + else if(!getRealName().isEmpty() && getRealName().lower() != loweredNickname()) + { + QString escapedRealName( getRealName() ); + escapedRealName.replace("<","<").replace(">",">"); + tooltip << escapedRealName; + dirty = true; + } + else + { + tooltip << getNickname(); + //Don't set dirty if all we have is their nickname + } + if(m_identified) tooltip << i18n(" (identified)"); + tooltip << (isimage?"":"
") << "
"; + + tooltip << ""; + if(!m_addressee.emails().isEmpty()) + { + tooltip << "" << i18n("Email") << ": "; + tooltip << m_addressee.emails().join(", "); + tooltip << ""; + dirty=true; + } + + if(!m_addressee.organization().isEmpty()) + { + tooltip << "" << m_addressee.organizationLabel() << ": " << m_addressee.organization() << ""; + dirty=true; + } + if(!m_addressee.role().isEmpty()) + { + tooltip << "" << m_addressee.roleLabel() << ": " << m_addressee.role() << ""; + dirty=true; + } + KABC::PhoneNumber::List numbers = m_addressee.phoneNumbers(); + for( KABC::PhoneNumber::List::ConstIterator it = numbers.begin(); it != numbers.end(); ++it) + { + tooltip << "" << (*it).label() << ": " << (*it).number() << ""; + dirty=true; + } + if(!m_addressee.birthday().toString().isEmpty() ) + { + tooltip << "" << m_addressee.birthdayLabel() << ": " << m_addressee.birthday().toString("ddd d MMMM yyyy") << ""; + dirty=true; + } + if(!getHostmask().isEmpty()) + { + tooltip << "" << i18n("Hostmask:") << " " << getHostmask() << ""; + dirty=true; + } + if(isAway()) + { + tooltip << "" << i18n("Away Message:") << " "; + if(!getAwayMessage().isEmpty()) + tooltip << getAwayMessage(); + else + tooltip << i18n("(unknown)"); + tooltip << ""; + dirty=true; + } + if(!getOnlineSince().toString().isEmpty()) + { + tooltip << "" << i18n("Online Since:") << " " << getPrettyOnlineSince() << ""; + dirty=true; + } + +} + +void NickInfo::showLinkAddressbookUI() +{ + LinkAddressbookUI *linkaddressbookui = new LinkAddressbookUI(m_owningServer->getViewContainer()->getWindow(), NULL, m_nickname, m_owningServer->getServerName(), m_owningServer->getDisplayName(), m_realName); + linkaddressbookui->show(); + +} + +bool NickInfo::editAddressee() const +{ + if(m_addressee.isEmpty()) return false; + + Konversation::Addressbook::self()->editAddressee(m_addressee.uid()); + return true; +} + +bool NickInfo::sendEmail() const +{ + return Konversation::Addressbook::self()->sendEmail(m_addressee); +} + +void NickInfo::setPrintedOnline(bool printed) +{ + m_printedOnline=printed; +} + +bool NickInfo::getPrintedOnline() +{ + if(this) + return m_printedOnline; + else + return false; +} + +#include "nickinfo.moc" diff --git a/konversation/src/nickinfo.h b/konversation/src/nickinfo.h new file mode 100644 index 0000000..f6e9a9b --- /dev/null +++ b/konversation/src/nickinfo.h @@ -0,0 +1,185 @@ +/* + 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. +*/ + +/* + Nick Information + begin: Sat Jan 17 2004 + copyright: (C) 2004 by Gary Cramblitt + email: garycramblitt@comcast.net +*/ + +#ifndef NICKINFO_H +#define NICKINFO_H + +#include +#include +#include + +#include + + +class Server; +class QTimer; + +/** + The NickInfo object is a data container for information about a single nickname. + It is owned by the Server object and should NOT be deleted by anything other than Server. + + A NickInfo is _only_ for online (or away) nicks. Not for offline nicks. + Offline (but watched or in addressbook) nicks are stored in the Server object. + +*/ +class NickInfo : public QObject, public KShared +{ + Q_OBJECT + + public: + NickInfo(const QString& nick, Server* server); + ~NickInfo(); + + // Get properties of NickInfo object. + QString getNickname() const; + QString loweredNickname() const; + QString getHostmask() const; + /** Currently return whether the user has set themselves to away with /away. + * May be changed in the future to parse the nick string and see if it contains + * "|away" or "|afk" or something. + */ + bool isAway() const; + QString getAwayMessage() const; + QString getIdentdInfo() const; + QString getVersionInfo() const; + bool isNotified() const; + QString getRealName() const; + QString getNetServer() const; + QString getNetServerInfo() const; + QDateTime getOnlineSince() const; + uint getNickColor(); + /** Whether this user is identified with nickserv. + * Found only by doing /whois nick + */ + bool isIdentified() const; + /** This returns a string of the date and time that the user has been online since. + * It will return null if a /whois hasn't been issued yet for this nickinfo + * @return a date-string in the form of "Today, 4:23pm", "Yesterday, 12:32pm" or "Mon 3 Mar 2004, 8:02am" + */ + QString getPrettyOnlineSince() const; + /// Return the Server object that owns this NickInfo object. + Server* getServer() const; + + /// Return the kabc (kaddressbook) contact for this nick + KABC::Addressee getAddressee() const; + + /** Set properties of NickInfo object. */ + void setNickname(const QString& newNickname); + /** Set properties of NickInfo object. Ignores the request is newmask is empty.*/ + void setHostmask(const QString& newMask); + /** Set properties of NickInfo object. */ + void setAway(bool state); + /** Set properties of NickInfo object. */ + void setAwayMessage(const QString& newMessage); + /** Set properties of NickInfo object. */ + void setIdentdInfo(const QString& newIdentdInfo); + /** Set properties of NickInfo object. */ + void setVersionInfo(const QString& newVersionInfo); + /** Set properties of NickInfo object. */ + void setNotified(bool state); + /** Set properties of NickInfo object. */ + void setRealName(const QString& newRealName); + /** Set properties of NickInfo object. */ + void setNetServer(const QString& newNetServer); + /** Set properties of NickInfo object. */ + void setNetServerInfo(const QString& newNetServerInfo); + /** Whether this user is identified with nickserv. + * Found only by doing /whois nick + */ + void setIdentified(bool identified); + /** Updates the time online since. + * This will be called from the results of a /whois + * This function also calculates and sets prettyOnlineSince + * @see getPrettyOnlineSince() + */ + void setOnlineSince(const QDateTime& datetime); + /** Returns html describing this nickInfo - useful for tooltips when hovering over this nick. + */ + QString tooltip() const; + /** Returns just the .. data for a tooltip. + * Used so that channelNick->tooltip() can call this, then append on its own information. + */ + void tooltipTableData(QTextStream &tooltip) const; + + /** Returns a full name for this contact. Tries to use the name out of addressbook. + * If that is empty, uses the real name from whois. If that fails, use nickname. + * + * @return A string to show the user for the name of this contact + */ + QString getBestAddresseeName(); + + /** Open this contact up in a "edit addresee association" window + */ + void showLinkAddressbookUI(); + /** Edit the contact in kaddressbook + */ + bool editAddressee() const; + /** Run kmail for this contact + */ + bool sendEmail() const; + + void setPrintedOnline(bool printed); + bool getPrintedOnline(); + + private: + /** After calling, emitNickInfoChanged is guaranteed to be called _within_ 1 second. + * Used to consolidate changed signals. + */ + void startNickInfoChangedTimer(); + QString m_nickname; + QString m_loweredNickname; + Server* m_owningServer; + QString m_hostmask; + bool m_away; + QString m_awayMessage; + QString m_identdInfo; + QString m_versionInfo; + bool m_notified; + QString m_realName; + /** The server they are connected to. */ + QString m_netServer; + QString m_netServerInfo; + QDateTime m_onlineSince; + KABC::Addressee m_addressee; + /** Whether this user is identified with nickserv. + * Found only by doing /whois nick + */ + bool m_identified; + QTimer *m_changedTimer; + /* True if "foo is online" message is printed */ + bool m_printedOnline; + /* The color index for lookup on Preferences::NickColor(index).name() + Internally stored as index-1 to allow checking for 0 */ + uint m_nickColor; + + private slots: + void refreshAddressee(); + /** emits NickInfoChanged for this object, and calls the server emitNickInfoChanged. + * Called when the m_changedTimer activates. + */ + void emitNickInfoChanged(); + signals: + void nickInfoChanged(void); +}; + +/** A NickInfoPtr is a pointer to a NickInfo object. Since it is a KSharedPtr, the NickInfo + * object is automatically destroyed when all references are destroyed. + */ +typedef KSharedPtr NickInfoPtr; +/** A NickInfoMap is a list of NickInfo objects, indexed and sorted by lowercase nickname. + */ +typedef QMap NickInfoMap; + +typedef QValueList NickInfoList; +#endif diff --git a/konversation/src/nicklistbehavior_preferences.cpp b/konversation/src/nicklistbehavior_preferences.cpp new file mode 100644 index 0000000..8bb3bde --- /dev/null +++ b/konversation/src/nicklistbehavior_preferences.cpp @@ -0,0 +1,108 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006 John Tapsell + Copyright (C) 2006 Eike Hein +*/ + +#include "nicklistbehavior_preferences.h" +#include "valuelistviewitem.h" +#include "config/preferences.h" + +#include + +#include +#include + + +NicklistBehavior_Config::NicklistBehavior_Config(QWidget *parent, const char *name) + : NicklistBehavior_ConfigUI(parent, name) +{ + // get page widget and populate listview + loadSettings(); + + // make items react to drag & drop + sortOrder->setSorting(-1,false); + sortOrder->header()->setMovingEnabled(false); + + connect(sortOrder,SIGNAL (moved()),this,SIGNAL (modified()) ); +} + +NicklistBehavior_Config::~NicklistBehavior_Config() +{ +} + +void NicklistBehavior_Config::restorePageToDefaults() +{ + setNickList(Preferences::defaultNicknameSortingOrder()); +} + +void NicklistBehavior_Config::loadSettings() +{ + // get sorting order string from preferences + setNickList(Preferences::sortOrder()); + m_oldSortingOrder=currentSortingOrder(); +} + +void NicklistBehavior_Config::setNickList(const QString &sortingOrder) +{ + sortOrder->clear(); + // loop through the sorting order string, insert the matching descriptions in reverse order + // to keep the correct sorting + for(unsigned int index=sortingOrder.length();index!=0;index--) + { + // get next mode char + QChar mode=sortingOrder[index-1]; + // find appropriate description + if(mode=='-') new KListViewItem(sortOrder,mode,i18n("Normal Users")); + if(mode=='v') new KListViewItem(sortOrder,mode,i18n("Voice (+v)")); + if(mode=='h') new KListViewItem(sortOrder,mode,i18n("Halfops (+h)")); + if(mode=='o') new KListViewItem(sortOrder,mode,i18n("Operators (+o)")); + if(mode=='p') new KListViewItem(sortOrder,mode,i18n("Channel Admins (+p)")); + if(mode=='q') new KListViewItem(sortOrder,mode,i18n("Channel Owners (+q)")); + } +} + +QString NicklistBehavior_Config::currentSortingOrder() +{ + // get the uppermost entry of the sorting list + QListViewItem* item=sortOrder->firstChild(); + // prepare the new sorting order string + QString currentSortingOrder; + // iterate through all items of the listview + while(item) + { + // add mode char to the sorting order string + currentSortingOrder+=item->text(0); + // go to next item in the listview + item=item->itemBelow(); + } // while + + return currentSortingOrder; +} + +// save settings permanently +void NicklistBehavior_Config::saveSettings() +{ + // get the current sorting order + QString newSortingOrder=currentSortingOrder(); + + // update sorting order on in-memory preferences + Preferences::setSortOrder(newSortingOrder); + + // save current sorting order as a reference to hasChanged() + m_oldSortingOrder=currentSortingOrder(); +} + +bool NicklistBehavior_Config::hasChanged() +{ + return(m_oldSortingOrder!=currentSortingOrder()); +} + +#include "nicklistbehavior_preferences.moc" diff --git a/konversation/src/nicklistbehavior_preferences.h b/konversation/src/nicklistbehavior_preferences.h new file mode 100644 index 0000000..5eda68d --- /dev/null +++ b/konversation/src/nicklistbehavior_preferences.h @@ -0,0 +1,46 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006 John Tapsell +*/ + +#ifndef NICKLISTBEHAVIOR_Config_H +#define NICKLISTBEHAVIOR_Config_H + +#include "konvisettingspage.h" +#include "nicklistbehavior_preferencesui.h" + +#include + + +class NicklistBehavior_Config : public NicklistBehavior_ConfigUI, public KonviSettingsPage +{ + Q_OBJECT + + public: + explicit NicklistBehavior_Config(QWidget *parent = 0, const char *name = 0); + ~NicklistBehavior_Config(); + + virtual void saveSettings(); + virtual void loadSettings(); + virtual void restorePageToDefaults(); + + virtual bool hasChanged(); + + private: + void setNickList(const QString &sortingOrder); + QString currentSortingOrder(); + + QString m_oldSortingOrder; + + signals: + void modified(); +}; + +#endif diff --git a/konversation/src/nicklistbehavior_preferencesui.ui b/konversation/src/nicklistbehavior_preferencesui.ui new file mode 100644 index 0000000..2e84d89 --- /dev/null +++ b/konversation/src/nicklistbehavior_preferencesui.ui @@ -0,0 +1,160 @@ + +NicklistBehavior_ConfigUI +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. + +Copyright (C) 2005 Peter Simonsson + + + NicklistBehavior_ConfigUI + + + + 0 + 0 + 692 + 480 + + + + + unnamed + + + 0 + + + + textLabel1_2 + + + &Command to be executed on double click: + + + kcfg_ChannelDoubleClickAction + + + + + kcfg_SortCaseInsensitive + + + Sort case &insensitive + + + + + kcfg_SortByActivity + + + Sort by &activity + + + + + kcfg_SortByStatus + + + + 4 + 0 + 0 + 0 + + + + Sort b&y user status + + + + + + Mode + + + true + + + true + + + + + Explanation + + + true + + + true + + + + sortOrder + + + false + + + true + + + true + + + true + + + true + + + false + + + + + kcfg_ChannelDoubleClickAction + + + + + orderHintLabel + + + false + + + (Reorder nick sorting order by drag and drop) + + + + + + + kcfg_SortByStatus + toggled(bool) + sortOrder + setEnabled(bool) + + + kcfg_SortByStatus + toggled(bool) + orderHintLabel + setEnabled(bool) + + + + kcfg_ChannelDoubleClickAction + kcfg_SortCaseInsensitive + kcfg_SortByStatus + sortOrder + + + + + klistview.h + klineedit.h + + diff --git a/konversation/src/nicklistview.cpp b/konversation/src/nicklistview.cpp new file mode 100644 index 0000000..e6e2bf2 --- /dev/null +++ b/konversation/src/nicklistview.cpp @@ -0,0 +1,336 @@ +/* + 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 is the class that shows the channel nick list + begin: Fre Jun 7 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include "nicklistview.h" +#include "konversationapplication.h" +#include "images.h" +#include "linkaddressbook/addressbook.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +NickListView::NickListView(QWidget* parent, Channel *chan) : +KListView(parent) +{ + KListView::setSorting(-1); + setWhatsThis(); + channel=chan; + popup=new KPopupMenu(this,"nicklist_context_menu"); + modes=new KPopupMenu(this,"nicklist_modes_context_submenu"); + kickban=new KPopupMenu(this,"nicklist_kick_ban_context_submenu"); + addressbook= new KPopupMenu(this,"nicklist_addressbook_context_submenu"); + setAcceptDrops(true); + setDropHighlighter(true); + setDropVisualizer(false); + + if (popup) + { + popup->insertItem(i18n("&Whois"),Konversation::Whois); + popup->insertItem(i18n("&Version"),Konversation::Version); + popup->insertItem(i18n("&Ping"),Konversation::Ping); + + popup->insertSeparator(); + + if (modes) + { + modes->insertItem(i18n("Give Op"),Konversation::GiveOp); + modes->insertItem(i18n("Take Op"),Konversation::TakeOp); + modes->insertItem(i18n("Give HalfOp"),Konversation::GiveHalfOp); + modes->insertItem(i18n("Take HalfOp"),Konversation::TakeHalfOp); + modes->insertItem(i18n("Give Voice"),Konversation::GiveVoice); + modes->insertItem(i18n("Take Voice"),Konversation::TakeVoice); + popup->insertItem(i18n("Modes"),modes,Konversation::ModesSub); + } + + if (kickban) + { + + kickban->insertItem(i18n("Kick"),Konversation::Kick); + kickban->insertItem(i18n("Kickban"),Konversation::KickBan); + kickban->insertItem(i18n("Ban Nickname"),Konversation::BanNick); + kickban->insertSeparator(); + kickban->insertItem(i18n("Ban *!*@*.host"),Konversation::BanHost); + kickban->insertItem(i18n("Ban *!*@domain"),Konversation::BanDomain); + kickban->insertItem(i18n("Ban *!user@*.host"),Konversation::BanUserHost); + kickban->insertItem(i18n("Ban *!user@domain"),Konversation::BanUserDomain); + kickban->insertSeparator(); + kickban->insertItem(i18n("Kickban *!*@*.host"),Konversation::KickBanHost); + kickban->insertItem(i18n("Kickban *!*@domain"),Konversation::KickBanDomain); + kickban->insertItem(i18n("Kickban *!user@*.host"),Konversation::KickBanUserHost); + kickban->insertItem(i18n("Kickban *!user@domain"),Konversation::KickBanUserDomain); + popup->insertItem(i18n("Kick / Ban"),kickban,Konversation::KickBanSub); + } + + popup->insertItem(i18n("Ignore"), Konversation::IgnoreNick); + popup->insertItem(i18n("Unignore"), Konversation::UnignoreNick); + + popup->insertSeparator(); + + int newitem; + newitem = popup->insertItem(i18n("Open &Query"),Konversation::OpenQuery); + popup->setWhatsThis(newitem, "Start a private chat between you and this person.

Technical note:
The conversation between you and this person will be sent via the server. This means that the conversation will be affected by server lag, server stability, and will be terminated when you disconnect from the server."); + newitem = popup->insertItem(i18n("Open DCC &Chat"),Konversation::StartDccChat); + popup->setWhatsThis(newitem, "Start a private Direct Client Connection chat between you and this person.

Technical note:
The conversation between you and this person will be sent directly. This means it is independent from the server - so if the server connection fails, or use disconnect, your DCC Chat will be unaffected. It also means that no irc server admin can view or spy on this chat."); + + if (kapp->authorize("allow_downloading")) + { + newitem = popup->insertItem(SmallIcon("2rightarrow"),i18n("Send &File..."),Konversation::DccSend); + popup->setWhatsThis(newitem, "Send a file to this person. If you are having problem sending files, or they are sending slowly, see the Konversation Handbook and DCC preferences page."); + } + popup->insertItem(SmallIconSet("mail_generic"),i18n("&Send Email..."), Konversation::SendEmail); + + popup->insertSeparator(); + + if (addressbook) + popup->insertItem(i18n("Addressbook Associations"), addressbook, Konversation::AddressbookSub); + + popup->insertItem(i18n("Add to Watched Nicks"), Konversation::AddNotify); + + connect (popup, SIGNAL(activated(int)), this, SIGNAL(popupCommand(int))); + connect (modes, SIGNAL(activated(int)), this, SIGNAL(popupCommand(int))); + connect (kickban, SIGNAL(activated(int)), this, SIGNAL(popupCommand(int))); + connect (addressbook, SIGNAL(activated(int)), this, SIGNAL(popupCommand(int))); + + } + else + { + kdWarning() << "NickListView::NickListView(): Could not create popup!" << endl; + } + + #if KDE_IS_VERSION(3,3,90) + setShadeSortColumn(false); + #endif + + // We have our own tooltips, don't use the default QListView ones + setShowToolTips(false); + m_tooltip = new Konversation::KonversationNickListViewToolTip(viewport(), this); + + m_resortTimer = new QTimer(this); + connect(m_resortTimer, SIGNAL(timeout()), SLOT(resort())); +} + +NickListView::~NickListView() +{ + delete m_tooltip; + m_tooltip = 0; +} + +void NickListView::setWhatsThis() +{ + Images* images = KonversationApplication::instance()->images(); + + if(images->getNickIcon( Images::Normal, false).isNull()) + { + QWhatsThis::add(this, i18n("This shows all the people in the channel. The nick for each person is shown.
Usually an icon is shown showing the status of each person, but you do not seem to have any icon theme installed. See the Konversation settings - Configure Konversation under the Settings menu. Then view the page for Themes under Appearence.
")); + } + else + { + QMimeSourceFactory::defaultFactory()->setImage( "admin", images->getNickIcon( Images::Admin, false ).convertToImage() ); + QMimeSourceFactory::defaultFactory()->setImage( "owner", images->getNickIcon( Images::Owner, false ).convertToImage()); + QMimeSourceFactory::defaultFactory()->setImage( "op", images->getNickIcon( Images::Op, false ).convertToImage() ); + QMimeSourceFactory::defaultFactory()->setImage( "halfop", images->getNickIcon( Images::HalfOp, false ).convertToImage() ); + QMimeSourceFactory::defaultFactory()->setImage( "voice", images->getNickIcon( Images::Voice, false ).convertToImage() ); + QMimeSourceFactory::defaultFactory()->setImage( "normal", images->getNickIcon( Images::Normal, false ).convertToImage() ); + QMimeSourceFactory::defaultFactory()->setImage( "normalaway", images->getNickIcon( Images::Normal, true).convertToImage() ); + + QWhatsThis::add(this, i18n("This shows all the people in the channel. The nick for each person is shown, with a picture showing their status.

" + "" + + "" + "" + "" + "" + "" + "" + "" + "
This person has administrator privileges.
This person is a channel owner.
This person is a channel operator.
This person is a channel half-operator.
This person has voice, and can therefore talk in a moderated channel.
This person does not have any special privileges.
This indicates that this person is currently away.

" + "The meaning of admin, owner and halfop varies between different IRC servers.

" + "Hovering over any nick shows their current status, as well as any information in the addressbook for this person. See the Konversation Handbook for more information." + "" + )); + } + +} + +void NickListView::refresh() +{ + QListViewItemIterator it(this); + + while (it.current()) + { + static_cast(it.current())->refresh(); + ++it; + } + + setWhatsThis(); +} + +void NickListView::startResortTimer() +{ + if(!m_resortTimer->isActive()) + m_resortTimer->start(3000, true /*single shot*/); +} + +void NickListView::resort() +{ + KListView::setSorting(m_column, m_ascending); + sort(); + KListView::setSorting(-1); +} + +void NickListView::contextMenuEvent(QContextMenuEvent* ce) +{ + ce->accept(); + + if (selectedItems().count()) + { + insertAssociationSubMenu(); + updateActions(); + popup->popup(ce->globalPos()); + } +} + +void NickListView::updateActions() +{ + int ignoreCounter = 0; + int unignoreCounter = 0; + int notifyCounter = 0; + + int serverGroupId = -1; + + if (channel->getServer()->getServerGroup()) + serverGroupId = channel->getServer()->getServerGroup()->id(); + + ChannelNickList nickList=channel->getSelectedChannelNicks(); + ChannelNickList::ConstIterator it; + + for (it = nickList.begin(); it != nickList.end(); ++it) + { + if (Preferences::isIgnored((*it)->getNickname())) + ++unignoreCounter; + else + ++ignoreCounter; + + if (serverGroupId != -1 && Preferences::isNotify(serverGroupId, (*it)->getNickname())) + ++notifyCounter; + } + + if (ignoreCounter) + popup->setItemVisible(Konversation::IgnoreNick, true); + else + popup->setItemVisible(Konversation::IgnoreNick, false); + + if (unignoreCounter) + popup->setItemVisible(Konversation::UnignoreNick, true); + else + popup->setItemVisible(Konversation::UnignoreNick, false); + + if (notifyCounter || !Preferences::hasNotifyList(serverGroupId)) + popup->setItemEnabled(Konversation::AddNotify, false); + else + popup->setItemEnabled(Konversation::AddNotify, true); +} + +void NickListView::insertAssociationSubMenu() +{ + + bool existingAssociation = false; + bool noAssociation = false; + bool emailAddress = false; + + addressbook->clear(); + + ChannelNickList nickList=channel->getSelectedChannelNicks(); + for(ChannelNickList::ConstIterator it=nickList.begin();it!=nickList.end();++it) + { + KABC::Addressee addr = (*it)->getNickInfo()->getAddressee(); + if(addr.isEmpty()) + { + noAssociation=true; + if(existingAssociation && emailAddress) break; + } + else + { + if(!emailAddress && !addr.preferredEmail().isEmpty()) + emailAddress = true; + existingAssociation=true; + if(noAssociation && emailAddress) break; + } + } + + if(!noAssociation && existingAssociation) + { + addressbook->insertItem(SmallIcon("contents"), i18n("Edit Contact..."), Konversation::AddressbookEdit); + addressbook->insertSeparator(); + } + + if(noAssociation && existingAssociation) + addressbook->insertItem(i18n("Choose/Change Associations..."), Konversation::AddressbookChange); + else if(noAssociation) + addressbook->insertItem(i18n("Choose Contact..."), Konversation::AddressbookChange); + else + addressbook->insertItem(i18n("Change Association..."), Konversation::AddressbookChange); + + if(noAssociation && !existingAssociation) + addressbook->insertItem(i18n("Create New Contact..."), Konversation::AddressbookNew); + + if(existingAssociation) + addressbook->insertItem(SmallIcon("editdelete"), i18n("Delete Association"), Konversation::AddressbookDelete); + + if(!emailAddress) + popup->setItemEnabled(Konversation::SendEmail, false); + else + popup->setItemEnabled(Konversation::SendEmail, true); + +} + +void NickListView::setSorting(int column, bool ascending) +{ + m_column = column; + m_ascending = ascending; +} + +bool NickListView::acceptDrag (QDropEvent* event) const +{ + if (event->provides("text/uri-list")) + { + if (event->source()) + { + QStrList uris; + + if (QUriDrag::decode(event,uris)) + { + QString first = uris.first(); + + if (first.startsWith("irc://") || channel->getNickList().containsNick(first)) + return false; + } + else + return false; + } + + return true; + } + else + return false; +} + +#include "nicklistview.moc" diff --git a/konversation/src/nicklistview.h b/konversation/src/nicklistview.h new file mode 100644 index 0000000..ac6ac80 --- /dev/null +++ b/konversation/src/nicklistview.h @@ -0,0 +1,77 @@ +/* + 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. +*/ + +/* + Channel Nick List, including context menu + begin: Fre Jun 7 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#ifndef NICKLISTVIEW_H +#define NICKLISTVIEW_H + +#include "channel.h" +#include "nicklisttooltip.h" +#include "images.h" +#include "common.h" + +#include + + +class QPopupMenu; +class QContextMenuEvent; +class QTimer; + +class NickListView : public KListView +{ + Q_OBJECT + + public: + NickListView(QWidget* parent, Channel *chan); + ~NickListView(); + + /** Call when the icons have been changed. + */ + void refresh(); + void setWhatsThis(); + + virtual void setSorting(int column, bool ascending); + + public slots: + /** When this is called, resort is guaranteed to be called within a hard-coded time (a few seconds). + * This prevents lots of calls to resort. + */ + void startResortTimer(); + + /** Resort the listview. + * It is better to call startResortTimer() which will resort with a minimum of a + * 1 second delay. + */ + void resort(); + + signals: + /* Will be connected to Channel::popupCommand(int) */ + void popupCommand(int id); + + protected: + void contextMenuEvent(QContextMenuEvent* ce); + virtual bool acceptDrag (QDropEvent* event) const; + void insertAssociationSubMenu(); + void updateActions(); + Konversation::KonversationNickListViewToolTip *m_tooltip; + QPopupMenu* popup; + QPopupMenu* modes; + QPopupMenu* kickban; + QPopupMenu* addressbook; + Channel *channel; + QTimer *m_resortTimer; + + int m_column; + bool m_ascending; +}; +#endif diff --git a/konversation/src/nicksonline.cpp b/konversation/src/nicksonline.cpp new file mode 100644 index 0000000..85361ff --- /dev/null +++ b/konversation/src/nicksonline.cpp @@ -0,0 +1,975 @@ +// -*- mode: c++; c-file-style: "bsd"; c-basic-offset: 4; tabs-width: 4; indent-tabs-mode: nil -*- + +/* + 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. +*/ + +/* + shows a user tree of friends per server + begin: Sam Aug 31 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#include "nicksonline.h" +#include "channel.h" +#include "server.h" +#include "konversationapplication.h" +#include "connectionmanager.h" +#include "images.h" +#include "query.h" +#include "linkaddressbook/linkaddressbookui.h" +#include "linkaddressbook/addressbook.h" +#include "linkaddressbook/nicksonlinetooltip.h" +#include "konversationmainwindow.h" +#include "viewcontainer.h" +#include "nicksonlineitem.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include + + +NicksOnline::NicksOnline(QWidget* parent): ChatWindow(parent) +{ + setName(i18n("Watched Nicks Online")); + setType(ChatWindow::NicksOnline); + + m_nickListView=new KListView(this); + + // Set to false every 8 seconds to permit a whois on watched nicks lacking information. + // Remove when server or addressbook does this automatically. + m_whoisRequested = true; + + m_nickListView->addColumn(i18n("Network/Nickname/Channel")); + m_kabcIconSet = KGlobal::iconLoader()->loadIconSet("kaddressbook",KIcon::Small); + m_nickListView->addColumn(i18n("Additional Information")); + m_nickListView->setFullWidth(true); + m_nickListView->setRootIsDecorated(true); + m_nickListView->setShowToolTips(false); + m_nickListView->setShadeSortColumn(true); + m_nickListView->setShowSortIndicator(true); + + QString nickListViewWT = i18n( + "

These are all the nicknames on your Nickname Watch list, listed under the " + "server network they are connected to. The list also includes the nicknames " + "in KAddressBook associated with the server network.

" + "

The Additional Information column shows the information known " + "for each nickname.

" + "

The channels the nickname has joined are listed underneath each nickname.

" + "

Nicknames appearing under Offline are not connected to any of the " + "servers in the network.

" + "

Right-click with the mouse on a nickname to perform additional functions.

"); + QWhatsThis::add(m_nickListView, nickListViewWT); + + m_tooltip = new Konversation::KonversationNicksOnlineToolTip(m_nickListView->viewport(), this); + + setMargin(margin()); + setSpacing(spacing()); + + QHBox* buttonBox=new QHBox(this); + buttonBox->setSpacing(spacing()); + QPushButton* editButton=new QPushButton(i18n("&Edit Watch List..."), + buttonBox,"edit_notify_button"); + QString editButtonWT = i18n( + "Click to edit the list of nicknames that appear on this screen."); + QWhatsThis::add(editButton, editButtonWT); + + connect(editButton, SIGNAL(clicked()), SIGNAL(editClicked()) ); + connect(m_nickListView, SIGNAL(doubleClicked(QListViewItem*)), + this,SLOT(processDoubleClick(QListViewItem*))); + + QLabel* addressbookLabel = new QLabel(i18n("Address book:"), + buttonBox, "nicksonline_addressbook_label"); + QString addressbookLabelWT = i18n( + "When you select a nickname in the list above, the buttons here are used " + "to associate the nickname with an entry in KAddressBook."); + QWhatsThis::add(addressbookLabel, addressbookLabelWT); + addressbookLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + m_editContactButton = new QPushButton(i18n("Edit C&ontact..."), + buttonBox, "nicksonline_editcontact_button"); + QString editContactButtonWT = i18n( + "Click to create, view, or edit the KAddressBook entry associated with the nickname " + "selected above."); + QWhatsThis::add(m_editContactButton, editContactButtonWT); + m_editContactButton->setIconSet(m_kabcIconSet); + m_changeAssociationButton = new QPushButton(i18n("&Change Association..."), + buttonBox, "nicksonline_changeassociation_button"); + QString changeAssociationButtonWT = i18n( + "Click to associate the nickname selected above with an entry in KAddressBook."); + QWhatsThis::add(m_changeAssociationButton, changeAssociationButtonWT); + m_changeAssociationButton->setIconSet(m_kabcIconSet); + m_deleteAssociationButton = new QPushButton(i18n("&Delete Association"), + buttonBox, "nicksonline_deleteassociation_button"); + QString deleteAssociationButtonWT = i18n( + "Click to remove the association between the nickname selected above and a " + "KAddressBook entry."); + QWhatsThis::add(m_deleteAssociationButton, deleteAssociationButtonWT); + m_deleteAssociationButton->setIconSet(m_kabcIconSet); + + connect(m_editContactButton, SIGNAL(clicked()), + this, SLOT(slotEditContactButton_Clicked())); + connect(m_changeAssociationButton, SIGNAL(clicked()), + this, SLOT(slotChangeAssociationButton_Clicked())); + connect(m_deleteAssociationButton, SIGNAL(clicked()), + this, SLOT(slotDeleteAssociationButton_Clicked())); + connect(m_nickListView, SIGNAL(selectionChanged()), + this, SLOT(slotNickListView_SelectionChanged())); + + setupAddressbookButtons(nsNotANick); + + // Create context menu. Individual menu entries are created in rightButtonClicked slot. + m_popupMenu = new QPopupMenu(this,"nicksonline_context_menu"); + connect(m_nickListView, SIGNAL(rightButtonClicked(QListViewItem *, const QPoint &, int )), + this, SLOT(slotNickListView_RightButtonClicked(QListViewItem*, const QPoint &))); + connect(m_popupMenu, SIGNAL(activated(int)), + this, SLOT(slotPopupMenu_Activated(int))); + + // Display info for all currently-connected servers. + refreshAllServerOnlineLists(); + + // Connect and start refresh timer. + m_timer = new QTimer(this, "nicksOnlineTimer"); + connect(m_timer, SIGNAL (timeout()), this, SLOT(timerFired())); + // TODO: User preference for refresh interval. + m_timer->start(8000); +} + +NicksOnline::~NicksOnline() +{ + m_timer->stop(); + delete m_timer; + delete m_nickListView; +} + +KListView* NicksOnline::getNickListView() +{ + return m_nickListView; +} + +/** + * Returns the named child of parent item in a NicksOnlineItem + * @param parent Pointer to a NicksOnlineItem. + * @param name The name in the desired child QListViewItem, must be in column 0. + * @param type The type of entry to be found + * @return Pointer to the child QListViewItem or 0 if not found. + */ +QListViewItem* NicksOnline::findItemChild(const QListViewItem* parent, const QString& name, NicksOnlineItem::NickListViewColumn type) +{ + if (!parent) return 0; + QListViewItem* child; + for (child = parent->firstChild(); (child) ; child = child->nextSibling()) + { + if(static_cast(child)->type() == type && child->text(0) == name) return child; + } + return 0; +} + +/** + * Returns the first occurrence of a child item of a given type in a NicksOnlineItem + * @param parent Pointer to a NicksOnlineItem. + * @param type The type of entry to be found + * @return Pointer to the child QListViewItem or 0 if not found. + */ +QListViewItem* NicksOnline::findItemType(const QListViewItem* parent, NicksOnlineItem::NickListViewColumn type) +{ + if (!parent) return 0; + QListViewItem* child; + for (child = parent->firstChild(); (child) ; child = child->nextSibling()) + { + if(static_cast(child)->type() == type) return child; + } + return 0; +} + +/** + * Returns a pointer to the network QListViewItem with the given name. + * @param name The name of the network, assumed to be in column 0 of the item. + * @return Pointer to the QListViewItem or 0 if not found. + */ +QListViewItem* NicksOnline::findNetworkRoot(const QString& name) +{ + QListViewItem* child; + for (child = getNickListView()->firstChild(); (child) ; child = child->nextSibling()) + { + if (child->text(0) == name) return child; + } + return 0; +} + +/** + * Return a string containing formatted additional information about a nick. + * @param nickInfo A pointer to NickInfo structure for the nick. May be Null. + * @param addressee Addressbook entry for the nick. May be empty. + * @return A string formatted for display containing the information + * about the nick. + * @return needWhois True if a WHOIS needs to be performed on the nick + * to get additional information. + */ +QString NicksOnline::getNickAdditionalInfo(NickInfoPtr nickInfo, KABC::Addressee addressee, +bool& needWhois) +{ + QString info; + if (!addressee.isEmpty()) + { + if (addressee.fullEmail().isEmpty()) + info += addressee.realName(); + else + info += addressee.fullEmail(); + } + QString niInfo; + if (nickInfo) + { + if (nickInfo->isAway()) + { + niInfo += i18n("Away"); + if (!nickInfo->getAwayMessage().isEmpty()) + niInfo += '(' + nickInfo->getAwayMessage() + ')'; + } + if (!nickInfo->getHostmask().isEmpty()) + niInfo += ' ' + nickInfo->getHostmask(); + if (!nickInfo->getRealName().isEmpty()) + niInfo += " (" + nickInfo->getRealName() + ')'; + if (!nickInfo->getNetServer().isEmpty()) + { + niInfo += i18n( " online via %1" ).arg( nickInfo->getNetServer() ); + if (!nickInfo->getNetServerInfo().isEmpty()) + niInfo += " (" + nickInfo->getNetServerInfo() + ')'; + } + if (!nickInfo->getOnlineSince().isNull()) + niInfo += i18n( " since %1" ).arg( nickInfo->getPrettyOnlineSince() ); + } + needWhois = niInfo.isEmpty(); + if (!info.isEmpty() && !needWhois) info += ' '; + return info + niInfo; +} + +/** + * Refresh the nicklistview for a single server. + * @param server The server to be refreshed. + */ +void NicksOnline::updateServerOnlineList(Server* servr) +{ + bool newNetworkRoot = false; + QString serverName = servr->getServerName(); + QString networkName = servr->getDisplayName(); + QListViewItem* networkRoot = findNetworkRoot(networkName); + // If network is not in our list, add it. + if (!networkRoot) + { + networkRoot = new NicksOnlineItem(NicksOnlineItem::NetworkRootItem,m_nickListView,networkName); + newNetworkRoot = true; + } + // Store server name in hidden column. + // Note that there could be more than one server in the network connected, + // but it doesn't matter because all the servers in a network have the same + // watch list. + networkRoot->setText(nlvcServerName, serverName); + // Update list of servers in the network that are connected. + QStringList serverList = QStringList::split(",", networkRoot->text(nlvcAdditionalInfo)); + if (!serverList.contains(serverName)) serverList.append(serverName); + networkRoot->setText(nlvcAdditionalInfo, serverList.join(",")); + // Get item in nicklistview for the Offline branch. + QListViewItem* offlineRoot = findItemType(networkRoot, NicksOnlineItem::OfflineItem); + if (!offlineRoot) + { + offlineRoot = new NicksOnlineItem(NicksOnlineItem::OfflineItem,networkRoot,i18n("Offline")); + offlineRoot->setText(nlvcServerName, serverName); + } + + // Get watch list. + QStringList watchList = servr->getWatchList(); + QStringList::iterator itEnd = watchList.end(); + QString nickname; + + for (QStringList::iterator it = watchList.begin(); it != itEnd; ++it) + { + nickname = (*it); + NickInfoPtr nickInfo = getOnlineNickInfo(networkName, nickname); + + if (nickInfo && nickInfo->getPrintedOnline()) + { + // Nick is online. + // Which server did NickInfo come from? + Server* server=nickInfo->getServer(); + // Get addressbook entry (if any) for the nick. + KABC::Addressee addressee = nickInfo->getAddressee(); + // Construct additional information string for nick. + bool needWhois = false; + QString nickAdditionalInfo = getNickAdditionalInfo(nickInfo, addressee, needWhois); + // Remove from offline branch if present. + QListViewItem* item = findItemChild(offlineRoot, nickname, NicksOnlineItem::NicknameItem); + if (item) delete item; + // Add to network if not already added. + QListViewItem* nickRoot = findItemChild(networkRoot, nickname, NicksOnlineItem::NicknameItem); + if (!nickRoot) nickRoot = new NicksOnlineItem(NicksOnlineItem::NicknameItem,networkRoot, nickname, nickAdditionalInfo); + nickRoot->setText(nlvcAdditionalInfo, nickAdditionalInfo); + nickRoot->setText(nlvcServerName, serverName); + // If no additional info available, request a WHOIS on the nick. + if (!m_whoisRequested) + { + if (needWhois) + { + requestWhois(networkName, nickname); + m_whoisRequested = true; + } + } + // Set Kabc icon if the nick is associated with an addressbook entry. + if (!addressee.isEmpty()) + nickRoot->setPixmap(nlvcKabc, m_kabcIconSet.pixmap( + QIconSet::Small, QIconSet::Normal, QIconSet::On)); + else + nickRoot->setPixmap(nlvcKabc, m_kabcIconSet.pixmap( + QIconSet::Small, QIconSet::Disabled, QIconSet::Off)); + + QStringList channelList = server->getNickChannels(nickname); + QStringList::iterator itEnd2 = channelList.end(); + + for (QStringList::iterator it2 = channelList.begin(); it2 != itEnd2; ++it2) + { + // Known channels where nickname is online and mode in each channel. + // FIXME: If user connects to multiple servers in same network, the + // channel info will differ between the servers, resulting in inaccurate + // mode and led info displayed. + + QString channelName = (*it2); + + ChannelNickPtr channelNick = server->getChannelNick(channelName, nickname); + QString nickMode; + if (channelNick->hasVoice()) nickMode = nickMode + i18n(" Voice"); + if (channelNick->isHalfOp()) nickMode = nickMode + i18n(" HalfOp"); + if (channelNick->isOp()) nickMode = nickMode + i18n(" Operator"); + if (channelNick->isOwner()) nickMode = nickMode + i18n(" Owner"); + if (channelNick->isAdmin()) nickMode = nickMode + i18n(" Admin"); + QListViewItem* channelItem = findItemChild(nickRoot, channelName, NicksOnlineItem::ChannelItem); + if (!channelItem) channelItem = new NicksOnlineItem(NicksOnlineItem::ChannelItem,nickRoot, + channelName, nickMode); + channelItem->setText(nlvcAdditionalInfo, nickMode); + + // Icon for mode of nick in each channel. + Images::NickPrivilege nickPrivilege = Images::Normal; + if (channelNick->hasVoice()) nickPrivilege = Images::Voice; + if (channelNick->isHalfOp()) nickPrivilege = Images::HalfOp; + if (channelNick->isOp()) nickPrivilege = Images::Op; + if (channelNick->isOwner()) nickPrivilege = Images::Owner; + if (channelNick->isAdmin()) nickPrivilege = Images::Admin; + if (server->getJoinedChannelMembers(channelName) != 0) + channelItem->setPixmap(nlvcChannel, + KonversationApplication::instance()->images()->getNickIcon(nickPrivilege, false)); + else + channelItem->setPixmap(nlvcChannel, + KonversationApplication::instance()->images()->getNickIcon(nickPrivilege, true)); + } + // Remove channel if nick no longer in it. + QListViewItem* child = nickRoot->firstChild(); + while (child) + { + QListViewItem* nextChild = child->nextSibling(); + if (channelList.find(child->text(nlvcNick)) == channelList.end()) + delete child; + child = nextChild; + } + } + else + { + // Nick is offline. + // Remove from online nicks, if present. + QListViewItem* item = findItemChild(networkRoot, nickname, NicksOnlineItem::NicknameItem); + if (item) delete item; + // Add to offline list if not already listed. + QListViewItem* nickRoot = findItemChild(offlineRoot, nickname, NicksOnlineItem::NicknameItem); + if (!nickRoot) nickRoot = new NicksOnlineItem(NicksOnlineItem::NicknameItem,offlineRoot, nickname); + nickRoot->setText(nlvcServerName, serverName); + // Get addressbook entry for the nick. + KABC::Addressee addressee = servr->getOfflineNickAddressee(nickname); + // Format additional information for the nick. + bool needWhois = false; + QString nickAdditionalInfo = getNickAdditionalInfo(0, addressee, needWhois); + nickRoot->setText(nlvcAdditionalInfo, nickAdditionalInfo); + // Set Kabc icon if the nick is associated with an addressbook entry. + if (!addressee.isEmpty()) + nickRoot->setPixmap(nlvcKabc, m_kabcIconSet.pixmap( + QIconSet::Small, QIconSet::Normal, QIconSet::On)); + else + nickRoot->setPixmap(nlvcKabc, m_kabcIconSet.pixmap( + QIconSet::Small, QIconSet::Disabled, QIconSet::Off)); + } + } + // Erase nicks no longer being watched. + QListViewItem* item = networkRoot->firstChild(); + while (item) + { + QListViewItem* nextItem = item->nextSibling(); + if (static_cast(item)->type() != NicksOnlineItem::OfflineItem) + { + QString nickname = item->text(nlvcNick); + if ((watchList.find(nickname) == watchList.end()) && + (serverName == item->text(nlvcServerName))) delete item; + } + item = nextItem; + } + item = offlineRoot->firstChild(); + + if(item) { + while (item) + { + QListViewItem* nextItem = item->nextSibling(); + QString nickname = item->text(nlvcNick); + if ((watchList.find(nickname) == watchList.end()) && + (serverName == item->text(nlvcServerName))) delete item; + item = nextItem; + } + } + else + { + delete offlineRoot; + } + // Expand server if newly added to list. + if (newNetworkRoot) + { + networkRoot->setOpen(true); + // Connect server NickInfo updates. + connect (servr, SIGNAL(nickInfoChanged(Server*, const NickInfoPtr)), + this, SLOT(slotNickInfoChanged(Server*, const NickInfoPtr))); + } +} + +/** + * Determines if a nick is online in any of the servers in a network and returns + * a NickInfo if found, otherwise 0. + * @param networkName Server network name. + * @param nickname Nick name. + * @return NickInfo if nick is online in any server, otherwise 0. + */ +NickInfoPtr NicksOnline::getOnlineNickInfo(QString& networkName, QString& nickname) +{ + // Get list of pointers to all servers. + KonversationApplication* konvApp = static_cast(kapp); + QPtrList serverList = konvApp->getConnectionManager()->getServerList(); + for (Server* server = serverList.first(); server; server = serverList.next()) + { + if (server->getDisplayName() == networkName) + { + NickInfoPtr nickInfo = server->getNickInfo(nickname); + if (nickInfo) return nickInfo; + } + } + return 0; +} + +/** + * Requests a WHOIS for a specified server network and nickname. + * The request is sent to the first server found in the network. + * @param groupName Server group name. + * @param nickname Nick name. + */ +void NicksOnline::requestWhois(QString& networkName, QString& nickname) +{ + KonversationApplication* konvApp = static_cast(kapp); + QPtrList serverList = konvApp->getConnectionManager()->getServerList(); + for (Server* server = serverList.first(); server; server = serverList.next()) + { + if (server->getDisplayName() == networkName) + { + server->requestWhois(nickname); + return; + } + } +} + +/** + * Refresh the nicklistview for all servers. + */ +void NicksOnline::refreshAllServerOnlineLists() +{ + KonversationApplication* konvApp = static_cast(kapp); + QPtrList serverList = konvApp->getConnectionManager()->getServerList(); + Server* server; + // Remove servers no longer connected. + QListViewItem* child = m_nickListView->firstChild(); + while (child) + { + QListViewItem* nextChild = child->nextSibling(); + QString networkName = child->text(nlvcNetwork); + QStringList serverNameList = QStringList::split(",", child->text(nlvcAdditionalInfo)); + QStringList::Iterator itEnd = serverNameList.end(); + QStringList::Iterator it = serverNameList.begin(); + while (it != itEnd) + { + QString serverName = *it; + // Locate server in server list. + bool found = false; + for (server = serverList.first(); server; server = serverList.next()) + { + if ((server->getServerName() == serverName) && + (server->getDisplayName() == networkName)) found = true; + } + if (!found) + it = serverNameList.remove(it); + else + ++it; + } + // Remove Networks with no servers connected, otherwise update list of connected + // servers. + if (serverNameList.empty()) + delete child; + else + child->setText(nlvcAdditionalInfo, serverNameList.join(",")); + child = nextChild; + } + // Display info for all currently-connected servers. + for (server = serverList.first(); server; server = serverList.next()) + { + updateServerOnlineList(server); + } + // Refresh addressbook buttons. + slotNickListView_SelectionChanged(); +} + +void NicksOnline::timerFired() +{ + // Allow one WHOIS request per cycle. + m_whoisRequested = false; + refreshAllServerOnlineLists(); +} + +/** + * When a user double-clicks a nickname in the nicklistview, let server know so that + * it can perform the user's chosen default action for that. + */ +void NicksOnline::processDoubleClick(QListViewItem* item) +{ + // Only emit signal when the user double clicked a nickname rather than + // a server name or channel name. + QString serverName; + QString nickname; + if (getItemServerAndNick(item, serverName, nickname)) + emit doubleClicked(serverName, nickname); +} + +/** + * Returns the server name and nickname of the specified nicklistview item. + * @param item The nicklistview item. + * @return serverName Name of the server for the nick at the item, or Null if not a nick. + * @return nickname The nickname at the item. + */ +bool NicksOnline::getItemServerAndNick(const QListViewItem* item, QString& serverName, QString& nickname) +{ + if (!item) return false; + // convert into NicksOnlineItem + const NicksOnlineItem* nlItem=static_cast(item); + // If on a network, return false; + if (nlItem->type() == NicksOnlineItem::NetworkRootItem) return false; + // get server name + serverName = item->text(nlvcServerName); + // If on a channel, move up to the nickname. + if (nlItem->type() == NicksOnlineItem::ChannelItem) + { + item = item->parent(); + serverName = item->text(nlvcServerName); + } + nickname = item->text(nlvcNick); + // offline columns are not nick names + if (nlItem->type() == NicksOnlineItem::OfflineItem) return false; + return true; +} + +NickInfoPtr NicksOnline::getNickInfo(const QListViewItem* item) +{ + QString serverName; + QString nickname; + + getItemServerAndNick(item, serverName, nickname); + + if (!serverName || !nickname) + return 0; + + Server* server = KonversationApplication::instance()->getConnectionManager()->getServerByName(serverName); + + if (server) return server->getNickInfo(nickname); + + return 0; +} + +/** + * Given a server name and nickname, returns the item in the Nick List View displaying + * the nick. + * @param serverName Name of server. + * @param nickname Nick name. + * @return Pointer to QListViewItem displaying the nick, or 0 if not found. + * + * @see getItemServerAndNick + */ +QListViewItem* NicksOnline::getServerAndNickItem(const QString& serverName, +const QString& nickname) +{ + Server* server = KonversationApplication::instance()->getConnectionManager()->getServerByName(serverName); + if (!server) return 0; + QString networkName = server->getDisplayName(); + QListViewItem* networkRoot = m_nickListView->findItem(networkName, nlvcNetwork); + if (!networkRoot) return 0; + QListViewItem* nickRoot = findItemChild(networkRoot, nickname, NicksOnlineItem::NicknameItem); + return nickRoot; +} + +/** + * Perform an addressbook command (edit contact, create new contact, + * change/delete association.) + * @param id The command id. @ref CommandIDs. + * + * The operation is performed on the nickname at the currently-selected item in + * the nicklistview. + * + * Also refreshes the nicklistview display to reflect the new addressbook state + * for the nick. + */ +void NicksOnline::doCommand(int id) +{ + if(id < 0) + { + return; + } + + QString serverName; + QString nickname; + QListViewItem* item = m_nickListView->selectedItem(); + + if(!getItemServerAndNick(item, serverName, nickname)) + { + return; + } + + // Get the server object corresponding to the server name. + Server* server = KonversationApplication::instance()->getConnectionManager()->getServerByName(serverName); + + if (!server) return; + + // Get NickInfo object corresponding to the nickname. + NickInfoPtr nickInfo = server->getNickInfo(nickname); + // Get addressbook entry for the nick. + KABC::Addressee addressee; + + if(nickInfo) + { + addressee = nickInfo->getAddressee(); + } + else + { + addressee = server->getOfflineNickAddressee(nickname); + } + + switch(id) + { + case ciSendEmail: + Konversation::Addressbook::self()->sendEmail(addressee); + return; //no need to refresh item + case ciAddressbookEdit: + Konversation::Addressbook::self()->editAddressee(addressee.uid()); + return; //no need to refresh item - nickinfo changed will be called anyway. + case ciAddressbookChange: + if(nickInfo) + { + nickInfo->showLinkAddressbookUI(); + } + else + { + LinkAddressbookUI *linkaddressbookui = new LinkAddressbookUI(server->getViewContainer()->getWindow(), NULL, nickname, server->getServerName(), server->getDisplayName(), addressee.realName()); + linkaddressbookui->show(); + } + break; + case ciAddressbookNew: + case ciAddressbookDelete: + { + Konversation::Addressbook *addressbook = Konversation::Addressbook::self(); + + if(addressbook && addressbook->getAndCheckTicket()) + { + if(id == ciAddressbookDelete) + { + if (addressee.isEmpty()) + { + return; + } + + addressbook->unassociateNick(addressee, nickname, server->getServerName(), server->getDisplayName()); + } + else + { + addressee.setGivenName(nickname); + addressee.setNickName(nickname); + addressbook->associateNickAndUnassociateFromEveryoneElse(addressee, nickname, server->getServerName(), server->getDisplayName()); + } + if(addressbook->saveTicket()) + { + //saveTicket will refresh the addressees for us. + if(id == ciAddressbookNew) + { + Konversation::Addressbook::self()->editAddressee(addressee.uid()); + } + } + } + break; + } + case ciJoinChannel: + { + // only join real channels + if (static_cast(m_nickListView->selectedItem())->type() == NicksOnlineItem::ChannelItem) + { + QString contactChannel = m_nickListView->selectedItem()->text(nlvcChannel); + server->queue( "JOIN "+contactChannel ); + } + break; + } + case ciWhois: + server->queue("WHOIS "+nickname); + return; + case ciOpenQuery: + NickInfoPtr nickInfo = server->obtainNickInfo(nickname); + class Query* query = server->addQuery(nickInfo, true /*we initiated*/); + emit showView(query); + return; + } + + refreshItem(item); +} + +/** + * Get the addressbook state of the nickname at the specified nicklistview item. + * @param item Item of the nicklistview. + * @return Addressbook state. + * 0 = not a nick, 1 = nick has no addressbook association, 2 = nick has association + */ +int NicksOnline::getNickAddressbookState(QListViewItem* item) +{ + int nickState = nsNotANick; + QString serverName; + QString nickname; + if (getItemServerAndNick(item, serverName, nickname)) + { + Server *server = KonversationApplication::instance()->getConnectionManager()->getServerByName(serverName); + if (!server) return nsNotANick; + NickInfoPtr nickInfo = server->getNickInfo(nickname); + if (nickInfo) + { + if (nickInfo->getAddressee().isEmpty()) + nickState = nsNoAddress; + else + nickState = nsHasAddress; + } + else + { + if (server->getOfflineNickAddressee(nickname).isEmpty()) + nickState = nsNoAddress; + else + nickState = nsHasAddress; + } + } + return nickState; +} + +/** + * Sets the enabled/disabled state and labels of the addressbook buttons + * based on the given nick addressbook state. + * @param nickState The state of the nick. 1 = not associated with addressbook, + * 2 = associated with addressbook. @ref getNickAddressbookState. + */ +void NicksOnline::setupAddressbookButtons(int nickState) +{ + switch (nickState) + { + case nsNotANick: + { + m_editContactButton->setEnabled(false); + m_changeAssociationButton->setEnabled(false); + m_deleteAssociationButton->setEnabled(false); + break; + } + case nsNoAddress: + { + m_editContactButton->setText(i18n("Create New C&ontact...")); + m_editContactButton->setEnabled(true); + m_changeAssociationButton->setText(i18n("&Choose Association...")); + m_changeAssociationButton->setEnabled(true); + m_deleteAssociationButton->setEnabled(false); + break; + } + case nsHasAddress: + { + m_editContactButton->setText(i18n("Edit C&ontact...")); + m_editContactButton->setEnabled(true); + m_changeAssociationButton->setText(i18n("&Change Association...")); + m_changeAssociationButton->setEnabled(true); + m_deleteAssociationButton->setEnabled(true); + break; + } + } +} + +/** + * Received when user clicks the Edit Contact (or New Contact) button. + */ +void NicksOnline::slotEditContactButton_Clicked() +{ + switch (getNickAddressbookState(m_nickListView->selectedItem())) + { + case nsNotANick: break; + case nsNoAddress: { doCommand(ciAddressbookNew); break; } + case nsHasAddress: { doCommand(ciAddressbookEdit); break; } + } +} + +/** + * Received when user clicks the Change Association button. + */ +void NicksOnline::slotChangeAssociationButton_Clicked() { doCommand(ciAddressbookChange); } +/** + * Received when user clicks the Delete Association button. + */ +void NicksOnline::slotDeleteAssociationButton_Clicked() { doCommand(ciAddressbookDelete); } +/** + * Received when user selects a different item in the nicklistview. + */ +void NicksOnline::slotNickListView_SelectionChanged() +{ + QListViewItem* item = m_nickListView->selectedItem(); + int nickState = getNickAddressbookState(item); + setupAddressbookButtons(nickState); +} + +/** + * Received when right-clicking an item in the NickListView. + */ +void NicksOnline::slotNickListView_RightButtonClicked(QListViewItem* item, const QPoint& pt) +{ + if (!item) return; + m_popupMenu->clear(); + int nickState = getNickAddressbookState(item); + switch (nickState) + { + case nsNotANick: + { + break; + } + case nsNoAddress: + { + m_popupMenu->insertItem(i18n("&Choose Association..."), ciAddressbookChange); + m_popupMenu->insertItem(i18n("Create New C&ontact..."), ciAddressbookNew); + m_popupMenu->insertSeparator(); + m_popupMenu->insertItem(i18n("&Whois"), ciWhois); + m_popupMenu->insertItem(i18n("Open &Query"), ciOpenQuery); + if (item->text(nlvcServerName).isEmpty()) + m_popupMenu->insertItem(i18n("&Join Channel"), ciJoinChannel); + break; + } + case nsHasAddress: + { + m_popupMenu->insertItem(SmallIcon("mail_generic"), i18n("&Send Email..."), ciSendEmail); + m_popupMenu->insertSeparator(); + m_popupMenu->insertItem(SmallIcon("contents"), i18n("Edit C&ontact..."), ciAddressbookEdit); + m_popupMenu->insertSeparator(); + m_popupMenu->insertItem(i18n("&Change Association..."), ciAddressbookChange); + m_popupMenu->insertItem(SmallIconSet("editdelete"), i18n("&Delete Association"), ciAddressbookDelete); + m_popupMenu->insertSeparator(); + m_popupMenu->insertItem(i18n("&Whois"), ciWhois); + m_popupMenu->insertItem(i18n("Open &Query"), ciOpenQuery); + if (item->text(nlvcServerName).isEmpty()) + m_popupMenu->insertItem(i18n("&Join Channel"), ciJoinChannel); + break; + } + } + if (nickState != nsNotANick) + m_popupMenu->popup(pt); +} + +/** + * Received from popup menu when user chooses something. + */ +void NicksOnline::slotPopupMenu_Activated(int id) +{ + doCommand(id); +} + +/** + * Received from server when a NickInfo changes its information. + */ +void NicksOnline::slotNickInfoChanged(Server* server, const NickInfoPtr nickInfo) +{ + if (!nickInfo) return; + QString nickname = nickInfo->getNickname(); + + if (!server) return; + QString serverName = server->getServerName(); + QListViewItem* item = getServerAndNickItem(serverName, nickname); + refreshItem(item); +} + +/** + * Refreshes the information for the given item in the list. + * @param item Pointer to listview item. + */ +void NicksOnline::refreshItem(QListViewItem* item) +{ + if (!item) return; + QString serverName; + QString nickname; + if (getItemServerAndNick(item, serverName, nickname)) + { + Server *server = KonversationApplication::instance()->getConnectionManager()->getServerByName(serverName); + if (server) + { + NickInfoPtr nickInfo = server->getNickInfo(nickname); + KABC::Addressee addressee; + if (nickInfo) + addressee = nickInfo->getAddressee(); + else + addressee = server->getOfflineNickAddressee(nickname); + int nickState = 2; + if (addressee.isEmpty()) nickState = 1; + switch (nickState) + { + case nsNotANick: + break; + case nsNoAddress: + { + item->setPixmap(nlvcKabc, m_kabcIconSet.pixmap( + QIconSet::Small, QIconSet::Disabled, QIconSet::Off)); break; + } + case nsHasAddress: + { + item->setPixmap(nlvcKabc, m_kabcIconSet.pixmap( + QIconSet::Small, QIconSet::Normal, QIconSet::On)); break; + } + } + QString nickAdditionalInfo; + bool needWhois = false; + if (nickInfo) nickAdditionalInfo = getNickAdditionalInfo(nickInfo, addressee, + needWhois); + item->setText(nlvcAdditionalInfo, nickAdditionalInfo); + if (item == m_nickListView->selectedItem()) setupAddressbookButtons(nickState); + } + } +} + +void NicksOnline::childAdjustFocus() {} + +#include "nicksonline.moc" + +// kate: space-indent on; tab-width 4; indent-width 4; mixed-indent off; replace-tabs on; +// vim: set et sw=4 ts=4 cino=l1,cs,U1: diff --git a/konversation/src/nicksonline.h b/konversation/src/nicksonline.h new file mode 100644 index 0000000..6243b78 --- /dev/null +++ b/konversation/src/nicksonline.h @@ -0,0 +1,261 @@ +/* + 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. +*/ + +/* + shows a user tree of friends per server + begin: Sam Aug 31 2002 + copyright: (C) 2002 by Dario Abatianni + email: eisfuchs@tigress.com +*/ + +#ifndef NICKSONLINE_H +#define NICKSONLINE_H + +#include "nickinfo.h" +#include "nicksonlineitem.h" +#include "chatwindow.h" +#include "linkaddressbook/nicksonlinetooltip.h" + +#include +#include +#include + + +class KListView; +class QPushButton; +class QPopupMenu; + +class ChatWindow; + +class NicksOnline : public ChatWindow +{ + Q_OBJECT + + public: + // Columns of the NickListView. + enum NickListViewColumn + { + nlvcNetworkNickChannel = 0, + nlvcNetwork = 0, + nlvcNick = 0, + nlvcChannel = 0, + nlvcKabc = 1, + nlvcAdditionalInfo = 1, + nlvcServerName = 2 // hidden + }; + // Ids associated with menu/button commands. + enum CommandIDs + { + ciAddressbookChange, ciAddressbookNew, ciAddressbookDelete, ciAddressbookEdit, + ciSendEmail, ciWhois, ciJoinChannel, ciOpenQuery + }; + enum NickState + { + nsNotANick = 0, // User didn't click on a nickname. + nsNoAddress = 1, // Nick does not have an addressbook association. + nsHasAddress = 2 // Nick has an associated addressbook entry. + }; + + explicit NicksOnline(QWidget* parent); + ~NicksOnline(); + + // These are here for the benefit of NicksOnlineTooltip. + KListView* getNickListView(); + NickInfoPtr getNickInfo(const QListViewItem* item); + + virtual bool canBeFrontView() { return true; } + + signals: + /** + * Emitted when user clicks Edit Watch List button. + */ + void editClicked(); + /** + * Emitted whenever user double-clicks a nick in the Nicks Online tab. + */ + void doubleClicked(const QString& server,const QString& nick); + + void showView(ChatWindow* view); + + public slots: + + /** + * Refresh the nicklistview for a single server. + * @param server The server to be refreshed. + */ + void updateServerOnlineList(Server* server); + + protected slots: + /** + * When a user double-clicks a nickname in the nicklistview, let server know so that + * it can perform the user's chosen default action for that. + */ + void processDoubleClick(QListViewItem* item); + /** + * Timer used to refresh display. + */ + void timerFired(); + /** + * Received when user clicks the Edit Contact (or New Contact) button. + */ + void slotEditContactButton_Clicked(); + /** + * Received when user clicks the Change Association button. + */ + void slotChangeAssociationButton_Clicked(); + /** + * Received when user clicks the Delete Association button. + */ + void slotDeleteAssociationButton_Clicked(); + /** + * Received when user selects a different item in the nicklistview. + */ + void slotNickListView_SelectionChanged(); + /** + * Received when right-clicking an item in the NickListView. + */ + void slotNickListView_RightButtonClicked(QListViewItem* item, const QPoint& pt); + /** + * Received from server when a NickInfo changes its information. + */ + void slotNickInfoChanged(Server* server, const NickInfoPtr nickInfo); + /** + * Received from popup menu when user chooses something. + */ + void slotPopupMenu_Activated(int id); + + protected: + /** Called from ChatWindow adjustFocus */ + virtual void childAdjustFocus(); + + private: + /** + * Returns the named child of parent item in a NicksOnlineItem + * @param parent Pointer to a NicksOnlineItem. + * @param name The name in the desired child QListViewItem, must be in column 0. + * @param type The type of entry to be found + * @return Pointer to the child QListViewItem or 0 if not found. + */ + QListViewItem* findItemChild(const QListViewItem* parent, const QString& name, NicksOnlineItem::NickListViewColumn type); + /** + * Returns the first occurrence of a child item of a given type in a NicksOnlineItem + * @param parent Pointer to a NicksOnlineItem. + * @param type The type of entry to be found + * @return Pointer to the child QListViewItem or 0 if not found. + */ + QListViewItem* findItemType(const QListViewItem* parent, NicksOnlineItem::NickListViewColumn type); + /** + * Returns a pointer to the network QListViewItem with the given name. + * @param name The name of the network, assumed to be in column 0 of the item. + * @return Pointer to the QListViewItem or 0 if not found. + */ + QListViewItem* findNetworkRoot(const QString& name); + /** + * Refresh the nicklistview for all servers. + */ + void refreshAllServerOnlineLists(); + /** + * Refreshes the information for the given item in the list. + * @param item Pointer to listview item. + */ + void refreshItem(QListViewItem* item); + /** + * Return a string containing formatted additional information about a nick. + * @param nickInfo A pointer to NickInfo structure for the nick. + * @return A string formatted for display containing the information + * about the nick. + * @return needWhois True if a WHOIS needs to be performed on the nick + * to get additional information. + */ + QString getNickAdditionalInfo(NickInfoPtr nickInfo, KABC::Addressee addressee, + bool& needWhois); + /** + * Invokes the KAddressBook contact editor for the specified contact id. + * @param uid Id of the contact. + * @return False if unable to invoke the Contact editor. + */ + bool editAddressee(const QString &uid); + /** + * Returns the server name and nickname of the specified nicklistview item. + * @param item The nicklistview item. + * @return serverName Name of the server for the nick at the item, or Null if not a nick. + * @return nickname The nickname at the item. + */ + bool getItemServerAndNick(const QListViewItem* item, QString& serverName, QString& nickname); + /** + * Given a server name and nickname, returns the item in the Nick List View displaying + * the nick. + * @param serverName Name of server.Server + * @param nickname Nick name. + * @return Pointer to QListViewItem displaying the nick, or 0 if not found. + * + * @see getItemServerAndNick + */ + QListViewItem* getServerAndNickItem(const QString& serverName, const QString& nickname); + /** + * Perform an addressbook command (edit contact, create new contact, + * change/delete association.) + * @param id The command id. @ref CommandIDs. + * + * The operation is performed on the nickname at the currently-selected item in + * the nicklistview. + * + * Also refreshes the nicklistview display to reflect the new addressbook state + * for the nick. + */ + void doCommand(int id); + /** + * Get the addressbook state of the nickname at the specified nicklistview item. + * @param item Item of the nicklistview. + * @return Addressbook state. + * 0 = not a nick, 1 = nick has no addressbook association, 2 = nick has association + */ + int getNickAddressbookState(QListViewItem* item); + /** + * Sets the enabled/disabled state and labels of the addressbook buttons + * based on the given nick addressbook state. + * @param nickState The state of the nick. 1 = not associated with addressbook, + * 2 = associated with addressbook. @ref getNickAddressbookState. + */ + void setupAddressbookButtons(int nickState); + /** + * Determines if a nick is online in any of the servers in a network and returns + * a NickInfo if found, otherwise 0. + * @param networkName Server network name. + * @param nickname Nick name. + * @return NickInfo if nick is online in any server, otherwise 0. + */ + NickInfoPtr getOnlineNickInfo(QString& networkName, QString& nickname); + /** + * Requests a WHOIS for a specified server network and nickname. + * The request is sent to the first server found in the network. + * @param groupName Server group name. + * @param nickname Nick name. + */ + void requestWhois(QString& networkName, QString& nickname); + + // The main display of networks, nicks, and channels. + KListView* m_nickListView; + // Buttons on screen. + QPushButton* m_editContactButton; + QPushButton* m_changeAssociationButton; + QPushButton* m_deleteAssociationButton; + // Context menu when right-clicking a nick. + QPopupMenu* m_popupMenu; + // Helper to display tooltip information for nicks. + Konversation::KonversationNicksOnlineToolTip *m_tooltip; + // A string containing the identifier for the "Offline" listview item + QString c_offline; + // Timer for refreshing display and generating WHOISes. + QTimer* m_timer; + // Addressbook icon. + QIconSet m_kabcIconSet; + /* Set to False every 8 seconds so that we generate a WHOIS on watch nicks that + lack information.*/ + bool m_whoisRequested; +}; +#endif diff --git a/konversation/src/nicksonlineitem.cpp b/konversation/src/nicksonlineitem.cpp new file mode 100644 index 0000000..cd8cd1d --- /dev/null +++ b/konversation/src/nicksonlineitem.cpp @@ -0,0 +1,52 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni +*/ + +#include "nicksonlineitem.h" + + +NicksOnlineItem::NicksOnlineItem(int type, QListView* parent, const QString& name, const QString& col2) : + KListViewItem(parent, name, col2) +{ + m_type=type; +} + +NicksOnlineItem::NicksOnlineItem(int type, QListViewItem* parent, const QString& name, const QString& col2) : + KListViewItem(parent, name, col2) +{ + m_type=type; +} + +/** + * Reimplemented to make sure, "Offline" items always get sorted to the bottom of the list + * @param i Pointer to the QListViewItem to compare with. + * @param col The column to compare + * @param ascending Specify sorting direction + * @return -1 if this item's value is smaller than i, 0 if they are equal, 1 if it's greater + */ +int NicksOnlineItem::compare(QListViewItem* i,int col,bool ascending) const +{ + // if we are the Offline item, make sure we get sorted at the end of the list + if(m_type==OfflineItem) return ascending ? 1 : -1; + // if we are competing with an Offline item, always lose + if(static_cast(i)->type()==OfflineItem) return ascending ? -1 : 1; + + // otherwise compare items case-insensitively + return key(col,ascending).lower().localeAwareCompare(i->key(col,ascending).lower()); +} + +/** + * Returns the type of the item. + * @return One of the enum NickListViewColumn + */ +int NicksOnlineItem::type() const +{ + return m_type; +} diff --git a/konversation/src/nicksonlineitem.h b/konversation/src/nicksonlineitem.h new file mode 100644 index 0000000..5711e60 --- /dev/null +++ b/konversation/src/nicksonlineitem.h @@ -0,0 +1,58 @@ +/* + 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. +*/ + +/* + Copyright (C) 2006 Dario Abatianni +*/ + +#ifndef NICKSONLINEITEM_H +#define NICKSONLINEITEM_H + +#include + + +class NicksOnlineItem : public KListViewItem +{ + public: + enum NickListViewColumn + { + NetworkRootItem=0, // TODO: not used yet + NicknameItem=1, // TODO: not used yet + ChannelItem=2, // TODO: not used yet + OfflineItem=3 // this item is the "Offline" item + }; + + NicksOnlineItem(int type, + QListView* parent, + const QString& name, + const QString& col2 = QString()); + + NicksOnlineItem(int type, + QListViewItem* parent, + const QString& name, + const QString& col2 = QString()); + + /** + * Reimplemented to make sure, "Offline" items always get sorted to the bottom of the list + * @param i Pointer to the QListViewItem to compare with. + * @param col The column to compare + * @param ascending Specify sorting direction + * @return -1 if this item's value is smaller than i, 0 if they are equal, 1 if it's greater + */ + virtual int compare(QListViewItem* i,int col,bool ascending) const; + + /** + * Returns the type of the item. + * @return One of the enum NickListViewColumn + */ + int type() const; + + protected: + int m_type; +}; + +#endif diff --git a/konversation/src/notificationhandler.cpp b/konversation/src/notificationhandler.cpp new file mode 100644 index 0000000..f8477e9 --- /dev/null +++ b/konversation/src/notificationhandler.cpp @@ -0,0 +1,334 @@ +/* + 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. +*/ + +/* + copyright: (C) 2004 by Peter Simonsson + email: psn@linux.se +*/ + +#include "notificationhandler.h" +#include "common.h" +#include "chatwindow.h" +#include "konversationapplication.h" +#include "konversationmainwindow.h" +#include "viewcontainer.h" +#include "trayicon.h" +#include "server.h" + +#include + +#include +#include +#include + + +namespace Konversation +{ + + NotificationHandler::NotificationHandler(KonversationApplication* parent, const char* name) + : QObject(parent, name) + { + m_mainWindow = parent->getMainWindow(); + } + + NotificationHandler::~NotificationHandler() + { + } + + void NotificationHandler::message(ChatWindow* chatWin, const QString& fromNick, const QString& message) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + QString cleanedMessage = QStyleSheet::escape(Konversation::removeIrcMarkup(message)); + QString cutup = addLineBreaks(cleanedMessage); + + KNotifyClient::event(m_mainWindow->winId(), "message", QString("<%1> %2").arg(fromNick).arg(cutup)); + + if(!Preferences::trayNotifyOnlyOwnNick()) + { + startTrayNotification(chatWin); + } + + if(Preferences::oSDShowChannel() && + (!m_mainWindow->isActiveWindow() || (chatWin != m_mainWindow->getViewContainer()->getFrontView()))) + { + KonversationApplication* konvApp = static_cast(kapp); + konvApp->osd->showOSD('(' + chatWin->getName() + ") <" + fromNick + "> " + cleanedMessage); + } + } + + void NotificationHandler::nick(ChatWindow* chatWin, const QString& fromNick, const QString& message) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + QString cleanedMessage = QStyleSheet::escape(Konversation::removeIrcMarkup(message)); + QString cutup = addLineBreaks(cleanedMessage); + + KNotifyClient::event(m_mainWindow->winId(), "nick", QString("<%1> %2").arg(fromNick).arg(cutup)); + + startTrayNotification(chatWin); + + KonversationApplication* konvApp = static_cast(kapp); + + if((Preferences::oSDShowChannel() || Preferences::oSDShowOwnNick()) && + (!m_mainWindow->isActiveWindow() || + (chatWin != m_mainWindow->getViewContainer()->getFrontView()))) + { + konvApp->osd->showOSD(i18n("[HighLight] (%1) <%2> %3").arg(chatWin->getName()).arg(fromNick).arg(cleanedMessage)); + } + } + + void NotificationHandler::queryMessage(ChatWindow* chatWin, + const QString& fromNick, const QString& message) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + QString cleanedMessage = QStyleSheet::escape(Konversation::removeIrcMarkup(message)); + QString cutup = addLineBreaks(cleanedMessage); + + KNotifyClient::event(m_mainWindow->winId(), "queryMessage", QString("<%1> %2").arg(fromNick).arg(cutup)); + + startTrayNotification(chatWin); + + KonversationApplication* konvApp = static_cast(kapp); + + if(Preferences::oSDShowQuery() && (!m_mainWindow->isActiveWindow() || + (chatWin != m_mainWindow->getViewContainer()->getFrontView()))) + { + konvApp->osd->showOSD(i18n("[Query] <%1> %2").arg(fromNick).arg(cleanedMessage)); + } + } + + void NotificationHandler::startTrayNotification(ChatWindow* chatWin) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (!chatWin->getServer() || (Preferences::disableNotifyWhileAway() && chatWin->getServer()->isAway())) + return; + + if (!m_mainWindow->isActiveWindow() && chatWin->getServer()->isConnected()) + m_mainWindow->systemTrayIcon()->startNotification(); + } + + void NotificationHandler::join(ChatWindow* chatWin, const QString& nick) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + KNotifyClient::event(m_mainWindow->winId(), "join", i18n("%1 joined %2").arg(nick, chatWin->getName())); + + // OnScreen Message + if(Preferences::oSDShowChannelEvent() && + (!m_mainWindow->isActiveWindow() || (chatWin != m_mainWindow->getViewContainer()->getFrontView()))) + { + KonversationApplication* konvApp = static_cast(kapp); + konvApp->osd->showOSD(i18n("%1 joined %2").arg(nick, chatWin->getName())); + } + } + + void NotificationHandler::part(ChatWindow* chatWin, const QString& nick) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + KNotifyClient::event(m_mainWindow->winId(), "part", i18n("%1 parted %2").arg(nick, chatWin->getName())); + + // OnScreen Message + if(Preferences::oSDShowChannelEvent() && + (!m_mainWindow->isActiveWindow() || (chatWin != m_mainWindow->getViewContainer()->getFrontView()))) + { + KonversationApplication* konvApp = static_cast(kapp); + konvApp->osd->showOSD(i18n("%1 parted %2").arg(nick, chatWin->getName())); + } + } + + void NotificationHandler::quit(ChatWindow* chatWin, const QString& nick) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + KNotifyClient::event(m_mainWindow->winId(), "part", i18n("%1 quit %2").arg(nick, chatWin->getServer()->getServerName())); + } + + void NotificationHandler::nickChange(ChatWindow* chatWin, const QString& oldNick, const QString& newNick) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + KNotifyClient::event(m_mainWindow->winId(), "nickchange", i18n("%1 changed nickname to %2").arg(oldNick, newNick)); + } + + void NotificationHandler::dccIncoming(ChatWindow* chatWin, const QString& fromNick) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + KNotifyClient::event(m_mainWindow->winId(), "dcc_incoming", i18n("%1 wants to send a file to you").arg(fromNick)); + } + + void NotificationHandler::mode(ChatWindow* chatWin, const QString& /*nick*/) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + KNotifyClient::event(m_mainWindow->winId(), "mode"); + } + + void NotificationHandler::query(ChatWindow* chatWin, const QString& fromNick) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + startTrayNotification(chatWin); + + KNotifyClient::event(m_mainWindow->winId(), "query", + i18n("%1 has started a conversation (query) with you.").arg(fromNick)); + } + + void NotificationHandler::nickOnline(ChatWindow* chatWin, const QString& nick) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + KNotifyClient::event(m_mainWindow->winId(), "notify", + i18n("%1 is online (%2).").arg(nick).arg(chatWin->getServer()->getServerName())); + } + + void NotificationHandler::nickOffline(ChatWindow* chatWin, const QString& nick) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + KNotifyClient::event(m_mainWindow->winId(), "notify", + i18n("%1 went offline (%2).").arg(nick).arg(chatWin->getServer()->getServerName())); + } + + void NotificationHandler::kick(ChatWindow* chatWin, const QString& channel,const QString& nick) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + KNotifyClient::event(m_mainWindow->winId(), "kick", + i18n("You are kicked by %1 from %2").arg(nick).arg(channel)); + } + + void NotificationHandler::dccChat(ChatWindow* chatWin, const QString& nick) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + KNotifyClient::event(m_mainWindow->winId(), "dccChat", + i18n("%1 started a dcc chat with you").arg(nick)); + } + + void NotificationHandler::highlight(ChatWindow* chatWin, const QString& fromNick, const QString& message) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + startTrayNotification(chatWin); + + if(Preferences::oSDShowOwnNick() && + (!m_mainWindow->isActiveWindow() || (chatWin != m_mainWindow->getViewContainer()->getFrontView()))) + { + KonversationApplication* konvApp = static_cast(kapp); + // if there was no nick associated, this must be a command message, so don't try displaying + // an empty nick in <> + if(fromNick.isEmpty()) + konvApp->osd->showOSD(i18n("[HighLight] (%1) *** %2").arg(chatWin->getName()).arg(message)); + // normal highlight message + else + konvApp->osd->showOSD(i18n("[HighLight] (%1) <%2> %3").arg(chatWin->getName()).arg(fromNick).arg(message)); + } + } + + void NotificationHandler::connectionFailure(ChatWindow* chatWin, const QString& server) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + KNotifyClient::event(m_mainWindow->winId(), "connectionFailure", + i18n("Failed to connect to %1").arg(server)); + } + + void NotificationHandler::channelJoin(ChatWindow* chatWin, const QString& channel) + { + if (!chatWin || !chatWin->notificationsEnabled()) + return; + + if (Preferences::disableNotifyWhileAway() && chatWin->getServer() && chatWin->getServer()->isAway()) + return; + + KNotifyClient::event(m_mainWindow->winId(), "channelJoin", i18n("You have joined %1.").arg(channel)); + } + + QString NotificationHandler::addLineBreaks(const QString& string) + { + QString cutup = string; + int offset = 0; + + for(uint i = 0; i < string.length(); i += 50) + { + cutup.insert(i + (offset * 4), "
"); + ++offset; + } + + return cutup; + } + +} + +#include "notificationhandler.moc" diff --git a/konversation/src/notificationhandler.h b/konversation/src/notificationhandler.h new file mode 100644 index 0000000..1f7319c --- /dev/null +++ b/konversation/src/notificationhandler.h @@ -0,0 +1,61 @@ +/* + 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. +*/ + +/* + copyright: (C) 2004 by Peter Simonsson + email: psn@linux.se +*/ +#ifndef KONVERSATIONNOTIFICATIONHANDLER_H +#define KONVERSATIONNOTIFICATIONHANDLER_H + +#include + + +class ChatWindow; +class KonversationApplication; +class KonversationMainWindow; + +namespace Konversation +{ + + class NotificationHandler : public QObject + { + Q_OBJECT + + public: + explicit NotificationHandler(KonversationApplication* parent = 0, const char* name = 0); + ~NotificationHandler(); + + public slots: + void message(ChatWindow* chatWin, const QString& fromNick, const QString& message); + void nick(ChatWindow* chatWin, const QString& fromNick, const QString& message); + void join(ChatWindow* chatWin, const QString& nick); + void part(ChatWindow* chatWin, const QString& nick); + void quit(ChatWindow* chatWin, const QString& nick); + void nickChange(ChatWindow* chatWin, const QString& oldNick, const QString& newNick); + void dccIncoming(ChatWindow* chatWin, const QString& fromNick); + void mode(ChatWindow* chatWin, const QString& nick); + void query(ChatWindow* chatWin, const QString& fromNick); + void queryMessage(ChatWindow* chatWin, const QString& fromNick, const QString& message); + void nickOnline(ChatWindow* chatWin, const QString& nick); + void nickOffline(ChatWindow* chatWin, const QString& nick); + void kick(ChatWindow* chatWin, const QString& channel,const QString& nick); + void dccChat(ChatWindow* chatWin, const QString& nick); + void highlight(ChatWindow* chatWin, const QString& fromNick, const QString& message); + void connectionFailure(ChatWindow* chatWin, const QString& server); + void channelJoin(ChatWindow* chatWin, const QString& channel); + + protected: + void startTrayNotification(ChatWindow* chatWin); + QString addLineBreaks(const QString& string); + + private: + KonversationMainWindow* m_mainWindow; + }; + +} +#endif diff --git a/konversation/src/osd.cpp b/konversation/src/osd.cpp new file mode 100644 index 0000000..ce173ab --- /dev/null +++ b/konversation/src/osd.cpp @@ -0,0 +1,446 @@ +/* +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. +*/ + +/* + Provides an interface to a plain QWidget, which is independent of KDE (bypassed to X11) + begin: Fre Sep 26 2003 + Copyright (C) 2003 Christian Muehlhaeuser + Copyright (C) 2004 Michael Goettsche +*/ + +#include "osd.h" +#include "konversationapplication.h" +#include "common.h" + +#include +#include +#include +#include + +#include +#include +#include +#include //unsetColors() + +#include //reposition() + + +OSDWidget::OSDWidget( const QString &appName, QWidget *parent, const char *name ) +: QWidget( parent, name, WNoAutoErase | WStyle_Customize | WX11BypassWM | WStyle_StaysOnTop | WStyle_Tool ) +, m_appName( appName ) +, m_duration( 5000 ) +, m_shadow( true ) +, m_alignment( Middle ) +, m_screen( 0 ) +, m_y( MARGIN ) +, m_dirty( false ) +{ + setFocusPolicy( NoFocus ); + setBackgroundMode( NoBackground ); + unsetColors(); + + connect( &timer, SIGNAL( timeout() ), SLOT( hide() ) ); + connect( &timerMin, SIGNAL( timeout() ), SLOT( minReached() ) ); +} + +void OSDWidget::renderOSDText( const QString &txt ) +{ + // Escaped text + QString text = Konversation::removeIrcMarkup(txt); + + static QBitmap mask; + + //This is various spacings and margins, based on the font to look "just right" + const uint METRIC = fontMetrics().width( 'x' ); + + // Set a sensible maximum size, don't cover the whole desktop or cross the screen + QSize max = QApplication::desktop()->screen( m_screen )->size() - QSize( MARGIN*2 + METRIC*2, 100 ); + QFont titleFont( "Arial", 12, QFont::Bold ); + QFontMetrics titleFm( titleFont ); + + // The title cannnot be taller than one line + // AlignAuto = align Arabic to the right, etc. + QRect titleRect = titleFm.boundingRect( 0, 0, max.width() - METRIC, titleFm.height(), AlignAuto, m_appName ); + // The osd cannot be larger than the screen + QRect textRect = fontMetrics().boundingRect( 0, 0, max.width(), max.height(), AlignAuto | WordBreak, text ); + + if ( textRect.width() < titleRect.width() ) + textRect.setWidth( titleRect.width() ); + + //this should still be within the screen bounds + textRect.addCoords( 0, 0, METRIC*2, titleRect.height() + METRIC ); + + osdBuffer.resize( textRect.size() ); + mask.resize( textRect.size() ); + + // Start painting! + QPainter bufferPainter( &osdBuffer ); + QPainter maskPainter( &mask ); + + // Draw backing rectangle + const uint xround = (METRIC * 200) / textRect.width(); + const uint yround = (METRIC * 200) / textRect.height(); + + bufferPainter.setPen( Qt::black ); + bufferPainter.setBrush( backgroundColor() ); + bufferPainter.drawRoundRect( textRect, xround, yround ); + bufferPainter.setFont( font() ); + + const uint w = textRect.width() - 1; + const uint h = textRect.height() - 1; + + // Draw the text shadow + if ( m_shadow ) + { + bufferPainter.setPen( backgroundColor().dark( 175 ) ); + bufferPainter.drawText( METRIC + 3, (METRIC/2) + titleFm.height() + 1, w, h, AlignLeft | WordBreak, text ); + } + + // Draw the text + bufferPainter.setPen( foregroundColor() ); + bufferPainter.drawText( METRIC, (METRIC/2) + titleFm.height() - 1, w, h, AlignLeft | WordBreak, text ); + + // Draw the title text + bufferPainter.setFont( titleFont ); + bufferPainter.drawText( METRIC * 2, (METRIC/2), w, h, AlignLeft, m_appName ); + + // Masking for transparency + mask.fill( Qt::black ); + maskPainter.setBrush( Qt::white ); + maskPainter.drawRoundRect( textRect, xround, yround ); + setMask( mask ); + + //do last to reduce noticeable change when showing multiple OSDs in succession + reposition( textRect.size() ); + + m_currentText = text; + m_dirty = false; + + update(); +} + + // slot +void OSDWidget::showOSD( const QString &text, bool preemptive ) +{ + if ( isEnabled() && !text.isEmpty() ) + { + + QString plaintext = text.copy(); + plaintext.replace(QRegExp("]*>"), QString("")); + plaintext.replace(QString("<"), QString("<")); + plaintext.replace(QString(">"), QString(">")); + plaintext.replace(QString("&"), QString("&")); + + if ( preemptive || !timerMin.isActive() ) + { + m_currentText = plaintext; + m_dirty = true; + + show(); + } + else textBuffer.append( plaintext ); //queue + } +} + +void OSDWidget::minReached() //SLOT +{ + if ( !textBuffer.isEmpty() ) + { + renderOSDText( textBuffer.front() ); + textBuffer.pop_front(); + + if( m_duration ) + //timerMin is still running + timer.start( m_duration, true ); + } + else timerMin.stop(); +} + +void OSDWidget::setDuration( int ms ) +{ + m_duration = ms; + + if( !m_duration ) timer.stop(); +} + +void OSDWidget::setFont( QFont newFont ) +{ + QWidget::setFont( newFont ); + refresh(); +} + +void OSDWidget::setShadow( bool shadow ) +{ + m_shadow = shadow; + refresh(); +} + +void OSDWidget::setTextColor( const QColor &newColor ) +{ + setPaletteForegroundColor( newColor ); + refresh(); +} + +void OSDWidget::setBackgroundColor( const QColor &newColor ) +{ + setPaletteBackgroundColor( newColor ); + refresh(); +} + +void OSDWidget::unsetColors() +{ + setPaletteForegroundColor( KGlobalSettings::activeTextColor() ); + setPaletteBackgroundColor( KGlobalSettings::activeTitleColor() ); + + refresh(); +} + +void OSDWidget::setOffset( int /*x*/, int y ) +{ + //m_offset = QPoint( x, y ); + m_y = y; + reposition(); +} + +void OSDWidget::setAlignment( Alignment a ) +{ + m_alignment = a; + reposition(); +} + +void OSDWidget::setScreen( uint screen ) +{ + const uint n = QApplication::desktop()->numScreens(); + m_screen = (screen >= n) ? n-1 : (int)screen; + reposition(); +} + +bool OSDWidget::event( QEvent *e ) +{ + switch( e->type() ) + { + case QEvent::Paint: + bitBlt( this, 0, 0, &osdBuffer ); + return true; + + default: + return QWidget::event( e ); + } +} + +void OSDWidget::mousePressEvent( QMouseEvent* ) +{ + hide(); + emit hidden(); +} + +void OSDWidget::show() +{ + // Don't show the OSD widget when the desktop is locked + if ( isKDesktopLockRunning() == Locked ) + { + minReached(); // don't queue the message + return; + } + + if ( m_dirty ) renderOSDText( m_currentText ); + + QWidget::show(); + + if ( m_duration ) //duration 0 -> stay forever + { + timer.start( m_duration, true ); //calls hide() + timerMin.start( 150 ); //calls minReached() + } +} + +void OSDWidget::refresh() +{ + if ( isVisible() ) + { + //we need to update the buffer + renderOSDText( m_currentText ); + } + else m_dirty = true; //ensure we are re-rendered before we are shown +} + +void OSDWidget::reposition( QSize newSize ) +{ + if( !newSize.isValid() ) newSize = size(); + + QPoint newPos( MARGIN, m_y ); + const QRect screen = QApplication::desktop()->screenGeometry( m_screen ); + + //TODO m_y is the middle of the OSD, and don't exceed screen margins + + switch ( m_alignment ) + { + case Left: + break; + + case Right: + newPos.rx() = screen.width() - MARGIN - newSize.width(); + break; + + case Center: + newPos.ry() = (screen.height() - newSize.height()) / 2; + + //FALL THROUGH + + case Middle: + newPos.rx() = (screen.width() - newSize.width()) / 2; + break; + } + + //ensure we don't dip below the screen + if( newPos.y()+newSize.height() > screen.height()-MARGIN ) newPos.ry() = screen.height()-MARGIN-newSize.height(); + + // correct for screen position + newPos += screen.topLeft(); + + //ensure we are painted before we move + if( isVisible() ) paintEvent( 0 ); + + //fancy X11 move+resize, reduces visual artifacts + XMoveResizeWindow( x11Display(), winId(), newPos.x(), newPos.y(), newSize.width(), newSize.height() ); +} + +////// OSDPreviewWidget below ///////////////////// + +#include //previewWidget +#include + +OSDPreviewWidget::OSDPreviewWidget( const QString &appName, QWidget *parent, const char *name ) +: OSDWidget( appName, parent, name ) +, m_dragging( false ) +{ + m_currentText = i18n( "OSD Preview - drag to reposition" ); + m_duration = 0; +} + +void OSDPreviewWidget::mousePressEvent( QMouseEvent *event ) +{ + m_dragOffset = event->pos(); + + if ( event->button() == LeftButton && !m_dragging ) + { + grabMouse( KCursor::sizeAllCursor() ); + m_dragging = true; + } +} + +void OSDPreviewWidget::mouseReleaseEvent( QMouseEvent * /*event*/ ) +{ + if ( m_dragging ) + { + m_dragging = false; + releaseMouse(); + + // compute current Position && offset + QDesktopWidget *desktop = QApplication::desktop(); + int currentScreen = desktop->screenNumber( pos() ); + + if ( currentScreen != -1 ) + { + // set new data + m_screen = currentScreen; + m_y = QWidget::y(); + + emit positionChanged(); + } + } +} + +void OSDPreviewWidget::mouseMoveEvent( QMouseEvent *e ) +{ + if ( m_dragging && this == mouseGrabber() ) + { + const QRect screen = QApplication::desktop()->screenGeometry( m_screen ); + const uint hcenter = screen.width() / 2; + const uint eGlobalPosX = e->globalPos().x() - screen.left(); + const uint snapZone = screen.width() / 8; + + QPoint destination = e->globalPos() - m_dragOffset - screen.topLeft(); + int maxY = screen.height() - height() - MARGIN; + if( destination.y() < MARGIN ) destination.ry() = MARGIN; + if( destination.y() > maxY ) destination.ry() = maxY; + + if( eGlobalPosX < (hcenter-snapZone) ) + { + m_alignment = Left; + destination.rx() = MARGIN; + } + else if( eGlobalPosX > (hcenter+snapZone) ) + { + m_alignment = Right; + destination.rx() = screen.width() - MARGIN - width(); + } + else + { + const uint eGlobalPosY = e->globalPos().y() - screen.top(); + const uint vcenter = screen.height()/2; + + destination.rx() = hcenter - width()/2; + + if( eGlobalPosY >= (vcenter-snapZone) && eGlobalPosY <= (vcenter+snapZone) ) + { + m_alignment = Center; + destination.ry() = vcenter - height()/2; + } + else m_alignment = Middle; + } + + destination += screen.topLeft(); + + move( destination ); + } +} + +// the code was taken from pilotDaemon.cc in KPilot + // static +OSDWidget::KDesktopLockStatus OSDWidget::isKDesktopLockRunning() +{ + if (!Preferences::oSDCheckDesktopLock()) + return NotLocked; + + DCOPClient *dcopptr = KApplication::kApplication()->dcopClient(); + + // Can't tell, very weird + if (!dcopptr || !dcopptr->isAttached()) + { + kdWarning() << k_funcinfo << ": Could not make DCOP connection." << endl; + return DCOPError; + } + + QByteArray data,returnValue; + QCString returnType; + + if (!dcopptr->call("kdesktop","KScreensaverIface","isBlanked()", + data,returnType,returnValue,true)) + { + // KDesktop is not running. Maybe we are in a KDE4 desktop... + kdDebug() << k_funcinfo << ": Check for screensaver failed." << endl; + return DCOPError; + } + + if (returnType == "bool") + { + bool b; + QDataStream reply(returnValue,IO_ReadOnly); + reply >> b; + return (b ? Locked : NotLocked); + } + else + { + kdWarning() << k_funcinfo << ": Strange return value from screensaver. " + << "Assuming screensaver is active." << endl; + // Err on the side of safety. + return Locked; + } +} + +#include "osd.moc" diff --git a/konversation/src/osd.h b/konversation/src/osd.h new file mode 100644 index 0000000..997162b --- /dev/null +++ b/konversation/src/osd.h @@ -0,0 +1,124 @@ +/* + 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. +*/ + +/* + Provides an interface to a plain QWidget, which is independent of KDE (bypassed to X11) + begin: Fre Sep 26 2003 + Copyright (C) 2003 Christian Muehlhaeuser + Copyright (C) 2004 Michael Goettsche +*/ + +#ifndef OSD_H +#define OSD_H + +#include //stack allocated +#include //stack allocated +#include //baseclass + + +class QFont; +class QString; +class QStringList; +class QTimer; +class MetaBundle; + +class OSDWidget : public QWidget +{ + Q_OBJECT + + public: + enum Alignment { Left, Middle, Center, Right }; + + explicit OSDWidget(const QString &appName, QWidget *parent = 0, const char *name = "osd"); + void setDuration(int ms); + void setFont(QFont newfont); + void setShadow(bool shadow); + void setTextColor(const QColor &newcolor); + void setBackgroundColor(const QColor &newColor); + void setOffset( int x, int y ); + void setAlignment(Alignment); + void setScreen(uint screen); + void setText(const QString &text) { m_currentText = text; refresh(); } + + void unsetColors(); + + int screen() { return m_screen; } + int alignment() { return m_alignment; } + int y() { return m_y; } + + signals: + void hidden(); + + public slots: + //TODO rename show, scrap removeOSD, just use hide() <- easier to learn + void showOSD(const QString&, bool preemptive=false ); + void removeOSD() //inlined as is convenience function + { + hide(); + } + + protected slots: + void minReached(); + + protected: + /* render text into osdBuffer */ + void renderOSDText(const QString &text); + void mousePressEvent( QMouseEvent* ); + bool event(QEvent*); + + void show(); + + /* call to reposition a new OSD text or when position attributes change */ + void reposition( QSize newSize = QSize() ); + + /* called after most set*() calls to update the OSD */ + void refresh(); + + enum KDesktopLockStatus { NotLocked=0, Locked=1, DCOPError=2 }; + static KDesktopLockStatus isKDesktopLockRunning(); + + static const int MARGIN = 15; + + QString m_appName; + int m_duration; + QTimer timer; + QTimer timerMin; + QPixmap osdBuffer; + QStringList textBuffer; + QString m_currentText; + bool m_shadow; + + Alignment m_alignment; + int m_screen; + uint m_y; + + bool m_dirty; //if dirty we will be re-rendered before we are shown +}; + +// do not pollute OSDWidget with this preview stuff +class OSDPreviewWidget : public OSDWidget +{ + Q_OBJECT + + public: + explicit OSDPreviewWidget( const QString &appName, QWidget *parent = 0, const char *name = "osdpreview" ); + + static QPoint m_previewOffset; + + signals: + void positionChanged(); + + protected: + void mousePressEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + void mouseMoveEvent( QMouseEvent * ); + + private: + bool m_dragging; + QPoint m_dragOffset; +}; +#endif /*OSD_H*/ diff --git a/konversation/src/osd_preferences.cpp b/konversation/src/osd_preferences.cpp new file mode 100644 index 0000000..49f223d --- /dev/null +++ b/konversation/src/osd_preferences.cpp @@ -0,0 +1,190 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 Ivor Hewitt + Copyright (C) 2005 Ismail Donmez + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006 John Tapsell + Copyright (C) 2006 Peter Simonsson +*/ + +#include "osd_preferences.h" +#include "config/preferences.h" +#include "osd.h" +#include "konversationapplication.h" + +#include +#include +#include +#include +#include +#include + +#include + + +OSD_Config::OSD_Config( QWidget* parent, const char* name, WFlags fl ) + : OSD_ConfigUI( parent, name, fl ) +{ + bool enableScreenChooser = false; + QRect screenRect; + + for(int i = 0; i < QApplication::desktop()->numScreens(); ++i) { + kcfg_OSDScreen->insertItem(QString::number(i)); + screenRect = QApplication::desktop()->screenGeometry(i); + + //Check if we're using xinerama or not + if(screenRect.left() != 0 || screenRect.top() != 0) { + enableScreenChooser = true; + } + } + + kcfg_OSDScreen->setEnabled(enableScreenChooser); + + m_pOSDPreview = new OSDPreviewWidget("Konversation"); + connect(m_pOSDPreview, SIGNAL(positionChanged()), this, SLOT(slotPositionChanged())); + + connect( kcfg_OSDFont, SIGNAL(fontSelected(const QFont&)), this, SLOT(slotUpdateFont(const QFont&))); + + slotOSDEnabledChanged(kcfg_UseOSD->isChecked()); + slotCustomColorsChanged(kcfg_OSDUseCustomColors->isChecked()); + slotScreenChanged(Preferences::oSDScreen()); + slotDrawShadowChanged( kcfg_OSDDrawShadow->isChecked()); + slotUpdateFont(Preferences::oSDFont()); + + kcfg_OSDOffsetX->hide(); + kcfg_OSDOffsetY->hide(); + kcfg_OSDAlignment->hide(); + + //Connect config page entries to control the OSDPreview + connect ( kcfg_UseOSD, SIGNAL( toggled( bool ) ), this, SLOT( slotOSDEnabledChanged(bool) ) ); + connect ( kcfg_OSDUseCustomColors, SIGNAL(toggled(bool)), this, SLOT(slotCustomColorsChanged(bool))); + connect ( kcfg_OSDTextColor, SIGNAL(changed(const QColor&)), this, SLOT(slotTextColorChanged(const QColor&))); + connect ( kcfg_OSDBackgroundColor, SIGNAL(changed(const QColor&)), this, SLOT(slotBackgroundColorChanged(const QColor&))); + connect ( kcfg_OSDScreen, SIGNAL(activated(int)), this, SLOT(slotScreenChanged(int))); + connect ( kcfg_OSDDrawShadow, SIGNAL(toggled(bool)), this, SLOT(slotDrawShadowChanged(bool))); +} + +OSD_Config::~OSD_Config() +{ + delete m_pOSDPreview; +} + +void OSD_Config::loadSettings() +{ +} + +void OSD_Config::restorePageToDefaults() +{ +} + +void OSD_Config::saveSettings() +{ + //Update the current OSD. + KonversationApplication *konvApp=static_cast(KApplication::kApplication()); + + konvApp->osd->setEnabled(kcfg_UseOSD->isChecked()); + if (kcfg_UseOSD->isChecked()) + { + konvApp->osd->setFont(Preferences::oSDFont()); + if(kcfg_OSDUseCustomColors->isChecked()) + { + konvApp->osd->setTextColor(kcfg_OSDTextColor->color()); + konvApp->osd->setBackgroundColor(kcfg_OSDBackgroundColor->color()); + } + else + { + konvApp->osd->unsetColors(); + } + + konvApp->osd->setDuration(kcfg_OSDDuration->value()); + konvApp->osd->setScreen(kcfg_OSDScreen->currentItem()); + konvApp->osd->setShadow(kcfg_OSDDrawShadow->isChecked()); + + //x is ignored anyway, but leave incase we use in future + konvApp->osd->setOffset(kcfg_OSDOffsetX->value(), kcfg_OSDOffsetY->value()); + konvApp->osd->setAlignment((OSDWidget::Alignment)kcfg_OSDAlignment->value()); + } + +} + +void OSD_Config::showEvent(QShowEvent*) +{ + //Update the preview + m_pOSDPreview->setAlignment((OSDWidget::Alignment)( kcfg_OSDAlignment->value() ) ); + m_pOSDPreview->setOffset(kcfg_OSDOffsetX->value(),kcfg_OSDOffsetY->value()); + + m_pOSDPreview->setShown(kcfg_UseOSD->isChecked()); +} + +void OSD_Config::hideEvent(QHideEvent*) +{ + m_pOSDPreview->setShown(false); +} + +bool OSD_Config::hasChanged() +{ + // follow the interface, no Non-KConfigXT settings here, so none have changed + return false; +} + +void OSD_Config::slotOSDEnabledChanged(bool on) +{ + if ( isVisible() ) + m_pOSDPreview->setShown(on); +} + +void OSD_Config::slotPositionChanged() +{ + kcfg_OSDScreen->setCurrentItem(m_pOSDPreview->screen()); + + kcfg_OSDAlignment->setValue( m_pOSDPreview->alignment() ); + kcfg_OSDOffsetX->setValue( m_pOSDPreview->x()); + kcfg_OSDOffsetY->setValue( m_pOSDPreview->y()); +} + + +void OSD_Config::slotCustomColorsChanged(bool on) +{ + if(on) + { + m_pOSDPreview->setTextColor(kcfg_OSDTextColor->color()); + m_pOSDPreview->setBackgroundColor(kcfg_OSDBackgroundColor->color()); + } + else + m_pOSDPreview->unsetColors(); +} +void OSD_Config::slotTextColorChanged(const QColor& color) +{ + if(kcfg_OSDUseCustomColors->isChecked()) + m_pOSDPreview->setTextColor(color); +} + +void OSD_Config::slotBackgroundColorChanged(const QColor& color) +{ + if(kcfg_OSDUseCustomColors->isChecked()) + m_pOSDPreview->setBackgroundColor(color); +} + +void OSD_Config::slotScreenChanged(int index) +{ + m_pOSDPreview->setScreen(index); +} + +void OSD_Config::slotDrawShadowChanged(bool on) +{ + m_pOSDPreview->setShadow(on); +} + +void OSD_Config::slotUpdateFont(const QFont& font) +{ + m_pOSDPreview->setFont(font); +} + +#include "osd_preferences.moc" + diff --git a/konversation/src/osd_preferences.h b/konversation/src/osd_preferences.h new file mode 100644 index 0000000..fe7c38e --- /dev/null +++ b/konversation/src/osd_preferences.h @@ -0,0 +1,57 @@ +/* + 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. +*/ + +/* + Copyright (C) 2005 Ivor Hewitt + Copyright (C) 2005 Ismail Donmez + Copyright (C) 2006 Dario Abatianni + Copyright (C) 2006 John Tapsell + Copyright (C) 2006 Peter Simonsson +*/ + +#ifndef EXOSDPREFERENCES_H +#define EXOSDPREFERENCES_H + +#include "osd_preferencesui.h" +#include "konvisettingspage.h" + + +class OSDPreviewWidget; + +class OSD_Config : public OSD_ConfigUI, public KonviSettingsPage +{ + Q_OBJECT + + public: + explicit OSD_Config( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~OSD_Config(); + + virtual void restorePageToDefaults(); + virtual void saveSettings(); + virtual void loadSettings(); + + virtual bool hasChanged(); // implement the interface, will not be used here, though + + protected slots: + void slotOSDEnabledChanged(bool on); + void slotCustomColorsChanged(bool on); + void slotTextColorChanged(const QColor& color); + void slotBackgroundColorChanged(const QColor& color); + void slotScreenChanged(int index); + void slotDrawShadowChanged(bool on); + void slotUpdateFont(const QFont& font); + void slotPositionChanged(); + + protected: + void showEvent(QShowEvent* event); + void hideEvent(QHideEvent* event); + + private: + OSDPreviewWidget* m_pOSDPreview; +}; + +#endif // EXOSDPREFERENCES_H diff --git a/konversation/src/osd_preferencesui.ui b/konversation/src/osd_preferencesui.ui new file mode 100644 index 0000000..3d44f1d --- /dev/null +++ b/konversation/src/osd_preferencesui.ui @@ -0,0 +1,424 @@ + +OSD_ConfigUI + + + OSD_ConfigUI + + + + 0 + 0 + 444 + 442 + + + + + unnamed + + + 0 + + + + spacer1 + + + Vertical + + + Expanding + + + + 21 + 10 + + + + + + kcfg_UseOSD + + + &Enable On Screen Display + + + + + groupBox2 + + + false + + + On &Screen Display + + + + unnamed + + + + kcfg_OSDDrawShadow + + + false + + + &Draw shadows + + + + + textLabel1 + + + false + + + Sunken + + + OSD font: + + + kFontRequester1 + + + + + kcfg_OSDFont + + + false + + + + + kcfg_OSDOffsetX + + + + 4 + 4 + 0 + 0 + + + + 2048 + + + -2048 + + + + + kcfg_OSDOffsetY + + + + 4 + 4 + 0 + 0 + + + + 2048 + + + -2048 + + + + + kcfg_OSDAlignment + + + + 4 + 4 + 0 + 0 + + + + + + + + groupBox3 + + + false + + + Show &OSD Message + + + + unnamed + + + + kcfg_OSDShowOwnNick + + + &If own nick appears in channel message + + + + + kcfg_OSDShowChannel + + + On an&y channel message + + + + + kcfg_OSDShowQuery + + + On &query activity + + + + + kcfg_OSDShowChannelEvent + + + On &Join/Part events + + + + + + + kcfg_OSDUseCustomColors + + + false + + + Enable Custom Colors + + + true + + + false + + + + unnamed + + + + textLabel2 + + + Te&xt color: + + + kcfg_OSDTextColor + + + + + textLabel3 + + + &Background color: + + + kcfg_OSDBackgroundColor + + + + + kcfg_OSDBackgroundColor + + + + + + + + kcfg_OSDTextColor + + + + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 50 + 31 + + + + + + + + groupBox4 + + + false + + + O&ther Settings + + + + unnamed + + + + textLabel1_2 + + + &Duration: + + + kcfg_OSDDuration + + + + + textLabel2_2 + + + S&creen: + + + kcfg_OSDScreen + + + + + kcfg_OSDDuration + + + ms + + + 10000 + + + 500 + + + 100 + + + + + kcfg_OSDScreen + + + + + spacer3 + + + Horizontal + + + Expanding + + + + 50 + 21 + + + + + + + + + + kcfg_UseOSD + toggled(bool) + kcfg_OSDDrawShadow + setEnabled(bool) + + + kcfg_UseOSD + toggled(bool) + groupBox3 + setEnabled(bool) + + + kcfg_UseOSD + toggled(bool) + kcfg_OSDUseCustomColors + setEnabled(bool) + + + kcfg_UseOSD + toggled(bool) + groupBox4 + setEnabled(bool) + + + kcfg_UseOSD + toggled(bool) + textLabel1 + setEnabled(bool) + + + kcfg_UseOSD + toggled(bool) + kcfg_OSDFont + setEnabled(bool) + + + kcfg_UseOSD + toggled(bool) + groupBox2 + setEnabled(bool) + + + + kcfg_UseOSD + kcfg_OSDDrawShadow + kcfg_OSDFont + kcfg_OSDOffsetX + kcfg_OSDOffsetY + kcfg_OSDAlignment + kcfg_OSDShowOwnNick + kcfg_OSDShowChannel + kcfg_OSDShowQuery + kcfg_OSDShowChannelEvent + kcfg_OSDUseCustomColors + kcfg_OSDTextColor + kcfg_OSDBackgroundColor + kcfg_OSDDuration + kcfg_OSDScreen + kcfg_OSDUseCustomColors + + + + + kcombobox.h + kcolorbutton.h + kcolorbutton.h + kfontrequester.h + + diff --git a/konversation/src/outputfilter.cpp b/konversation/src/outputfilter.cpp new file mode 100644 index 0000000..40823e2 --- /dev/null +++ b/konversation/src/outputfilter.cpp @@ -0,0 +1,1790 @@ +/* + 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. +*/ + +/* + Copyright (C) 2002 Dario Abatianni + Copyright (C) 2005 Ismail Donmez + Copyright (C) 2005 Peter Simonsson + Copyright (C) 2005 John Tapsell + Copyright (C) 2005-2008 Eike Hein +*/ + +#include "outputfilter.h" +#include "konversationapplication.h" +#include "konversationmainwindow.h" +#include "awaymanager.h" +#include "ignore.h" +#include "server.h" +#include "irccharsets.h" +#include "linkaddressbook/addressbook.h" +#include "query.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Konversation +{ + OutputFilter::OutputFilter(Server* server) + : QObject(server) + { + m_server = server; + } + + OutputFilter::~OutputFilter() + { + } + + // replace all aliases in the string and return true if anything got replaced at all + bool OutputFilter::replaceAliases(QString& line) + { + QStringList aliasList=Preferences::aliasList(); + QString cc(Preferences::commandChar()); + // check if the line starts with a defined alias + for(unsigned int index=0;index" as "%%" + aliasReplace.replace("%\x01","%%"); + // modify line + line=aliasReplace; + // return "replaced" + return true; + } + } // for + + return false; + } + + QStringList OutputFilter::splitForEncoding(const QString& inputLine, uint max) + { + uint sublen = 0; //The encoded length since the last split + int charLength = 0; //the length of this char + int lastBreakPoint = 0; + + //FIXME should we run this through the encoder first, checking with "canEncode"? + QString text = inputLine; // the text we'll send, currently in Unicode + QStringList finals; // The strings we're going to output + + QString channelCodecName=Preferences::channelEncoding(m_server->getDisplayName(), destination); + //Get the codec we're supposed to use. This must not fail. (not verified) + QTextCodec* codec; + + // I copied this bit straight out of Server::send + if (channelCodecName.isEmpty()) + { + codec = m_server->getIdentity()->getCodec(); + } + else + { + codec = Konversation::IRCCharsets::self()->codecForName(channelCodecName); + } + + Q_ASSERT(codec); + int index = 0; + + while(text.length() > max) + { + // The most important bit - turn the current char into a QCString so we can measure it + QCString ch = codec->fromUnicode(QString(text[index])); + charLength = ch.length(); + + // If adding this char puts us over the limit: + if (charLength + sublen > max) + { + if(lastBreakPoint != 0) + { + finals.append(text.left(lastBreakPoint + 1)); + text = text.mid(lastBreakPoint + 1); + } + else + { + finals.append(text.left(index)); + text = text.mid(index); + } + + lastBreakPoint = 0; + sublen = 0; + index = 0; + } + else if (text[index].isSpace() || text[index].isPunct()) + { + lastBreakPoint = index; + } + + ++index; + sublen += charLength; + } + + if (!text.isEmpty()) + { + finals.append(text); + } + + return finals; + } + + OutputFilterResult OutputFilter::parse(const QString& myNick,const QString& originalLine,const QString& name) + { + setCommandChar(); + + OutputFilterResult result; + destination=name; + + QString inputLine(originalLine); + + if(inputLine.isEmpty() || inputLine == "\n") + return result; + + //Protect against nickserv auth being sent as a message on the off chance + // someone didn't notice leading spaces + { + QString testNickServ( inputLine.stripWhiteSpace() ); + if(testNickServ.startsWith(commandChar+"nickserv", false) + || testNickServ.startsWith(commandChar+"ns", false)) + { + inputLine = testNickServ; + } + } + + if(!Preferences::disableExpansion()) + { + // replace placeholders + inputLine.replace("%%","%\x01"); // make sure to protect double %% + inputLine.replace("%B","\x02"); // replace %B with bold char + inputLine.replace("%C","\x03"); // replace %C with color char + inputLine.replace("%G","\x07"); // replace %G with ASCII BEL 0x07 + inputLine.replace("%I","\x09"); // replace %I with italics char + inputLine.replace("%O","\x0f"); // replace %O with reset to default char + inputLine.replace("%S","\x13"); // replace %S with strikethru char + // inputLine.replace(QRegExp("%?"),"\x15"); + inputLine.replace("%R","\x16"); // replace %R with reverse char + inputLine.replace("%U","\x1f"); // replace %U with underline char + inputLine.replace("%\x01","%"); // restore double %% as single % + } + + QString line=inputLine.lower(); + + // Convert double command chars at the beginning to single ones + if(line.startsWith(commandChar+commandChar) && !destination.isEmpty()) + { + inputLine=inputLine.mid(1); + goto BYPASS_COMMAND_PARSING; + } + // Server command? + else if(line.startsWith(commandChar)) + { + QString command = inputLine.section(' ', 0, 0).mid(1).lower(); + QString parameter = inputLine.section(' ', 1); + + if (command !="topic") + parameter = parameter.stripWhiteSpace(); + + if (command == "join") result = parseJoin(parameter); + else if(command == "part") result = parsePart(parameter); + else if(command == "leave") result = parsePart(parameter); + else if(command == "quit") result = parseQuit(parameter); + else if(command == "close") result = parseClose(parameter); + else if(command == "notice") result = parseNotice(parameter); + else if(command == "j") result = parseJoin(parameter); + else if(command == "me") result = parseMe(parameter, destination); + else if(command == "msg") result = parseMsg(myNick,parameter, false); + else if(command == "m") result = parseMsg(myNick,parameter, false); + else if(command == "smsg") result = parseSMsg(parameter); + else if(command == "query") result = parseMsg(myNick,parameter, true); + else if(command == "op") result = parseOp(parameter); + else if(command == "deop") result = parseDeop(myNick,parameter); + else if(command == "hop") result = parseHop(parameter); + else if(command == "dehop") result = parseDehop(myNick,parameter); + else if(command == "voice") result = parseVoice(parameter); + else if(command == "unvoice") result = parseUnvoice(myNick,parameter); + else if(command == "devoice") result = parseUnvoice(myNick,parameter); + else if(command == "ctcp") result = parseCtcp(parameter); + else if(command == "ping") result = parseCtcp(parameter.section(' ', 0, 0) + " ping"); + else if(command == "kick") result = parseKick(parameter); + else if(command == "topic") result = parseTopic(parameter); + else if(command == "away") parseAway(parameter); + else if(command == "unaway") parseBack(); + else if(command == "back") parseBack(); + else if(command == "invite") result = parseInvite(parameter); + else if(command == "exec") result = parseExec(parameter); + else if(command == "notify") result = parseNotify(parameter); + else if(command == "oper") result = parseOper(myNick,parameter); + else if(command == "ban") result = parseBan(parameter); + else if(command == "unban") result = parseUnban(parameter); + else if(command == "kickban") result = parseBan(parameter,true); + else if(command == "ignore") result = parseIgnore(parameter); + else if(command == "unignore") result = parseUnignore(parameter); + else if(command == "quote") result = parseQuote(parameter); + else if(command == "say") result = parseSay(parameter); + else if(command == "list") result = parseList(parameter); + else if(command == "names") result = parseNames(parameter); + else if(command == "raw") result = parseRaw(parameter); + else if(command == "dcc") result = parseDcc(parameter); + else if(command == "konsole") parseKonsole(); + else if(command == "aaway") KonversationApplication::instance()->getAwayManager()->requestAllAway(parameter); + else if(command == "aunaway") KonversationApplication::instance()->getAwayManager()->requestAllUnaway(); + else if(command == "aback") KonversationApplication::instance()->getAwayManager()->requestAllUnaway(); + else if(command == "ame") result = parseAme(parameter); + else if(command == "amsg") result = parseAmsg(parameter); + else if(command == "omsg") result = parseOmsg(parameter); + else if(command == "onotice") result = parseOnotice(parameter); + else if(command == "server") parseServer(parameter); + else if(command == "reconnect") emit reconnectServer(); + else if(command == "disconnect") emit disconnectServer(); + else if(command == "charset") result = parseCharset(parameter); + else if(command == "encoding") result = parseCharset(parameter); + else if(command == "setkey") result = parseSetKey(parameter); + else if(command == "delkey") result = parseDelKey(parameter); + else if(command == "showkey") result = parseShowKey(parameter); + else if(command == "dns") result = parseDNS(parameter); + else if(command == "kill") result = parseKill(parameter); + else if(command == "queuetuner") result = parseShowTuner(parameter); + + // Forward unknown commands to server + else + { + result.toServer = inputLine.mid(1); + result.type = Message; + } + } + // Ordinary message to channel/query? + else if(!destination.isEmpty()) + { + BYPASS_COMMAND_PARSING: + + QStringList outputList=splitForEncoding(inputLine, m_server->getPreLength("PRIVMSG", destination)); + if (outputList.count() > 1) + { + result.output=QString(); + result.outputList=outputList; + for ( QStringList::Iterator it = outputList.begin(); it != outputList.end(); ++it ) + { + result.toServerList += "PRIVMSG " + destination + " :" + *it; + } + } + else + { + result.output = inputLine; + result.toServer = "PRIVMSG " + destination + " :" + inputLine; + } + + result.type = Message; + } + // Eveything else goes to the server unchanged + else + { + result.toServer = inputLine; + result.output = inputLine; + result.typeString = i18n("Raw"); + result.type = Program; + } + + return result; + } + + OutputFilterResult OutputFilter::parseShowTuner(const QString ¶meter) + { + KonversationApplication *konvApp = static_cast(KApplication::kApplication()); + OutputFilterResult result; + + if(parameter.isEmpty() || parameter == "on") + konvApp->showQueueTuner(true); + else if(parameter == "off") + konvApp->showQueueTuner(false); + else + result = usage(i18n("Usage: %1queuetuner [on | off]").arg(commandChar)); + + return result; + } + + OutputFilterResult OutputFilter::parseOp(const QString ¶meter) + { + return changeMode(parameter,'o','+'); + } + + OutputFilterResult OutputFilter::parseDeop(const QString &ownNick, const QString ¶meter) + { + return changeMode(addNickToEmptyNickList(ownNick,parameter),'o','-'); + } + + OutputFilterResult OutputFilter::parseHop(const QString ¶meter) + { + return changeMode(parameter, 'h', '+'); + } + + OutputFilterResult OutputFilter::parseDehop(const QString &ownNick, const QString ¶meter) + { + return changeMode(addNickToEmptyNickList(ownNick,parameter), 'h', '-'); + } + + OutputFilterResult OutputFilter::parseVoice(const QString ¶meter) + { + return changeMode(parameter,'v','+'); + } + + OutputFilterResult OutputFilter::parseUnvoice(const QString &ownNick, const QString ¶meter) + { + return changeMode(addNickToEmptyNickList(ownNick,parameter),'v','-'); + } + + OutputFilterResult OutputFilter::parseJoin(QString& channelName) + { + OutputFilterResult result; + + if(channelName.contains(",")) // Protect against #foo,0 tricks + channelName = channelName.remove(",0"); + //else if(channelName == "0") // FIXME IRC RFC 2812 section 3.2.1 + + if (channelName.isEmpty()) + { + if (destination.isEmpty() || !isAChannel(destination)) + return usage(i18n("Usage: %1JOIN [password]").arg(commandChar)); + channelName=destination; + } + else if (!isAChannel(channelName)) + channelName = "#" + channelName.stripWhiteSpace(); + + Channel* channel = m_server->getChannelByName(channelName); + + if (channel) + { + // Note that this relies on the channels-flush-nicklists-on-disconnect behavior. + if (!channel->numberOfNicks()) + result.toServer = "JOIN " + channelName; + + if (channel->joined()) emit showView (channel); + } + else + result.toServer = "JOIN " + channelName; + + return result; + } + + OutputFilterResult OutputFilter::parseKick(const QString ¶meter) + { + OutputFilterResult result; + + if(isAChannel(destination)) + { + // get nick to kick + QString victim = parameter.left(parameter.find(" ")); + + if(victim.isEmpty()) + { + result = usage(i18n("Usage: %1KICK [reason]").arg(commandChar)); + } + else + { + // get kick reason (if any) + QString reason = parameter.mid(victim.length() + 1); + + // if no reason given, take default reason + if(reason.isEmpty()) + { + reason = m_server->getIdentity()->getKickReason(); + } + + result.toServer = "KICK " + destination + ' ' + victim + " :" + reason; + } + } + else + { + result = error(i18n("%1KICK only works from within channels.").arg(commandChar)); + } + + return result; + } + + OutputFilterResult OutputFilter::parsePart(const QString ¶meter) + { + OutputFilterResult result; + + // No parameter, try default part message + if(parameter.isEmpty()) + { + // But only if we actually are in a channel + if(isAChannel(destination)) + { + result.toServer = "PART " + destination + " :" + m_server->getIdentity()->getPartReason(); + } + else + { + result = error(i18n("%1PART without parameters only works from within a channel or a query.").arg(commandChar)); + } + } + else + { + // part a given channel + if(isAChannel(parameter)) + { + // get channel name + QString channel = parameter.left(parameter.find(" ")); + // get part reason (if any) + QString reason = parameter.mid(channel.length() + 1); + + // if no reason given, take default reason + if(reason.isEmpty()) + { + reason = m_server->getIdentity()->getPartReason(); + } + + result.toServer = "PART " + channel + " :" + reason; + } + // part this channel with a given reason + else + { + if(isAChannel(destination)) + { + result.toServer = "PART " + destination + " :" + parameter; + } + else + { + result = error(i18n("%1PART without channel name only works from within a channel.").arg(commandChar)); + } + } + } + + return result; + } + + OutputFilterResult OutputFilter::parseTopic(const QString ¶meter) + { + OutputFilterResult result; + + // No parameter, try to get current topic + if(parameter.isEmpty()) + { + // But only if we actually are in a channel + if(isAChannel(destination)) + { + result.toServer = "TOPIC " + destination; + } + else + { + result = error(i18n("%1TOPIC without parameters only works from within a channel.").arg(commandChar)); + } + } + else + { + // retrieve or set topic of a given channel + if(isAChannel(parameter)) + { + // get channel name + QString channel=parameter.left(parameter.find(" ")); + // get topic (if any) + QString topic=parameter.mid(channel.length()+1); + // if no topic given, retrieve topic + if(topic.isEmpty()) + { + m_server->requestTopic(channel); + } + // otherwise set topic there + else + { + result.toServer = "TOPIC " + channel + " :"; + //If we get passed a ^A as a topic its a sign we should clear the topic. + //Used to be a \n, but those get smashed by QStringList::split and readded later + //Now is not the time to fight with that. FIXME + //If anyone out there *can* actually set the topic to a single ^A, now they have to + //specify it twice to get one. + if (topic =="\x01\x01") + result.toServer += '\x01'; + else if (topic!="\x01") + result.toServer += topic; + + } + } + // set this channel's topic + else + { + if(isAChannel(destination)) + { + result.toServer = "TOPIC " + destination + " :" + parameter; + } + else + { + result = error(i18n("%1TOPIC without channel name only works from within a channel.").arg(commandChar)); + } + } + } + + return result; + } + + void OutputFilter::parseAway(QString& reason) + { + if (reason.isEmpty() && m_server->isAway()) + m_server->requestUnaway(); + else + m_server->requestAway(reason); + } + + void OutputFilter::parseBack() + { + m_server->requestUnaway(); + } + + OutputFilterResult OutputFilter::parseNames(const QString ¶meter) + { + OutputFilterResult result; + result.toServer = "NAMES "; + if (parameter.isNull()) + { + return error(i18n("%1NAMES with no target may disconnect you from the server. Specify '*' if you really want this.").arg(commandChar)); + } + else if (parameter != QChar('*')) + { + result.toServer.append(parameter); + } + return result; + } + + OutputFilterResult OutputFilter::parseClose(QString parm) + { + if (parm.isEmpty()) + parm=destination; + + if (isAChannel(parm) && m_server->getChannelByName(parm)) + m_server->getChannelByName(parm)->closeYourself(false); + else if (m_server->getQueryByName(parm)) + m_server->getQueryByName(parm)->closeYourself(false); + else if (parm.isEmpty()) // this can only mean one thing.. we're in the Server tab + m_server->closeYourself(false); + else + return usage(i18n("Usage: %1close [window] closes the named channel or query tab, or the current tab if none specified.").arg(commandChar)); + return OutputFilterResult(); + } + + OutputFilterResult OutputFilter::parseQuit(const QString &reason) + { + OutputFilterResult result; + + result.toServer = "QUIT :"; + // if no reason given, take default reason + if(reason.isEmpty()) + result.toServer += m_server->getIdentity()->getQuitReason(); + else + result.toServer += reason; + + return result; + } + + OutputFilterResult OutputFilter::parseNotice(const QString ¶meter) + { + OutputFilterResult result; + QString recipient = parameter.left(parameter.find(" ")); + QString message = parameter.mid(recipient.length()+1); + + if(parameter.isEmpty() || message.isEmpty()) + { + result = usage(i18n("Usage: %1NOTICE ").arg(commandChar)); + } + else + { + result.typeString = i18n("Notice"); + result.toServer = "NOTICE " + recipient + " :" + message; + result.output=i18n("%1 is the message, %2 the recipient nickname","Sending notice \"%2\" to %1.").arg(recipient).arg(message); + result.type = Program; + } + + return result; + } + + OutputFilterResult OutputFilter::parseMe(const QString ¶meter, const QString &destination) + { + OutputFilterResult result; + + if (!destination.isEmpty() && !parameter.isEmpty()) + { + result.toServer = "PRIVMSG " + destination + " :" + '\x01' + "ACTION " + parameter + '\x01'; + result.output = parameter; + result.type = Action; + } + else + { + result = usage(i18n("Usage: %1ME text").arg(commandChar)); + } + + return result; + } + + OutputFilterResult OutputFilter::parseMsg(const QString &myNick, const QString ¶meter, bool isQuery) + { + OutputFilterResult result; + QString recipient = parameter.section(" ", 0, 0, QString::SectionSkipEmpty); + QString message = parameter.section(" ", 1); + QString output; + + if (recipient.isEmpty()) + { + result = error("Error: You need to specify a recipient."); + return result; + } + + if (isQuery && m_server->isAChannel(recipient)) + { + result = error("Error: You cannot open queries to channels."); + return result; + } + + if (message.stripWhiteSpace().isEmpty()) + { + //empty result - we don't want to send any message to the server + if (!isQuery) + { + result = error("Error: You need to specify a message."); + return result; + } + } + else if (message.startsWith(commandChar+"me")) + { + result.toServer = "PRIVMSG " + recipient + " :" + '\x01' + "ACTION " + message.mid(4) + '\x01'; + output = QString("* %1 %2").arg(myNick).arg(message.mid(4)); + } + else + { + result.toServer = "PRIVMSG " + recipient + " :" + message; + output = message; + } + + ::Query *query; + + if (isQuery || output.isEmpty()) + { + //if this is a /query, always open a query window. + //treat "/msg nick" as "/query nick" + + //Note we have to be a bit careful here. + //We only want to create ('obtain') a new nickinfo if we have done /query + //or "/msg nick". Not "/msg nick message". + NickInfoPtr nickInfo = m_server->obtainNickInfo(recipient); + query = m_server->addQuery(nickInfo, true /*we initiated*/); + //force focus if the user did not specify any message + if (output.isEmpty()) emit showView(query); + } + else + { + //We have "/msg nick message" + query = m_server->getQueryByName(recipient); + } + + if (query && !output.isEmpty()) + { + if (message.startsWith(commandChar+"me")) + //log if and only if the query open + query->appendAction(m_server->getNickname(), message.mid(4)); + else + //log if and only if the query open + query->appendQuery(m_server->getNickname(), output); + } + + if (output.isEmpty()) return result; //result should be completely empty; + //FIXME - don't do below line if query is focused + result.output = output; + result.typeString= recipient; + result.type = PrivateMessage; + return result; + } + + OutputFilterResult OutputFilter::parseSMsg(const QString ¶meter) + { + OutputFilterResult result; + QString recipient = parameter.left(parameter.find(" ")); + QString message = parameter.mid(recipient.length() + 1); + + if(message.startsWith(commandChar + "me")) + { + result.toServer = "PRIVMSG " + recipient + " :" + '\x01' + "ACTION " + message.mid(4) + '\x01'; + } + else + { + result.toServer = "PRIVMSG " + recipient + " :" + message; + } + + return result; + } + + OutputFilterResult OutputFilter::parseCtcp(const QString ¶meter) + { + OutputFilterResult result; + // who is the recipient? + QString recipient = parameter.section(' ', 0, 0); + // what is the first word of the ctcp? + QString request = parameter.section(' ', 1, 1, QString::SectionSkipEmpty).upper(); + // what is the complete ctcp command? + QString message = parameter.section(' ', 2, 0xffffff, QString::SectionSkipEmpty); + + QString out = request; + if (!message.isEmpty()) + out+= ' ' + message; + + if (request == "PING") + { + unsigned int time_t = QDateTime::currentDateTime().toTime_t(); + result.toServer = QString("PRIVMSG %1 :\x01PING %2\x01").arg(recipient).arg(time_t); + result.output = i18n("Sending CTCP-%1 request to %2.").arg("PING").arg(recipient); + } + else + { + result.toServer = "PRIVMSG " + recipient + " :" + '\x01' + out + '\x01'; + result.output = i18n("Sending CTCP-%1 request to %2.").arg(out).arg(recipient); + } + + result.typeString = i18n("CTCP"); + result.type = Program; + return result; + } + + OutputFilterResult OutputFilter::changeMode(const QString ¶meter,char mode,char giveTake) + { + OutputFilterResult result; + // TODO: Make sure this works with +l and +k also! + QString token; + QString tmpToken; + QStringList nickList = QStringList::split(' ', parameter); + + if(nickList.count()) + { + // Check if the user specified a channel + if(isAChannel(nickList[0])) + { + token = "MODE " + nickList[0]; + // remove the first element + nickList.remove(nickList.begin()); + } + // Add default destination if it is a channel + else if(isAChannel(destination)) + { + token = "MODE " + destination; + } + + // Only continue if there was no error + if(token.length()) + { + unsigned int modeCount = nickList.count(); + QString modes; + modes.fill(mode, modeCount); + + token += QString(" ") + QChar(giveTake) + modes; + tmpToken = token; + + for(unsigned int index = 0; index < modeCount; index++) + { + if((index % 3) == 0) + { + result.toServerList.append(token); + token = tmpToken; + } + token += ' ' + nickList[index]; + } + + if(token != tmpToken) + { + result.toServerList.append(token); + } + } + } + + return result; + } + + OutputFilterResult OutputFilter::parseDcc(const QString ¶meter) + { + OutputFilterResult result; + + // No parameter, just open DCC panel + if(parameter.isEmpty()) + { + emit addDccPanel(); + } + else + { + QString tmpParameter = parameter; + QStringList parameterList = QStringList::split(' ', tmpParameter.replace("\\ ", "%20")); + + QString dccType = parameterList[0].lower(); + + if(dccType=="close") + { + emit closeDccPanel(); + } + else if(dccType=="send") + { + if(parameterList.count()==1) // DCC SEND + { + emit requestDccSend(); + } // DCC SEND + else if(parameterList.count()==2) + { + emit requestDccSend(parameterList[1]); + } // DCC SEND [file] ... + else if(parameterList.count()>2) + { + // TODO: make sure this will work: + //output=i18n("Usage: %1DCC SEND nickname [fi6lename] [filename] ...").arg(commandChar); + KURL fileURL(parameterList[2]); + + //We could easily check if the remote file exists, but then we might + //end up asking for creditionals twice, so settle for only checking locally + if(!fileURL.isLocalFile() || QFile::exists( fileURL.path() )) + { + emit openDccSend(parameterList[1],fileURL); + } + else + { + result = error(i18n("File \"%1\" does not exist.").arg(parameterList[2])); + } + } + else // Don't know how this should happen, but ... + { + result = usage(i18n("Usage: %1DCC [SEND nickname filename]").arg(commandChar)); + } + } + // TODO: DCC Chat etc. comes here + else if(dccType=="chat") + { + if(parameterList.count()==2) + { + emit openDccChat(parameterList[1]); + } + else + { + result = usage(i18n("Usage: %1DCC [CHAT nickname]").arg(commandChar)); + } + } + else + { + result = error(i18n("Unrecognized command %1DCC %2. Possible commands are SEND, CHAT, CLOSE.").arg(commandChar).arg(parameterList[0])); + } + } + + return result; + } + + OutputFilterResult OutputFilter::sendRequest(const QString &recipient,const QString &fileName,const QString &address,const QString &port,unsigned long size) + { + OutputFilterResult result; + QString niftyFileName(fileName); + /*QFile file(fileName); + QFileInfo info(file);*/ + + result.toServer = "PRIVMSG " + recipient + " :" + '\x01' + "DCC SEND " + + fileName + + ' ' + address + ' ' + port + ' ' + QString::number(size) + '\x01'; + + // Dirty hack to avoid printing ""name with spaces.ext"" instead of "name with spaces.ext" + if ((fileName.startsWith("\"")) && (fileName.endsWith("\""))) + niftyFileName = fileName.mid(1, fileName.length()-2); + + return result; + } + + OutputFilterResult OutputFilter::passiveSendRequest(const QString& recipient,const QString &fileName,const QString &address,unsigned long size,const QString &token) + { + OutputFilterResult result; + QString niftyFileName(fileName); + + result.toServer = "PRIVMSG " + recipient + " :" + '\x01' + "DCC SEND " + + fileName + + ' ' + address + " 0 " + QString::number(size) + ' ' + token + '\x01'; + + // Dirty hack to avoid printing ""name with spaces.ext"" instead of "name with spaces.ext" + if ((fileName.startsWith("\"")) && (fileName.endsWith("\""))) + niftyFileName = fileName.mid(1, fileName.length()-2); + + return result; + } + + // Accepting Resume Request + OutputFilterResult OutputFilter::acceptResumeRequest(const QString &recipient,const QString &fileName,const QString &port,int startAt) + { + QString niftyFileName(fileName); + + OutputFilterResult result; + result.toServer = "PRIVMSG " + recipient + " :" + '\x01' + "DCC ACCEPT " + fileName + ' ' + port + + ' ' + QString::number(startAt) + '\x01'; + + // Dirty hack to avoid printing ""name with spaces.ext"" instead of "name with spaces.ext" + if ((fileName.startsWith("\"")) && (fileName.endsWith("\""))) + niftyFileName = fileName.mid(1, fileName.length()-2); + + return result; + } + + OutputFilterResult OutputFilter::resumeRequest(const QString &sender,const QString &fileName,const QString &port,KIO::filesize_t startAt) + { + QString niftyFileName(fileName); + + OutputFilterResult result; + /*QString newFileName(fileName); + newFileName.replace(" ", "_");*/ + result.toServer = "PRIVMSG " + sender + " :" + '\x01' + "DCC RESUME " + fileName + ' ' + port + ' ' + + QString::number(startAt) + '\x01'; + + // Dirty hack to avoid printing ""name with spaces.ext"" instead of "name with spaces.ext" + if ((fileName.startsWith("\"")) && (fileName.endsWith("\""))) + niftyFileName = fileName.mid(1, fileName.length()-2); + + return result; + } + + OutputFilterResult OutputFilter::acceptPassiveSendRequest(const QString& recipient,const QString &fileName,const QString &address,const QString &port,unsigned long size,const QString &token) + { + OutputFilterResult result; + QString niftyFileName(fileName); + + // "DCC SEND" to receive a file sounds weird, but it's ok. + result.toServer = "PRIVMSG " + recipient + " :" + '\x01' + "DCC SEND " + + fileName + + ' ' + address + ' ' + port + ' ' + QString::number(size) + ' ' + token + '\x01'; + + // Dirty hack to avoid printing ""name with spaces.ext"" instead of "name with spaces.ext" + if ((fileName.startsWith("\"")) && (fileName.endsWith("\""))) + niftyFileName = fileName.mid(1, fileName.length()-2); + + return result; + } + + OutputFilterResult OutputFilter::parseInvite(const QString ¶meter) + { + OutputFilterResult result; + + if(parameter.isEmpty()) + { + result = usage(i18n("Usage: %1INVITE [channel]").arg(commandChar)); + } + else + { + QString nick = parameter.section(' ', 0, 0, QString::SectionSkipEmpty); + QString channel = parameter.section(' ', 1, 1, QString::SectionSkipEmpty); + + if(channel.isEmpty()) + { + if(isAChannel(destination)) + { + channel = destination; + } + else + { + result = error(i18n("%1INVITE without channel name works only from within channels.").arg(commandChar)); + } + } + + if(!channel.isEmpty()) + { + if(isAChannel(channel)) + { + result.toServer = "INVITE " + nick + ' ' + channel; + } + else + { + result = error(i18n("%1 is not a channel.").arg(channel)); + } + } + } + + return result; + } + + OutputFilterResult OutputFilter::parseExec(const QString& parameter) + { + OutputFilterResult result; + + if(parameter.isEmpty()) + { + result = usage(i18n("Usage: %1EXEC